const nocodbService = require('../services/nocodb'); // Helper function to check if a temp user has expired const checkTempUserExpiration = async (req, res) => { if (req.session?.userType === 'temp' && req.session?.userEmail) { try { const user = await nocodbService.getUserByEmail(req.session.userEmail); if (user) { const expiration = user.ExpiresAt || user.expiresAt || user.Expiration || user.expiration; if (expiration) { const expirationDate = new Date(expiration); const now = new Date(); if (now > expirationDate) { console.warn(`Expired temp user session detected: ${req.session.userEmail}, expired: ${expiration}`); // Destroy the session req.session.destroy((err) => { if (err) { console.error('Session destroy error:', err); } }); if (req.xhr || req.headers.accept?.indexOf('json') > -1) { return res.status(401).json({ success: false, error: 'Account has expired. Please contact an administrator.', expired: true }); } else { return res.redirect('/login.html?expired=true'); } } } } } catch (error) { console.error('Error checking temp user expiration:', error.message); // Don't fail the request on database errors, just log it } } return null; // No expiration issue }; const requireAuth = async (req, res, next) => { const isAuthenticated = (req.session && req.session.authenticated) || (req.session && req.session.userId && req.session.userEmail); if (isAuthenticated) { // Check if temp user has expired const expirationResponse = await checkTempUserExpiration(req, res); if (expirationResponse) { return; // Response already sent by checkTempUserExpiration } // Set up req.user object for controllers that expect it req.user = { id: req.session.userId, email: req.session.userEmail, isAdmin: req.session.isAdmin || false, userType: req.session.userType || 'user', name: req.session.userName || req.session.user_name || null }; next(); } else { console.warn('Unauthorized access attempt', { ip: req.ip, path: req.path, userAgent: req.get('User-Agent'), method: req.method, timestamp: new Date().toISOString() }); if (req.xhr || req.headers.accept?.indexOf('json') > -1) { res.status(401).json({ success: false, error: 'Authentication required' }); } else { res.redirect('/login.html'); } } }; const requireAdmin = async (req, res, next) => { const isAuthenticated = (req.session && req.session.authenticated) || (req.session && req.session.userId && req.session.userEmail); if (isAuthenticated && req.session.isAdmin) { // Check if temp user has expired const expirationResponse = await checkTempUserExpiration(req, res); if (expirationResponse) { return; // Response already sent by checkTempUserExpiration } // Set up req.user object for controllers that expect it req.user = { id: req.session.userId, email: req.session.userEmail, isAdmin: req.session.isAdmin || false, userType: req.session.userType || 'user', name: req.session.userName || req.session.user_name || null }; next(); } else { console.warn('Unauthorized admin access attempt', { ip: req.ip, path: req.path, user: req.session?.userEmail || 'anonymous', userAgent: req.get('User-Agent') }); if (req.xhr || req.headers.accept?.indexOf('json') > -1) { res.status(403).json({ success: false, error: 'Admin access required' }); } else { res.redirect('/login.html'); } } }; const requireNonTemp = async (req, res, next) => { const isAuthenticated = (req.session && req.session.authenticated) || (req.session && req.session.userId && req.session.userEmail); if (isAuthenticated && req.session.userType !== 'temp') { // Check if temp user has expired (shouldn't happen here, but for safety) const expirationResponse = await checkTempUserExpiration(req, res); if (expirationResponse) { return; // Response already sent by checkTempUserExpiration } // Set up req.user object for controllers that expect it req.user = { id: req.session.userId, email: req.session.userEmail, isAdmin: req.session.isAdmin || false, userType: req.session.userType || 'user', name: req.session.userName || req.session.user_name || null }; next(); } else { console.warn('Temp user access denied', { ip: req.ip, path: req.path, user: req.session?.userEmail || 'anonymous', userType: req.session?.userType || 'unknown' }); if (req.xhr || req.headers.accept?.indexOf('json') > -1) { res.status(403).json({ success: false, error: 'Access denied for temporary users' }); } else { res.redirect('/'); } } }; // Optional authentication - sets req.user if authenticated, but doesn't block if not const optionalAuth = async (req, res, next) => { const isAuthenticated = (req.session && req.session.authenticated) || (req.session && req.session.userId && req.session.userEmail); if (isAuthenticated) { // Check if temp user has expired const expirationResponse = await checkTempUserExpiration(req, res); if (expirationResponse) { return; // Response already sent by checkTempUserExpiration } // Set up req.user object for controllers that expect it req.user = { id: req.session.userId, email: req.session.userEmail, isAdmin: req.session.isAdmin || false, userType: req.session.userType || 'user', name: req.session.userName || req.session.user_name || null }; } // Continue regardless of authentication status next(); }; module.exports = { requireAuth, requireAdmin, requireNonTemp, optionalAuth };