updated temp user control access and limited data send for temps
This commit is contained in:
parent
2ebbb2dc44
commit
2591cfe8a8
@ -44,6 +44,44 @@ class LocationsController {
|
||||
|
||||
logger.info(`Retrieved ${validLocations.length} valid locations out of ${locations.length} total`);
|
||||
|
||||
// Check if user is temp user and limit data accordingly
|
||||
if (req.session?.userType === 'temp') {
|
||||
// For temp users, return limited data but include necessary fields for functionality
|
||||
const limitedLocations = validLocations.map(loc => {
|
||||
const locationId = loc.id || loc.Id || loc.ID || loc._id;
|
||||
return {
|
||||
// Include ID with all possible variants for compatibility
|
||||
id: locationId,
|
||||
Id: locationId,
|
||||
ID: locationId,
|
||||
_id: locationId,
|
||||
'Geo-Location': loc['Geo-Location'],
|
||||
latitude: loc.latitude,
|
||||
longitude: loc.longitude,
|
||||
// Include display fields needed for map functionality
|
||||
'First Name': loc['First Name'] || '',
|
||||
'Last Name': loc['Last Name'] || '', // Include last name for display
|
||||
'Support Level': loc['Support Level'],
|
||||
Address: loc.Address || '',
|
||||
'Unit Number': loc['Unit Number'] || '',
|
||||
Notes: loc.Notes || '',
|
||||
Sign: loc.Sign,
|
||||
'Sign Size': loc['Sign Size'] || '',
|
||||
// Exclude sensitive fields like Email, Phone
|
||||
};
|
||||
});
|
||||
|
||||
logger.info(`Returning limited data for temp user: ${limitedLocations.length} locations`);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
count: limitedLocations.length,
|
||||
total: response.pageInfo?.totalRows || limitedLocations.length,
|
||||
locations: limitedLocations,
|
||||
isLimited: true // Flag to indicate limited data
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
count: validLocations.length,
|
||||
|
||||
@ -40,8 +40,29 @@ const authLimiter = rateLimit({
|
||||
skipSuccessfulRequests: true
|
||||
});
|
||||
|
||||
// Temp user rate limiter - much stricter limits
|
||||
const tempUserLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 10, // Much lower limit for temp users
|
||||
keyGenerator,
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
trustProxy: true,
|
||||
message: 'Too many requests for temporary account. Please contact an administrator for full access.'
|
||||
});
|
||||
|
||||
// Conditional rate limiter that applies stricter limits to temp users
|
||||
const conditionalTempLimiter = (req, res, next) => {
|
||||
if (req.session?.userType === 'temp') {
|
||||
return tempUserLimiter(req, res, next);
|
||||
}
|
||||
return apiLimiter(req, res, next);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
apiLimiter,
|
||||
strictLimiter,
|
||||
authLimiter
|
||||
authLimiter,
|
||||
tempUserLimiter,
|
||||
conditionalTempLimiter
|
||||
};
|
||||
@ -29,15 +29,25 @@ let originalIcon = null;
|
||||
|
||||
export async function loadLocations() {
|
||||
try {
|
||||
showStatus('Loading locations...', 'info');
|
||||
|
||||
const response = await fetch('/api/locations');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
displayLocations(data.locations);
|
||||
updateLocationCount(data.locations.length);
|
||||
} else {
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Failed to load locations');
|
||||
}
|
||||
|
||||
// Check if data is limited (temp user)
|
||||
if (data.isLimited && currentUser?.userType === 'temp') {
|
||||
console.log('Map data loaded'); // Generic message for temp users
|
||||
} else {
|
||||
console.log(`Loaded ${data.count} locations from NocoDB`);
|
||||
}
|
||||
|
||||
displayLocations(data.locations);
|
||||
updateLocationCount(data.locations.length);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading locations:', error);
|
||||
showStatus('Failed to load locations', 'error');
|
||||
@ -91,7 +101,12 @@ export function displayLocations(locations) {
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Displayed ${markers.length} location markers (${locations.length} total locations)`);
|
||||
// Limit console output for temp users
|
||||
if (currentUser?.userType === 'temp') {
|
||||
console.log('Map built successfully');
|
||||
} else {
|
||||
console.log(`Displayed ${markers.length} location markers (${locations.length} total locations)`);
|
||||
}
|
||||
}
|
||||
|
||||
function createLocationMarker(location) {
|
||||
@ -211,7 +226,10 @@ function createLocationMarker(location) {
|
||||
marker.bindPopup(popupContent);
|
||||
marker._locationData = location;
|
||||
|
||||
console.log(`Created marker at ${lat}, ${lng} with color ${markerColor}`);
|
||||
// Only log marker creation for non-temp users
|
||||
if (currentUser?.userType !== 'temp') {
|
||||
console.log(`Created marker at ${lat}, ${lng} with color ${markerColor}`);
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
@ -219,14 +237,45 @@ function createLocationMarker(location) {
|
||||
function createPopupContent(location) {
|
||||
const locationId = location.Id || location.id || location.ID || location._id;
|
||||
|
||||
// If current user is temp, show limited information but allow editing
|
||||
if (currentUser?.userType === 'temp') {
|
||||
const name = [location['First Name'], location['Last Name']]
|
||||
.filter(Boolean).join(' ') || 'Unknown';
|
||||
const address = location.Address || 'No address';
|
||||
const supportLevel = location['Support Level'] ?
|
||||
`Level ${location['Support Level']}` : 'Not specified';
|
||||
|
||||
return `
|
||||
<div class="popup-content">
|
||||
<h3>${escapeHtml(name)}</h3>
|
||||
<p><strong>Address:</strong> ${escapeHtml(address)}</p>
|
||||
<p><strong>Support:</strong> ${escapeHtml(supportLevel)}</p>
|
||||
${location.Sign ? '<p>🏁 Has campaign sign</p>' : ''}
|
||||
${location.Notes ? `<p><strong>Notes:</strong> ${escapeHtml(location.Notes)}</p>` : ''}
|
||||
<div class="popup-meta">
|
||||
<p>ID: ${locationId || 'Unknown'}</p>
|
||||
</div>
|
||||
<div class="popup-actions">
|
||||
<button class="btn btn-primary btn-sm edit-location-popup-btn"
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'>
|
||||
✏️ Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Full information for regular users and admins
|
||||
const name = [location['First Name'], location['Last Name']]
|
||||
.filter(Boolean).join(' ') || 'Unknown';
|
||||
const address = location.Address || 'No address';
|
||||
const supportLevel = location['Support Level'] ?
|
||||
`Level ${location['Support Level']}` : 'Not specified';
|
||||
|
||||
// Add debugging
|
||||
console.log('Creating popup for location:', locationId, location);
|
||||
// Add debugging only for non-temp users
|
||||
if (currentUser?.userType !== 'temp') {
|
||||
console.log('Creating popup for location:', locationId, location);
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="popup-content">
|
||||
@ -319,6 +368,11 @@ export function openEditForm(location) {
|
||||
// Extract ID - check multiple possible field names
|
||||
const locationId = location.Id || location.id || location.ID || location._id;
|
||||
|
||||
// Add debugging for temp users
|
||||
console.log('Opening edit form for location:', location);
|
||||
console.log('Extracted ID:', locationId);
|
||||
console.log('Available keys:', Object.keys(location));
|
||||
|
||||
if (!locationId) {
|
||||
console.error('No ID found in location object. Available fields:', Object.keys(location));
|
||||
showStatus('Error: Location ID not found. Check console for details.', 'error');
|
||||
@ -803,7 +857,10 @@ function createMultiUnitMarker(group) {
|
||||
setupAppApartmentPopupListeners(group);
|
||||
});
|
||||
|
||||
console.log(`Created multi-unit marker at ${lat}, ${lng} with ${locations.length} units`);
|
||||
// Only log multi-unit marker creation for non-temp users
|
||||
if (currentUser?.userType !== 'temp') {
|
||||
console.log(`Created multi-unit marker at ${lat}, ${lng} with ${locations.length} units`);
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
@ -883,8 +940,11 @@ function createUnitDetailsHTML(location, index) {
|
||||
const name = [location['First Name'], location['Last Name']].filter(Boolean).join(' ') || 'Unknown';
|
||||
const unit = location['Unit Number'] || `Unit ${index + 1}`;
|
||||
const supportLevel = location['Support Level'] ? `Level ${location['Support Level']}` : 'Not specified';
|
||||
const email = location.Email || '';
|
||||
const phone = location.Phone || '';
|
||||
|
||||
// For temp users, hide sensitive contact information
|
||||
const isTemp = currentUser?.userType === 'temp';
|
||||
const email = !isTemp ? (location.Email || '') : '';
|
||||
const phone = !isTemp ? (location.Phone || '') : '';
|
||||
|
||||
// Truncate long values for mobile
|
||||
const truncatedEmail = email.length > 25 ? email.substring(0, 25) + '...' : email;
|
||||
@ -920,11 +980,13 @@ function createUnitDetailsHTML(location, index) {
|
||||
style="background: #a02c8d; border: none; padding: 3px 6px; border-radius: 3px; font-size: 9px; cursor: pointer; flex: 1; min-width: 45%;">
|
||||
✏️ Edit
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm move-unit-btn"
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'
|
||||
style="background: #6c757d; border: none; padding: 3px 6px; border-radius: 3px; font-size: 9px; cursor: pointer; flex: 1; min-width: 45%;">
|
||||
📍 Move
|
||||
</button>
|
||||
${currentUser.userType !== 'temp' ? `
|
||||
<button class="btn btn-primary btn-sm move-unit-btn"
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'
|
||||
style="background: #6c757d; border: none; padding: 3px 6px; border-radius: 3px; font-size: 9px; cursor: pointer; flex: 1; min-width: 45%;">
|
||||
📍 Move
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
@ -30,6 +30,9 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
// First check authentication
|
||||
await checkAuth();
|
||||
|
||||
// Setup temp user security measures after authentication
|
||||
setupTempUserSecurity();
|
||||
|
||||
// Then initialize the map
|
||||
await initializeMap();
|
||||
|
||||
@ -99,3 +102,64 @@ async function initializeUnifiedSearch() {
|
||||
console.error('Error setting up unified search:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup security measures for temp users
|
||||
function setupTempUserSecurity() {
|
||||
// Import currentUser from auth module
|
||||
import('./auth.js').then(authModule => {
|
||||
const { currentUser } = authModule;
|
||||
|
||||
if (currentUser?.userType === 'temp') {
|
||||
console.log('Applying temp user security measures...');
|
||||
|
||||
// Disable right-click context menu
|
||||
document.addEventListener('contextmenu', (e) => {
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const locationsController = require('../controllers/locationsController');
|
||||
const { strictLimiter } = require('../middleware/rateLimiter');
|
||||
const { strictLimiter, conditionalTempLimiter } = require('../middleware/rateLimiter');
|
||||
const { requireAuth, requireDeletePermission } = require('../middleware/auth');
|
||||
|
||||
// Get all locations (public)
|
||||
router.get('/', locationsController.getAll);
|
||||
// Get all locations (apply stricter rate limiting for temp users)
|
||||
router.get('/', conditionalTempLimiter, locationsController.getAll);
|
||||
|
||||
// Get single location (public)
|
||||
router.get('/:id', locationsController.getById);
|
||||
// Get single location (apply stricter rate limiting for temp users)
|
||||
router.get('/:id', conditionalTempLimiter, locationsController.getById);
|
||||
|
||||
// Create location (requires authentication)
|
||||
router.post('/', requireAuth, strictLimiter, locationsController.create);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user