Bunch of updates for temp users and logging securely.

This commit is contained in:
admin 2025-08-19 12:09:19 -06:00
parent 3b88eef397
commit 960bd39e21
9 changed files with 170 additions and 71 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -431,7 +431,7 @@
<div class="spinner"></div>
<p>Authenticating...</p>
<p class="loading-patience-message">
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.
</p>
</div>
</div>

View File

@ -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() {

View File

@ -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');
}
}

View File

@ -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;
}
});
}
}