diff --git a/map/app/controllers/locationsController.js b/map/app/controllers/locationsController.js index db97286..96b1143 100644 --- a/map/app/controllers/locationsController.js +++ b/map/app/controllers/locationsController.js @@ -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, diff --git a/map/app/middleware/rateLimiter.js b/map/app/middleware/rateLimiter.js index 6f14e59..a67d2c7 100644 --- a/map/app/middleware/rateLimiter.js +++ b/map/app/middleware/rateLimiter.js @@ -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 }; \ No newline at end of file diff --git a/map/app/public/js/location-manager.js b/map/app/public/js/location-manager.js index c4d1cea..c9cb5c9 100644 --- a/map/app/public/js/location-manager.js +++ b/map/app/public/js/location-manager.js @@ -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 ` +
Address: ${escapeHtml(address)}
+Support: ${escapeHtml(supportLevel)}
+ ${location.Sign ? '🏁 Has campaign sign
' : ''} + ${location.Notes ? `Notes: ${escapeHtml(location.Notes)}
` : ''} + +