const express = require('express'); const crypto = require('crypto'); const rateLimit = require('express-rate-limit'); const router = express.Router(); const { COOKIE_NAME, verify, createSessionCookie, clearSessionCookie, } = require('../middleware/auth'); const loginLimiter = rateLimit({ windowMs: 60 * 1000, max: 5, standardHeaders: true, legacyHeaders: false, message: { error: 'Too many login attempts. Try again later.' }, }); router.post('/login', loginLimiter, (req, res) => { const password = process.env.APP_PASSWORD; if (!password) { return res.status(200).json({ ok: true }); } const submitted = req.body?.password || ''; const submittedBuf = Buffer.from(String(submitted)); const passwordBuf = Buffer.from(password); let match = false; if (submittedBuf.length === passwordBuf.length) { match = crypto.timingSafeEqual(submittedBuf, passwordBuf); } if (!match) { return res.status(401).json({ error: 'Invalid password' }); } const session = createSessionCookie(); if (!session) { return res.status(500).json({ error: 'Auth not configured' }); } const cookieOpts = { ...session.opts }; if (cookieOpts.secure && !req.secure) cookieOpts.secure = false; res.cookie(COOKIE_NAME, session.token, cookieOpts); res.json({ ok: true }); }); router.post('/logout', (req, res) => { res.cookie(COOKIE_NAME, '', clearSessionCookie()); res.status(204).send(); }); router.get('/me', (req, res) => { if (!process.env.APP_PASSWORD) { return res.status(200).json({ ok: true }); } const token = req.cookies?.[COOKIE_NAME] || null; if (!token || !verify(token)) { return res.status(401).json({ error: 'Unauthorized' }); } res.json({ ok: true }); }); module.exports = router;