const express = require('express'); const router = express.Router(); const { Users } = require('../models'); router.get('/login', (req, res) => { res.render('auth/login', { title: 'Login', error: null }); }); router.post('/login', (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.render('auth/login', { title: 'Login', error: 'Username and password are required.' }); } const user = Users.findByUsername(username); if (!user || !Users.verifyPassword(user, password)) { return res.render('auth/login', { title: 'Login', error: 'Invalid username or password.' }); } req.session.userId = user.id; req.session.username = user.username; req.session.displayName = user.display_name || user.username; req.session.isAdmin = !!user.is_admin; req.session.isOrganizer = !!user.is_organizer; const returnTo = req.session.returnTo || '/'; delete req.session.returnTo; res.redirect(returnTo); }); router.get('/register', (req, res) => { res.render('auth/register', { title: 'Register', error: null }); }); router.post('/register', (req, res) => { const { username, password, password_confirm } = req.body; if (!username || !password) { return res.render('auth/register', { title: 'Register', error: 'Username and password are required.' }); } if (username.length < 3 || username.length > 24) { return res.render('auth/register', { title: 'Register', error: 'Username must be 3-24 characters.' }); } if (!/^[a-zA-Z0-9_-]+$/.test(username)) { return res.render('auth/register', { title: 'Register', error: 'Username can only contain letters, numbers, hyphens and underscores.' }); } if (password.length < 6) { return res.render('auth/register', { title: 'Register', error: 'Password must be at least 6 characters.' }); } if (password !== password_confirm) { return res.render('auth/register', { title: 'Register', error: 'Passwords do not match.' }); } if (Users.findByUsername(username)) { return res.render('auth/register', { title: 'Register', error: 'Username is already taken.' }); } try { const userId = Users.create(username, password); req.session.userId = userId; req.session.username = username; req.session.displayName = username; req.session.isAdmin = false; req.session.isOrganizer = false; req.session.flash = { type: 'success', message: 'Account created! Welcome to Loot Hunt.' }; const returnTo = req.session.returnTo || '/'; delete req.session.returnTo; res.redirect(returnTo); } catch (err) { console.error('Registration error:', err); res.render('auth/register', { title: 'Register', error: 'Registration failed. Try a different username.' }); } }); router.get('/logout', (req, res) => { req.session.destroy(() => { res.redirect('/'); }); }); // ─── Password reset (via admin-generated URL) ──────────── router.get('/reset/:token', (req, res) => { const tokenRecord = Users.findByResetToken(req.params.token); if (!tokenRecord) { return res.render('error', { title: 'Invalid Link', message: 'This password reset link is invalid or has expired.' }); } res.render('auth/reset', { title: 'Reset Password', token: req.params.token, username: tokenRecord.username, error: null }); }); router.post('/reset/:token', (req, res) => { const tokenRecord = Users.findByResetToken(req.params.token); if (!tokenRecord) { return res.render('error', { title: 'Invalid Link', message: 'This password reset link is invalid or has expired.' }); } const { password, password_confirm } = req.body; if (!password || password.length < 6) { return res.render('auth/reset', { title: 'Reset Password', token: req.params.token, username: tokenRecord.username, error: 'Password must be at least 6 characters.' }); } if (password !== password_confirm) { return res.render('auth/reset', { title: 'Reset Password', token: req.params.token, username: tokenRecord.username, error: 'Passwords do not match.' }); } Users.setPassword(tokenRecord.user_id, password); Users.consumeResetToken(req.params.token); // Log the user in req.session.userId = tokenRecord.user_id; req.session.username = tokenRecord.username; req.session.displayName = tokenRecord.username; req.session.isAdmin = false; // they can re-check on next load res.redirect('/'); }); module.exports = router;