From 960bd39e21b63421aa7b8380c6b13841fd8bc6d6 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 19 Aug 2025 12:09:19 -0600 Subject: [PATCH] Bunch of updates for temp users and logging securely. --- map/README.md | 2 +- map/app/controllers/authController.js | 22 ++++- map/app/controllers/locationsController.js | 8 ++ map/app/controllers/usersController.js | 2 + map/app/public/css/modules/temp-user.css | 26 +++++ map/app/public/index.html | 2 +- map/app/public/js/auth.js | 52 +++++++++- map/app/public/js/location-manager.js | 21 +++- map/app/public/js/main.js | 106 ++++++++++----------- 9 files changed, 170 insertions(+), 71 deletions(-) diff --git a/map/README.md b/map/README.md index d5f676e..57c1c93 100644 --- a/map/README.md +++ b/map/README.md @@ -215,7 +215,7 @@ The build script automatically creates the following table structure: - `Password` (Single Line Text): User password (required) - `Name` (Single Line Text): User display name - `Admin` (Checkbox): Admin privileges -- `UserType` (Single Select): Options: "user" (Blue), "temp" (Orange) - User role type +- `UserType` or `User Type` (Single Select): Options: "user" (Blue), "temp" (Orange) - User role type - `ExpiresAt` (DateTime): Expiration date for temporary users - `ExpireDays` (Number): Number of days until temp user expires - `Created At` (DateTime): Account creation timestamp diff --git a/map/app/controllers/authController.js b/map/app/controllers/authController.js index 1e34d15..ad28084 100644 --- a/map/app/controllers/authController.js +++ b/map/app/controllers/authController.js @@ -52,7 +52,7 @@ class AuthController { } // Check if temp user has expired - const userType = user.UserType || user.userType || 'user'; + const userType = user['User Type'] || user.UserType || user.userType || 'user'; if (userType === 'temp') { const expiration = user.ExpiresAt || user.expiresAt || user.Expiration || user.expiration; if (expiration) { @@ -91,11 +91,23 @@ class AuthController { req.session.userEmail = user.email || user.Email; // Make sure this is set req.session.userName = user.name || user.Name; req.session.isAdmin = user.admin || user.Admin || false; - req.session.userType = user.UserType || user.userType || (req.session.isAdmin ? 'admin' : 'user'); - logger.info('User logged in:', { - email: req.session.userEmail, - admin: req.session.isAdmin + // More explicit userType determination with proper fallback - handle both field name variations + let sessionUserType = 'user'; // default + if (user['User Type']) { + sessionUserType = user['User Type'].toLowerCase(); + } else if (user.UserType) { + sessionUserType = user.UserType.toLowerCase(); + } else if (user.userType) { + sessionUserType = user.userType.toLowerCase(); + } else if (req.session.isAdmin) { + sessionUserType = 'admin'; + } + + req.session.userType = sessionUserType; + + logger.info('User logged in successfully', { + userType: req.session.userType }); // Force session save diff --git a/map/app/controllers/locationsController.js b/map/app/controllers/locationsController.js index 701db40..e5bbb5b 100644 --- a/map/app/controllers/locationsController.js +++ b/map/app/controllers/locationsController.js @@ -334,6 +334,14 @@ class LocationsController { async delete(req, res) { try { + // Check if user is temp and deny delete + if (req.session?.userType === 'temp') { + return res.status(403).json({ + success: false, + error: 'Temporary users cannot delete locations' + }); + } + const locationId = req.params.id; // Validate ID diff --git a/map/app/controllers/usersController.js b/map/app/controllers/usersController.js index 3fefae9..2b389fb 100644 --- a/map/app/controllers/usersController.js +++ b/map/app/controllers/usersController.js @@ -100,6 +100,7 @@ class UsersController { name: name || '', Admin: isAdmin === true, admin: isAdmin === true, + 'User Type': userType || 'user', // Handle space in field name UserType: userType || 'user', userType: userType || 'user', CreatedAt: new Date().toISOString(), @@ -121,6 +122,7 @@ class UsersController { Email: email, Name: name, Admin: isAdmin, + 'User Type': userType, // Handle space in field name UserType: userType, 'Created At': new Date().toISOString(), ExpiresAt: expiresAt diff --git a/map/app/public/css/modules/temp-user.css b/map/app/public/css/modules/temp-user.css index 7390ffc..cf98384 100644 --- a/map/app/public/css/modules/temp-user.css +++ b/map/app/public/css/modules/temp-user.css @@ -28,4 +28,30 @@ a.temp-restricted, body.temp-user a[href="/shifts.html"], body.temp-user .mobile-dropdown-item a[href="/shifts.html"] { display: none !important; +} + +/* Hide delete button for temp users - MOST AGGRESSIVE RULES */ +body.temp-user #delete-location-btn, +body.temp-user .delete-location-btn, +body.temp-user .btn-danger[id*="delete"], +body.temp-user button[id*="delete"], +body.temp-user .form-actions .btn-danger, +body.temp-user .form-actions button[type="button"].btn-danger, +.temp-hidden, +[hidden] { + display: none !important; + visibility: hidden !important; + opacity: 0 !important; + pointer-events: none !important; + position: absolute !important; + left: -9999px !important; + width: 0 !important; + height: 0 !important; + overflow: hidden !important; +} + +/* Hide move location button for temp users */ +body.temp-user .move-location-btn, +body.temp-user #move-location-btn { + display: none !important; } \ No newline at end of file diff --git a/map/app/public/index.html b/map/app/public/index.html index 5515a5e..487645c 100644 --- a/map/app/public/index.html +++ b/map/app/public/index.html @@ -431,7 +431,7 @@

