import { Router } from 'express' import crypto from 'node:crypto' import { prisma } from '../db.js' import { authRequired, signToken } from '../middleware.js' const router = Router() // 校验密码: 接受 scrypt$salt$hash 格式 function verifyPassword(plain, stored) { if (!stored || !stored.startsWith('scrypt$')) return false const parts = stored.split('$') if (parts.length !== 3) return false const [, salt, hash] = parts const computed = crypto.scryptSync(plain, salt, 64).toString('hex') // 常数时间比较 const a = Buffer.from(computed, 'hex') const b = Buffer.from(hash, 'hex') if (a.length !== b.length) return false return crypto.timingSafeEqual(a, b) } router.post('/login', async (req, res) => { const { email, password } = req.body || {} if (!email || !password) return res.status(400).json({ error: '邮箱或密码不能为空' }) const user = await prisma.user.findUnique({ where: { email: String(email).toLowerCase() } }) if (!user) return res.status(401).json({ error: '邮箱或密码错误' }) if (!verifyPassword(String(password), user.password)) { return res.status(401).json({ error: '邮箱或密码错误' }) } const payload = { sub: user.id, email: user.email, name: user.name } const token = signToken(payload) res.json({ token, user: { id: user.id, name: user.name, email: user.email, createdAt: user.createdAt } }) }) router.get('/me', authRequired, async (req, res) => { const user = await prisma.user.findUnique({ where: { id: req.user.sub } }) if (!user) return res.status(401).json({ error: '用户不存在' }) res.json({ user: { id: user.id, name: user.name, email: user.email, createdAt: user.createdAt } }) }) router.post('/logout', (_req, res) => { // JWT 无状态, 前端清 token 即可; 这里返回 200 让前端不用特判 res.json({ ok: true }) }) export default router