UNPKG

protect-scr

Version:

Comprehensive client-side security protection for React applications against screenshots, printing, and unauthorized access

224 lines (223 loc) 8.43 kB
import { DevToolsDetector } from './DevToolsDetector'; import { ScreenshotProtector } from './ScreenshotProtector'; import { KeyboardProtector } from './KeyboardProtector'; import { PrintProtector } from './PrintProtector'; import { WatermarkManager } from './WatermarkManager'; export class SecurityManager { constructor(config = {}) { this.isActive = false; this.eventListeners = []; this.config = this.mergeWithDefaults(config); } mergeWithDefaults(config) { return { disableRightClick: true, disableTextSelection: true, disableKeyboardShortcuts: true, preventScreenshots: true, preventPrinting: true, preventPDFGeneration: true, preventDevTools: true, blurOnFocusLoss: true, showWarningOnProtectedAction: true, customWarningMessage: 'This action is not allowed for security reasons.', devToolsDetectionSensitivity: 'medium', watermark: { enabled: false, text: 'PROTECTED CONTENT', opacity: 0.1, fontSize: 48, color: '#000000', rotation: -45 }, ...config }; } enable() { if (this.isActive) return; this.isActive = true; this.applySecurityMeasures(); } disable() { if (!this.isActive) return; this.isActive = false; this.removeSecurityMeasures(); } updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; if (this.isActive) { this.disable(); this.enable(); } } isEnabled() { return this.isActive; } getConfig() { return { ...this.config }; } applySecurityMeasures() { var _a; // Apply CSS-based protections this.applyCSSProtections(); // Initialize protection modules if (this.config.preventDevTools) { this.devToolsDetector = new DevToolsDetector({ sensitivity: this.config.devToolsDetectionSensitivity, onDetected: this.config.onDevToolsDetected, redirectUrl: this.config.redirectOnDevToolsDetection }); this.devToolsDetector.start(); } if (this.config.preventScreenshots) { this.screenshotProtector = new ScreenshotProtector({ blurOnFocusLoss: this.config.blurOnFocusLoss, onAttempt: this.config.onScreenshotAttempt }); this.screenshotProtector.start(); } if (this.config.disableKeyboardShortcuts) { this.keyboardProtector = new KeyboardProtector({ showWarning: this.config.showWarningOnProtectedAction, warningMessage: this.config.customWarningMessage, onAttempt: this.config.onProtectedActionAttempt }); this.keyboardProtector.start(); } if (this.config.preventPrinting || this.config.preventPDFGeneration) { this.printProtector = new PrintProtector({ preventPrinting: this.config.preventPrinting, preventPDFGeneration: this.config.preventPDFGeneration, showWarning: this.config.showWarningOnProtectedAction }); this.printProtector.start(); } if ((_a = this.config.watermark) === null || _a === void 0 ? void 0 : _a.enabled) { this.watermarkManager = new WatermarkManager(this.config.watermark); this.watermarkManager.show(); } // Mouse and touch protections this.setupMouseProtections(); } applyCSSProtections() { const styleId = 'secure-app-shield-styles'; let styleElement = document.getElementById(styleId); if (!styleElement) { styleElement = document.createElement('style'); styleElement.id = styleId; document.head.appendChild(styleElement); } let css = ''; if (this.config.disableTextSelection) { css += ` body, * { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; -webkit-touch-callout: none !important; -webkit-tap-highlight-color: transparent !important; } `; } if (this.config.preventPrinting) { css += ` @media print { body * { visibility: hidden !important; } body::before { content: "Printing is not allowed" !important; visibility: visible !important; position: absolute !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; font-size: 24px !important; font-weight: bold !important; } } `; } // Add mobile-specific protections css += ` body { -webkit-app-region: no-drag !important; -webkit-user-drag: none !important; -webkit-user-modify: read-only !important; } img, video, canvas, svg { -webkit-user-drag: none !important; -webkit-user-select: none !important; pointer-events: none !important; } `; styleElement.textContent = css; } setupMouseProtections() { if (this.config.disableRightClick) { const contextMenuHandler = (e) => { var _a, _b; e.preventDefault(); e.stopPropagation(); if (this.config.showWarningOnProtectedAction) { this.showWarning('Right-click is disabled'); } (_b = (_a = this.config).onProtectedActionAttempt) === null || _b === void 0 ? void 0 : _b.call(_a, 'right-click'); return false; }; document.addEventListener('contextmenu', contextMenuHandler, true); this.eventListeners.push(() => { document.removeEventListener('contextmenu', contextMenuHandler, true); }); } // Disable drag and drop const dragHandler = (e) => { e.preventDefault(); e.stopPropagation(); return false; }; ['dragstart', 'drag', 'dragenter', 'dragover', 'dragleave', 'drop'].forEach(event => { document.addEventListener(event, dragHandler, true); this.eventListeners.push(() => { document.removeEventListener(event, dragHandler, true); }); }); // Disable text selection via mouse if (this.config.disableTextSelection) { const selectHandler = (e) => { e.preventDefault(); return false; }; document.addEventListener('selectstart', selectHandler, true); this.eventListeners.push(() => { document.removeEventListener('selectstart', selectHandler, true); }); } } removeSecurityMeasures() { var _a, _b, _c, _d, _e; // Remove CSS protections const styleElement = document.getElementById('secure-app-shield-styles'); if (styleElement) { styleElement.remove(); } // Stop protection modules (_a = this.devToolsDetector) === null || _a === void 0 ? void 0 : _a.stop(); (_b = this.screenshotProtector) === null || _b === void 0 ? void 0 : _b.stop(); (_c = this.keyboardProtector) === null || _c === void 0 ? void 0 : _c.stop(); (_d = this.printProtector) === null || _d === void 0 ? void 0 : _d.stop(); (_e = this.watermarkManager) === null || _e === void 0 ? void 0 : _e.hide(); // Remove event listeners this.eventListeners.forEach(removeListener => removeListener()); this.eventListeners = []; } showWarning(message) { if (typeof window !== 'undefined' && typeof window.alert === 'function') { alert(this.config.customWarningMessage || message); } } } //# sourceMappingURL=SecurityManager.js.map