Authenticating...

- Loading map for the first time can take several seconds, even up to a minute. Please be patient. + Loading map can take several seconds, even up to a minute. Please be patient.

diff --git a/map/app/public/js/auth.js b/map/app/public/js/auth.js index aeacdd7..296794e 100644 --- a/map/app/public/js/auth.js +++ b/map/app/public/js/auth.js @@ -25,6 +25,27 @@ export async function checkAuth() { currentUser = data.user; currentUser.userType = data.user.userType || 'user'; // Ensure userType is set + // IMMEDIATE console blocking for all non-admin users - before any other code runs + if (currentUser.userType !== 'admin') { + const noop = () => {}; + setTimeout(() => { + console.log = noop; + console.debug = noop; + console.info = noop; + console.warn = noop; + console.error = noop; + console.trace = noop; + console.dir = noop; + console.dirxml = noop; + console.group = noop; + console.groupEnd = noop; + console.time = noop; + console.timeEnd = noop; + console.assert = noop; + console.profile = noop; + }, 1000); // Give 1 second for initialization logs, then block + } + // Authentication successful - show the app document.body.classList.remove('authenticating'); document.body.classList.add('authenticated'); @@ -43,9 +64,19 @@ export async function checkAuth() { export function updateUserInterface() { if (!currentUser) return; - /* NEW – add a body class we can target with CSS */ - document.body.classList.toggle('temp-user', currentUser.userType === 'temp'); - document.body.classList.toggle('admin-user', currentUser.isAdmin === true); + // CRITICAL: Add body class for temp users FIRST + if (currentUser.userType === 'temp') { + document.body.classList.add('temp-user'); + } else { + document.body.classList.remove('temp-user'); + } + + // Also add admin class for consistency + if (currentUser.isAdmin === true) { + document.body.classList.add('admin-user'); + } else { + document.body.classList.remove('admin-user'); + } // ----- existing code that manipulates DOM ----- // Update user email in both desktop and mobile @@ -119,6 +150,21 @@ export function updateUserInterface() { if (currentUser.isAdmin) { addAdminLinks(); } + + // CRITICAL: Final check to hide delete buttons for temp users + if (currentUser.userType === 'temp') { + // Use setTimeout to ensure this runs after all other DOM operations + setTimeout(() => { + const deleteButtons = document.querySelectorAll('#delete-location-btn, .delete-location-btn, .btn-danger[id*="delete"]'); + deleteButtons.forEach(btn => { + btn.style.display = 'none'; + btn.style.visibility = 'hidden'; + btn.disabled = true; + btn.classList.add('temp-hidden'); + btn.setAttribute('hidden', 'true'); + }); + }, 100); + } } function addAdminLinks() { diff --git a/map/app/public/js/location-manager.js b/map/app/public/js/location-manager.js index c50343d..b66ceba 100644 --- a/map/app/public/js/location-manager.js +++ b/map/app/public/js/location-manager.js @@ -413,13 +413,26 @@ export function openEditForm(location) { document.getElementById('edit-location-lng').value = location.longitude || ''; document.getElementById('edit-geo-location').value = location['Geo-Location'] || ''; - // Show/hide delete button based on user type + // Hide delete button for temp users - use multiple approaches const deleteBtn = document.getElementById('delete-location-btn'); - if (deleteBtn) { - if (currentUser?.userType === 'temp') { + if (deleteBtn) { + // Check both currentUser and body class to ensure restriction + const isTemp = currentUser?.userType === 'temp' || document.body.classList.contains('temp-user'); + + if (isTemp) { deleteBtn.style.display = 'none'; + deleteBtn.style.visibility = 'hidden'; + deleteBtn.disabled = true; + deleteBtn.classList.add('temp-hidden'); + deleteBtn.setAttribute('hidden', 'true'); + // Remove the button from DOM completely for temp users + deleteBtn.remove(); } else { - deleteBtn.style.display = ''; + deleteBtn.style.display = 'inline-block'; + deleteBtn.style.visibility = 'visible'; + deleteBtn.disabled = false; + deleteBtn.classList.remove('temp-hidden'); + deleteBtn.removeAttribute('hidden'); } } diff --git a/map/app/public/js/main.js b/map/app/public/js/main.js index 3639d51..b2002b6 100644 --- a/map/app/public/js/main.js +++ b/map/app/public/js/main.js @@ -37,8 +37,8 @@ document.addEventListener('DOMContentLoaded', async () => { console.log('Authentication confirmed, initializing application...'); - // Setup temp user security measures after authentication - setupTempUserSecurity(); + // Setup temp user security measures immediately after authentication + await setupUserSecurity(); // Then initialize the map updateLoadingMessage('Initializing map...'); @@ -177,63 +177,55 @@ async function initializeUnifiedSearch() { } } -// Setup security measures for temp users -function setupTempUserSecurity() { +// Setup security measures for non-admin users +async function setupUserSecurity() { // Import currentUser from auth module - import('./auth.js').then(authModule => { - const { currentUser } = authModule; + const { currentUser } = await import('./auth.js'); + + if (currentUser?.userType !== 'admin') { + // Override console methods for all non-admin users + const noop = () => {}; + console.log = noop; + console.debug = noop; + console.info = noop; + console.warn = noop; + console.error = noop; + console.trace = noop; + console.dir = noop; + console.dirxml = noop; + console.group = noop; + console.groupEnd = noop; + console.time = noop; + console.timeEnd = noop; + console.assert = noop; + console.profile = noop; + } + + // Additional temp user specific restrictions + if (currentUser?.userType === 'temp') { + // Disable right-click context menu + document.addEventListener('contextmenu', (e) => { + e.preventDefault(); + return false; + }); - if (currentUser?.userType === 'temp') { - console.log('Applying temp user security measures...'); - - // Disable right-click context menu - document.addEventListener('contextmenu', (e) => { + // Disable common keyboard shortcuts for developer tools + document.addEventListener('keydown', (e) => { + // F12 + if (e.keyCode === 123) { e.preventDefault(); return false; - }); - - // Basic developer tools detection - const devtools = { open: false }; - let devtoolsTimer = setInterval(() => { - // Detect if developer tools are open by checking window dimensions - if (window.outerHeight - window.innerHeight > 200 || - window.outerWidth - window.innerWidth > 200) { - if (!devtools.open) { - console.clear(); - console.log('Access to developer tools is restricted for temporary accounts.'); - console.log('Please contact an administrator for full access.'); - } - devtools.open = true; - } else { - devtools.open = false; - } - }, 1000); - - // Clear interval on page unload - window.addEventListener('beforeunload', () => { - if (devtoolsTimer) { - clearInterval(devtoolsTimer); - } - }); - - // Disable common keyboard shortcuts for developer tools - document.addEventListener('keydown', (e) => { - // F12 - if (e.keyCode === 123) { - e.preventDefault(); - return false; - } - // Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+U - if (e.ctrlKey && e.shiftKey && (e.keyCode === 73 || e.keyCode === 74)) { - e.preventDefault(); - return false; - } - // Ctrl+U (view source) - if (e.ctrlKey && e.keyCode === 85) { - e.preventDefault(); - return false; - } - }); - } - }); + } + // Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+U + if (e.ctrlKey && e.shiftKey && (e.keyCode === 73 || e.keyCode === 74)) { + e.preventDefault(); + return false; + } + // Ctrl+U (view source) + if (e.ctrlKey && e.keyCode === 85) { + e.preventDefault(); + return false; + } + }); + } }