import { Router } from 'express'; import bcrypt from 'bcryptjs'; import { getAdmin, updateAdminPassword } from '../db.js'; import { requireAuth, signToken } from '../auth.js'; const router = Router(); const loginAttempts = new Map(); function checkRateLimit(ip) { const now = Date.now(); const record = loginAttempts.get(ip) || { count: 0, resetAt: now + 60000 }; if (now > record.resetAt) { loginAttempts.set(ip, { count: 1, resetAt: now + 60000 }); return true; } if (record.count >= 5) return false; record.count++; loginAttempts.set(ip, record); return true; } router.post('/login', (req, res) => { const ip = req.ip; if (!checkRateLimit(ip)) { return res.status(429).json({ error: 'Too many login attempts', code: 'RATE_LIMITED' }); } const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ error: 'Username and password required', code: 'VALIDATION' }); } const admin = getAdmin(); if (!admin || username !== admin.username || !bcrypt.compareSync(password, admin.passwordHash)) { return res.status(401).json({ error: 'Invalid credentials', code: 'UNAUTHORIZED' }); } const token = signToken(username); const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); res.json({ token, expiresAt }); }); router.get('/me', requireAuth, (req, res) => { res.json({ username: req.user.username }); }); router.put('/password', requireAuth, (req, res) => { const { currentPassword, newPassword } = req.body; if (!currentPassword || !newPassword || newPassword.length < 6) { return res.status(400).json({ error: 'Valid current and new password (min 6 chars) required', code: 'VALIDATION' }); } const admin = getAdmin(); if (!bcrypt.compareSync(currentPassword, admin.passwordHash)) { return res.status(401).json({ error: 'Current password is incorrect', code: 'UNAUTHORIZED' }); } updateAdminPassword(bcrypt.hashSync(newPassword, 12)); res.json({ message: 'Password updated' }); }); export default router;