protect-scr
Version:
Comprehensive client-side security protection for React applications against screenshots, printing, and unauthorized access
152 lines • 4.96 kB
JavaScript
// src/react/hooks.ts
import { useEffect, useRef, useState, useCallback } from 'react';
import { SecurityManager } from '../core/SecurityManager';
import { getPresetConfig } from '../presets';
export function useSecurityShield(config) {
const securityManagerRef = useRef(null);
const [isEnabled, setIsEnabled] = useState(false);
const configRef = useRef(config);
// Update config ref when config changes
useEffect(() => {
configRef.current = config;
}, [config]);
// Initialize security manager only once
useEffect(() => {
if (securityManagerRef.current)
return; // Already initialized
try {
let finalConfig = {};
if (typeof configRef.current === 'string') {
finalConfig = getPresetConfig(configRef.current);
}
else if (configRef.current) {
finalConfig = configRef.current;
}
securityManagerRef.current = new SecurityManager(finalConfig);
console.log('SecurityManager initialized');
}
catch (error) {
console.error('Failed to initialize SecurityManager:', error);
}
// Cleanup function
return () => {
if (securityManagerRef.current) {
try {
securityManagerRef.current.disable();
securityManagerRef.current = null;
}
catch (error) {
console.error('Cleanup error:', error);
}
}
};
}, []); // Empty dependency array - only run once
const enable = useCallback(() => {
if (securityManagerRef.current && !isEnabled) {
try {
securityManagerRef.current.enable();
setIsEnabled(true);
}
catch (error) {
console.error('Failed to enable security:', error);
}
}
}, [isEnabled]);
const disable = useCallback(() => {
if (securityManagerRef.current && isEnabled) {
try {
securityManagerRef.current.disable();
setIsEnabled(false);
}
catch (error) {
console.error('Failed to disable security:', error);
}
}
}, [isEnabled]);
const updateConfig = useCallback((newConfig) => {
if (securityManagerRef.current) {
try {
securityManagerRef.current.updateConfig(newConfig);
}
catch (error) {
console.error('Failed to update config:', error);
}
}
}, []);
return {
isEnabled,
enable,
disable,
updateConfig
};
}
// Simplified version for other hooks to prevent dependency issues
export function useRouteSecurityShield(routes, config) {
const [currentPath, setCurrentPath] = useState(() => {
if (typeof window !== 'undefined') {
return window.location.pathname;
}
return '/';
});
const [shouldProtect, setShouldProtect] = useState(false);
const { isEnabled, enable, disable } = useSecurityShield(config);
// Monitor route changes
useEffect(() => {
if (typeof window === 'undefined')
return;
const handleRouteChange = () => {
setCurrentPath(window.location.pathname);
};
window.addEventListener('popstate', handleRouteChange);
return () => {
window.removeEventListener('popstate', handleRouteChange);
};
}, []);
// Check if current route should be protected
useEffect(() => {
const isProtectedRoute = routes.some(route => {
if (route.endsWith('*')) {
return currentPath.startsWith(route.slice(0, -1));
}
return currentPath === route || currentPath.startsWith(route + '/');
});
setShouldProtect(isProtectedRoute);
if (isProtectedRoute) {
enable();
}
else {
disable();
}
}, [currentPath, routes, enable, disable]);
return {
isEnabled: isEnabled && shouldProtect,
shouldProtect
};
}
export function useConditionalSecurityShield(condition, config) {
const { isEnabled, enable: baseEnable, disable: baseDisable } = useSecurityShield(config);
useEffect(() => {
if (condition) {
baseEnable();
}
else {
baseDisable();
}
}, [condition, baseEnable, baseDisable]);
return {
isEnabled: isEnabled && condition,
enable: baseEnable,
disable: baseDisable
};
}
export function useSecurityEvents() {
const [events, setEvents] = useState([]);
const clearEvents = useCallback(() => {
setEvents([]);
}, []);
return {
events,
clearEvents
};
}
//# sourceMappingURL=hooks.js.map