first commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user