import { Router } from 'express'; import bcrypt from 'bcrypt'; import jwt from 'jsonwebtoken'; import { PrismaClient } from '@prisma/client'; import rateLimit from 'express-rate-limit'; const router = Router(); const prisma = new PrismaClient(); const JWT_SECRET = process.env.JWT_SECRET || 'fallback-secret-for-development-only'; const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 5, // Limit each IP to 5 failed login attempts per window message: { status: 'error', message: 'Too many login attempts, please try again later' }, skipSuccessfulRequests: true, }); // Check if setup is required (no users exist) router.get('/auth/status', async (req, res) => { try { const userCount = await prisma.user.count(); res.json({ setupRequired: userCount === 0 }); } catch (error) { res.status(500).json({ status: 'error', message: 'Database error' }); } }); // Initial Setup (Only works if no users exist) router.post('/auth/setup', async (req, res) => { try { const userCount = await prisma.user.count(); if (userCount > 0) { return res.status(403).json({ status: 'error', message: 'Setup has already been completed' }); } const { username, password } = req.body; if (!username || !password || password.length < 8) { return res.status(400).json({ status: 'error', message: 'Invalid username or password must be at least 8 characters' }); } const hashedPassword = await bcrypt.hash(password, 10); const user = await prisma.user.create({ data: { username, password: hashedPassword }, }); const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '7d' }); res.json({ status: 'success', token, user: { id: user.id, username: user.username } }); } catch (error) { res.status(500).json({ status: 'error', message: 'Failed to create user' }); } }); // Login router.post('/auth/login', loginLimiter, async (req, res) => { try { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ status: 'error', message: 'Username and password required' }); } const user = await prisma.user.findUnique({ where: { username } }); if (!user) { return res.status(401).json({ status: 'error', message: 'Invalid credentials' }); } const valid = await bcrypt.compare(password, user.password); if (!valid) { return res.status(401).json({ status: 'error', message: 'Invalid credentials' }); } const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '7d' }); res.json({ status: 'success', token, user: { id: user.id, username: user.username } }); } catch (error) { res.status(500).json({ status: 'error', message: 'Login failed' }); } }); export default router;