46 lines
1.5 KiB
JavaScript
46 lines
1.5 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const db = require('../db');
|
|
|
|
const SECRET = process.env.JWT_SECRET;
|
|
|
|
// 最后活跃记录:模块级缓存 <userId, 'YYYY-MM-DD'>,仅当用户上次记录日期 ≠ 今天时
|
|
// 才写库(避免每个请求都执行 UPDATE)。写入失败静默忽略(best-effort,不影响鉴权)。
|
|
const activeDates = new Map();
|
|
|
|
function touchLastActive(userId) {
|
|
if (!userId) return;
|
|
const today = new Date().toISOString().slice(0, 10);
|
|
if (activeDates.get(userId) === today) return;
|
|
activeDates.set(userId, today);
|
|
try {
|
|
db.run("UPDATE users SET last_active_at = datetime('now') WHERE id = ?", [userId]);
|
|
} catch { /* 忽略活跃记录失败 */ }
|
|
}
|
|
|
|
function authMiddleware(req, res, next) {
|
|
const header = req.headers.authorization;
|
|
if (!header || !header.startsWith('Bearer ')) {
|
|
return res.status(401).json({ error: '未登录' });
|
|
}
|
|
try {
|
|
const payload = jwt.verify(header.slice(7), SECRET);
|
|
req.user = payload;
|
|
// 记录最后活跃(跨天节流)
|
|
touchLastActive(payload.id);
|
|
next();
|
|
} catch {
|
|
return res.status(401).json({ error: '登录已过期' });
|
|
}
|
|
}
|
|
|
|
function adminOnly(req, res, next) {
|
|
// 查库复查角色,防止 JWT 中过期/被篡改的角色信息直接放行
|
|
const u = db.get('SELECT role FROM users WHERE id = ?', [req.user.id]);
|
|
if (!u || u.role !== 'admin') {
|
|
return res.status(403).json({ error: '需要管理员权限' });
|
|
}
|
|
next();
|
|
}
|
|
|
|
module.exports = { authMiddleware, adminOnly, SECRET };
|