Major Security Improvements:
- Enhanced user fingerprinting with WebGL, Canvas, and Audio fingerprinting - Hardware binding to prevent F5/Ctrl+F5 abuse - Persistent storage across browser sessions (localStorage + sessionStorage) - Global demo session counter with 10 session limit per device - Multi-tab protection (max 2 tabs simultaneously) - Anti-reset protection with hardware mismatch detection Demo Session Protection: - Advanced fingerprint generation with CPU benchmarking - Enhanced validation with cryptographic verification - Automatic cleanup and session completion tracking - Cooldown periods between sessions (1min + 15min completion) - Weekly partial reset of global counters Fixes: - Fixed SessionTimer console spam after connection disconnect - Added missing registerEnhancedDemoSessionUsage method - Corrected method calls from generateUserFingerprint to generateAdvancedUserFingerprint - Implemented proper event handling for connection state changes WebRTC Improvements: - Added peer-disconnect, new-connection, and connection-cleaned events - Enhanced connection cleanup with proper UI notifications - Fixed SessionTimer state management during disconnections - Prevented infinite re-rendering and console logging Performance Optimizations: - Auto-save persistent data every 30 seconds - Periodic cleanup of old session data (every 6 hours) - Memory management for used preimages (10k limit) - Tab heartbeat system for multi-tab detection Testing: - Demo sessions now properly enforce limits - P2P anonymity maintained (no server validation) - Compatible with incognito mode restrictions - Resistant to common abuse techniques
This commit is contained in:
@@ -163,7 +163,7 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('p', {
|
||||
key: 'subtitle',
|
||||
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
||||
}, 'End-to-end freedom. v4.0.02.88')
|
||||
}, 'End-to-end freedom. v4.0.03.00')
|
||||
])
|
||||
]),
|
||||
|
||||
|
||||
@@ -2,12 +2,17 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
const [currentTime, setCurrentTime] = React.useState(timeLeft || 0);
|
||||
const [showExpiredMessage, setShowExpiredMessage] = React.useState(false);
|
||||
const [initialized, setInitialized] = React.useState(false);
|
||||
const [connectionBroken, setConnectionBroken] = React.useState(false);
|
||||
const [connectionBroken, setConnectionBroken] = React.useState(false);
|
||||
|
||||
|
||||
const [loggedHidden, setLoggedHidden] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (connectionBroken) {
|
||||
console.log('⏱️ SessionTimer initialization skipped - connection broken');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ SessionTimer initialization skipped - connection broken');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,17 +28,22 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
|
||||
setCurrentTime(initialTime);
|
||||
setInitialized(true);
|
||||
}, [sessionManager, connectionBroken]);
|
||||
setLoggedHidden(false);
|
||||
}, [sessionManager, connectionBroken]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (connectionBroken) {
|
||||
console.log('⏱️ SessionTimer props update skipped - connection broken');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ SessionTimer props update skipped - connection broken');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeLeft && timeLeft > 0) {
|
||||
setCurrentTime(timeLeft);
|
||||
}
|
||||
setLoggedHidden(false);
|
||||
}, [timeLeft, connectionBroken]);
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -42,7 +52,10 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
}
|
||||
|
||||
if (connectionBroken) {
|
||||
console.log('⏱️ Timer interval skipped - connection broken');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ Timer interval skipped - connection broken');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +63,6 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (connectionBroken) {
|
||||
console.log('⏱️ Timer interval stopped - connection broken');
|
||||
@@ -81,22 +93,18 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [initialized, currentTime, sessionManager, connectionBroken]);
|
||||
|
||||
}, [initialized, currentTime, sessionManager, connectionBroken]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleSessionTimerUpdate = (event) => {
|
||||
|
||||
if (event.detail.timeLeft && event.detail.timeLeft > 0) {
|
||||
setCurrentTime(event.detail.timeLeft);
|
||||
}
|
||||
};
|
||||
|
||||
const handleForceHeaderUpdate = (event) => {
|
||||
|
||||
if (sessionManager && sessionManager.hasActiveSession()) {
|
||||
const newTime = sessionManager.getTimeLeft();
|
||||
setCurrentTime(newTime);
|
||||
@@ -105,28 +113,41 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
|
||||
const handlePeerDisconnect = (event) => {
|
||||
console.log('🔌 Peer disconnect detected in SessionTimer - stopping timer permanently');
|
||||
setConnectionBroken(true);
|
||||
setConnectionBroken(true);
|
||||
setCurrentTime(0);
|
||||
setShowExpiredMessage(false);
|
||||
setLoggedHidden(false);
|
||||
};
|
||||
|
||||
const handleNewConnection = (event) => {
|
||||
console.log('🔌 New connection detected in SessionTimer - resetting connection state');
|
||||
setConnectionBroken(false);
|
||||
setConnectionBroken(false);
|
||||
setLoggedHidden(false);
|
||||
};
|
||||
|
||||
const handleConnectionCleaned = (event) => {
|
||||
console.log('🧹 Connection cleaned - resetting SessionTimer state');
|
||||
setConnectionBroken(false);
|
||||
setCurrentTime(0);
|
||||
setShowExpiredMessage(false);
|
||||
setInitialized(false);
|
||||
setLoggedHidden(false);
|
||||
};
|
||||
|
||||
document.addEventListener('session-timer-update', handleSessionTimerUpdate);
|
||||
document.addEventListener('force-header-update', handleForceHeaderUpdate);
|
||||
document.addEventListener('peer-disconnect', handlePeerDisconnect);
|
||||
document.addEventListener('new-connection', handleNewConnection);
|
||||
document.addEventListener('connection-cleaned', handleConnectionCleaned);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('session-timer-update', handleSessionTimerUpdate);
|
||||
document.removeEventListener('force-header-update', handleForceHeaderUpdate);
|
||||
document.removeEventListener('peer-disconnect', handlePeerDisconnect);
|
||||
document.removeEventListener('new-connection', handleNewConnection);
|
||||
document.removeEventListener('connection-cleaned', handleConnectionCleaned);
|
||||
};
|
||||
}, [sessionManager]);
|
||||
}, [sessionManager]);
|
||||
|
||||
if (showExpiredMessage) {
|
||||
return React.createElement('div', {
|
||||
@@ -145,20 +166,33 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
}
|
||||
|
||||
if (!sessionManager) {
|
||||
console.log('⏱️ SessionTimer hidden - no sessionManager');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ SessionTimer hidden - no sessionManager');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (connectionBroken) {
|
||||
console.log('⏱️ SessionTimer hidden - connection broken');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ SessionTimer hidden - connection broken');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!currentTime || currentTime <= 0) {
|
||||
console.log('⏱️ SessionTimer hidden - no time left');
|
||||
if (!loggedHidden) {
|
||||
console.log('⏱️ SessionTimer hidden - no time left');
|
||||
setLoggedHidden(true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (loggedHidden) {
|
||||
setLoggedHidden(false);
|
||||
}
|
||||
|
||||
const totalMinutes = Math.floor(currentTime / (60 * 1000));
|
||||
const totalSeconds = Math.floor(currentTime / 1000);
|
||||
|
||||
@@ -179,8 +213,8 @@ const SessionTimer = ({ timeLeft, sessionType, sessionManager }) => {
|
||||
};
|
||||
|
||||
const getTimerStyle = () => {
|
||||
const totalDuration = sessionType === 'demo' ? 6 * 60 * 1000 : 60 * 60 * 1000;
|
||||
const timeProgress = (totalDuration - currentTime) / totalDuration;
|
||||
const totalDuration = sessionType === 'demo' ? 6 * 60 * 1000 : 60 * 60 * 1000;
|
||||
const timeProgress = (totalDuration - currentTime) / totalDuration;
|
||||
|
||||
let backgroundColor, textColor, iconColor, iconClass, shouldPulse;
|
||||
|
||||
@@ -247,4 +281,4 @@ window.updateSessionTimer = (newTimeLeft, newSessionType) => {
|
||||
}));
|
||||
};
|
||||
|
||||
console.log('✅ SessionTimer loaded with fixes and improvements');
|
||||
console.log('✅ SessionTimer loaded with anti-spam logging fixes');
|
||||
Reference in New Issue
Block a user