| import express from "express"; |
| import bcrypt from "bcrypt"; |
| import jwt from "jsonwebtoken"; |
| import crypto from "crypto"; |
| import { User } from "../models/User.js"; |
| import { loginLimiter } from "../middleware/rateLimit.js"; |
| import { JWT_CONFIG, PASSWORD_POLICY } from "../config/security.js"; |
|
|
| const r = express.Router(); |
|
|
| r.post("/register", async (req, res) => { |
| if (!req.body.password || req.body.password.length < PASSWORD_POLICY.minLength) |
| return res.status(400).json({ error: "Weak password" }); |
|
|
| const hash = await bcrypt.hash(req.body.password, 10); |
| await User.create({ email: req.body.email, passwordHash: hash }); |
| res.json({ ok: true }); |
| }); |
|
|
| r.post("/login", loginLimiter, async (req, res) => { |
| const user = await User.findOne({ email: req.body.email }); |
| if (!user) return res.sendStatus(401); |
|
|
| const ok = await bcrypt.compare(req.body.password, user.passwordHash); |
| await new Promise((r) => setTimeout(r, 500)); |
| if (!ok) return res.sendStatus(401); |
|
|
| const accessToken = jwt.sign( |
| { id: user.id, role: user.role }, |
| process.env.JWT_SECRET, |
| { expiresIn: "15m", ...JWT_CONFIG } |
| ); |
|
|
| const refresh = crypto.randomBytes(64).toString("hex"); |
| user.refreshTokens.push({ |
| hash: await bcrypt.hash(refresh, 10), |
| ip: req.ip, |
| userAgent: req.headers["user-agent"], |
| }); |
| await user.save(); |
|
|
| res.json({ accessToken, refreshToken: refresh }); |
| }); |
|
|
| export default r; |
|
|