const express = require('express'); const path = require('path'); const { requireAuth, requireAdmin, requireNonTemp } = require('../middleware/auth'); // Import route modules const authRoutes = require('./auth'); const locationRoutes = require('./locations'); const adminRoutes = require('./admin'); const settingsRoutes = require('./settings'); const userRoutes = require('./users'); const qrRoutes = require('./qr'); const debugRoutes = require('./debug'); const geocodingRoutes = require('../routes/geocoding'); // Existing geocoding routes const shiftsRoutes = require('./shifts'); const publicRoutes = require('./public'); const externalDataRoutes = require('./external'); const cutsRoutes = require('./cuts'); const listmonkRoutes = require('./listmonk'); module.exports = (app) => { // Health check (no auth) app.get('/health', (req, res) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), version: process.env.npm_package_version || '1.0.0' }); }); // Login page (no auth) app.get('/login.html', (req, res) => { res.sendFile(path.join(__dirname, '../public', 'login.html')); }); // Auth routes (no auth required) app.use('/api/auth', authRoutes); // Public routes (no auth required) app.use('/api/public', publicRoutes); // Public config endpoint app.get('/api/config/start-location', require('../controllers/settingsController').getPublicStartLocation); // Domain config endpoint (public) app.get('/api/config/domain', (req, res) => { const config = require('../config'); res.json({ domain: config.domain }); }); // QR code routes (authenticated) app.use('/api/qr', requireAuth, qrRoutes); // Public cuts endpoint (no auth required) app.get('/api/cuts/public', require('../controllers/cutsController').getPublic); // Test QR page (no auth for testing) app.get('/test-qr', (req, res) => { res.sendFile(path.join(__dirname, '../public/test-qr.html')); }); // Protected routes app.use('/api/locations', requireAuth, locationRoutes); app.use('/api/geocode', requireAuth, geocodingRoutes); app.use('/api/settings', requireAuth, settingsRoutes); app.use('/api/shifts', requireNonTemp, shiftsRoutes); app.use('/api/external', externalDataRoutes); // Cuts routes (add after other protected routes) app.use('/api/cuts', requireAuth, cutsRoutes); // Listmonk routes (authenticated) app.use('/api/listmonk', requireAuth, listmonkRoutes); // Admin routes app.get('/admin.html', requireAdmin, (req, res) => { res.sendFile(path.join(__dirname, '../public', 'admin.html')); }); app.use('/api/admin', requireAdmin, adminRoutes); app.use('/api/users', requireAdmin, userRoutes); // Debug routes (admin only) app.use('/api/debug', requireAdmin, debugRoutes); // Debug cuts endpoint to see raw field names app.get('/api/debug/cuts-raw', requireAdmin, async (req, res) => { try { const config = require('../config'); const nocodbService = require('../services/nocodb'); if (!config.nocodb.cutsSheetId) { return res.json({ error: 'Cuts table not configured' }); } const response = await nocodbService.getAll(config.nocodb.cutsSheetId); res.json({ totalCuts: response?.list?.length || 0, sampleCut: response?.list?.[0] || null, allFields: response?.list?.[0] ? Object.keys(response.list[0]) : [] }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Config check endpoint (authenticated) app.get('/api/config-check', requireAuth, (req, res) => { const config = require('../config'); const configStatus = { hasApiUrl: !!config.nocodb.apiUrl, hasApiToken: !!config.nocodb.apiToken, hasProjectId: !!config.nocodb.projectId, hasTableId: !!config.nocodb.tableId, hasLoginSheet: !!config.nocodb.loginSheetId, hasSettingsSheet: !!config.nocodb.settingsSheetId, hasCutsSheet: !!config.nocodb.cutsSheetId, projectId: config.nocodb.projectId, tableId: config.nocodb.tableId, loginSheet: config.nocodb.loginSheetId, settingsSheet: config.nocodb.settingsSheetId, cutsSheet: config.nocodb.cutsSheetId, nodeEnv: config.nodeEnv }; const isConfigured = configStatus.hasApiUrl && configStatus.hasApiToken && configStatus.hasProjectId && configStatus.hasTableId; res.json({ configured: isConfigured, ...configStatus }); }); // Config endpoint (authenticated) app.get('/api/config', requireAuth, (req, res) => { const config = require('../config'); console.log('Config endpoint called by user:', { user: req.user ? req.user.email : 'No user', isAdmin: req.user ? req.user.isAdmin : 'No user', hasNocodbUrls: !!(process.env.NOCODB_VIEW_URL) }); // Determine the MkDocs URL based on the request let mkdocsUrl = config.mkdocs.url; // If we're in production and the request is not from localhost if (config.isProduction && req.hostname !== 'localhost' && !req.hostname.includes('127.0.0.1')) { // Use the configured MKDOCS_URL from environment mkdocsUrl = config.mkdocs.url; } const response = { mkdocsUrl: mkdocsUrl, mkdocsPort: config.mkdocs.port }; // Include NocoDB URLs for admin users if (req.user && req.user.isAdmin) { console.log('Adding NocoDB URLs for admin user'); response.nocodbUrls = { viewUrl: process.env.NOCODB_VIEW_URL, loginSheet: process.env.NOCODB_LOGIN_SHEET, settingsSheet: process.env.NOCODB_SETTINGS_SHEET, shiftsSheet: process.env.NOCODB_SHIFTS_SHEET, shiftSignupsSheet: process.env.NOCODB_SHIFT_SIGNUPS_SHEET }; } else { console.log('Not adding NocoDB URLs - user not admin or not found'); console.log('req.user:', req.user); console.log('req.user.isAdmin:', req.user ? req.user.isAdmin : 'no user'); // If this is a request from the admin page specifically, add the URLs anyway // since the requireAdmin middleware would have already checked permissions const referer = req.get('Referer'); if (referer && referer.includes('/admin.html')) { console.log('Request from admin page, adding NocoDB URLs anyway'); response.nocodbUrls = { viewUrl: process.env.NOCODB_VIEW_URL, loginSheet: process.env.NOCODB_LOGIN_SHEET, settingsSheet: process.env.NOCODB_SETTINGS_SHEET, shiftsSheet: process.env.NOCODB_SHIFTS_SHEET, shiftSignupsSheet: process.env.NOCODB_SHIFT_SIGNUPS_SHEET }; } } res.json(response); }); // Serve static files (protected) app.use(express.static(path.join(__dirname, '../public'), { index: false // Don't serve index.html automatically })); // Main app route (protected) app.get('/', requireAuth, (req, res) => { res.sendFile(path.join(__dirname, '../public', 'index.html')); }); // Protected page route app.get('/shifts.html', requireNonTemp, (req, res) => { res.sendFile(path.join(__dirname, '../public', 'shifts.html')); }); // User profile page route app.get('/user.html', requireNonTemp, (req, res) => { res.sendFile(path.join(__dirname, '../public', 'user.html')); }); // Catch all - redirect to login app.get('*', (req, res) => { res.redirect('/login.html'); }); };