const express = require('express'); const router = express.Router(); const AdminAuthService = require('../services/AdminAuthService'); const { requireAdminAuth } = require('../middlewares/auth'); const { requireCsrf } = require('../middlewares/csrf'); router.get('/setup/status', async (req, res) => { try { const needsSetup = await AdminAuthService.needsInitialSetup(); const sessionUser = req.session && req.session.user ? { id: req.session.user.id, username: req.session.user.username, role: req.session.user.role, requiresPasswordChange: Boolean(req.session.user.requiresPasswordChange) } : null; res.json({ needsSetup, hasSession: Boolean(sessionUser), user: sessionUser }); } catch (error) { console.error('[Auth] setup/status error:', error); res.status(500).json({ error: 'SETUP_STATUS_FAILED' }); } }); router.post('/setup/initial-admin', async (req, res) => { try { const { username, password } = req.body || {}; if (!username || !password) { return res.status(400).json({ error: 'USERNAME_AND_PASSWORD_REQUIRED' }); } const user = await AdminAuthService.createInitialAdmin({ username, password }); const csrfToken = AdminAuthService.startSession(req, { ...user, requiresPasswordChange: false }); res.status(201).json({ success: true, user: { id: user.id, username: user.username, role: user.role }, csrfToken }); } catch (error) { console.error('[Auth] initial setup error:', error.message); switch (error.message) { case 'SETUP_ALREADY_COMPLETED': return res.status(409).json({ error: 'SETUP_ALREADY_COMPLETED' }); case 'USERNAME_REQUIRED': return res.status(400).json({ error: 'USERNAME_REQUIRED' }); case 'PASSWORD_TOO_WEAK': return res.status(400).json({ error: 'PASSWORD_TOO_WEAK' }); default: if (error.message && error.message.includes('UNIQUE')) { return res.status(409).json({ error: 'USERNAME_IN_USE' }); } return res.status(500).json({ error: 'INITIAL_SETUP_FAILED' }); } } }); router.post('/login', async (req, res) => { try { const { username, password } = req.body || {}; if (!username || !password) { return res.status(400).json({ error: 'USERNAME_AND_PASSWORD_REQUIRED' }); } if (await AdminAuthService.needsInitialSetup()) { return res.status(409).json({ error: 'SETUP_REQUIRED' }); } const user = await AdminAuthService.verifyCredentials(username, password); if (!user) { return res.status(401).json({ error: 'INVALID_CREDENTIALS' }); } const csrfToken = AdminAuthService.startSession(req, user); res.json({ success: true, user: { id: user.id, username: user.username, role: user.role, requiresPasswordChange: user.requiresPasswordChange }, csrfToken }); } catch (error) { console.error('[Auth] login error:', error); res.status(500).json({ error: 'LOGIN_FAILED' }); } }); router.post('/logout', async (req, res) => { try { await AdminAuthService.destroySession(req); res.clearCookie('sid'); res.status(204).send(); } catch (error) { console.error('[Auth] logout error:', error); res.status(500).json({ error: 'LOGOUT_FAILED' }); } }); router.get('/csrf-token', requireAdminAuth, (req, res) => { if (!req.session.csrfToken) { req.session.csrfToken = AdminAuthService.generateCsrfToken(); } res.json({ csrfToken: req.session.csrfToken }); }); router.post('/change-password', requireAdminAuth, requireCsrf, async (req, res) => { try { const { currentPassword, newPassword } = req.body || {}; if (!currentPassword || !newPassword) { return res.status(400).json({ error: 'CURRENT_AND_NEW_PASSWORD_REQUIRED' }); } const user = await AdminAuthService.changePassword({ userId: req.session.user.id, currentPassword, newPassword }); req.session.user = { ...req.session.user, requiresPasswordChange: false }; res.json({ success: true, user: { id: user.id, username: user.username, role: user.role, requiresPasswordChange: false } }); } catch (error) { console.error('[Auth] change password error:', error.message || error); switch (error.message) { case 'CURRENT_PASSWORD_REQUIRED': return res.status(400).json({ error: 'CURRENT_PASSWORD_REQUIRED' }); case 'PASSWORD_TOO_WEAK': return res.status(400).json({ error: 'PASSWORD_TOO_WEAK' }); case 'INVALID_CURRENT_PASSWORD': return res.status(400).json({ error: 'INVALID_CURRENT_PASSWORD' }); case 'USER_NOT_FOUND': return res.status(404).json({ error: 'USER_NOT_FOUND' }); default: return res.status(500).json({ error: 'PASSWORD_CHANGE_FAILED' }); } } }); module.exports = router;