const { query } = require('../config/database') const { verify } = require('../utils/jwt') const { decodeBasicAuth } = require('../utils/legacy-token') const ROLE_USER = 0 const ROLE_STAFF = 1 const ROLE_ADMIN = 2 async function getUserByToken(token) { if (!token) return null if (token.startsWith('legacy.')) { return decodeBasicAuth(token.slice(7)) } const payload = verify(token) if (!payload) return null const users = await query( 'SELECT id, phone, name, avatar, points, role, status, openid FROM users WHERE id = ? AND status = 1', [payload.sub] ) return users[0] || null } function extractToken(ctx) { const header = ctx.headers.authorization || '' if (header.startsWith('Bearer ')) return header.slice(7).trim() return ctx.query.token || '' } function deny(ctx, status, message) { ctx.status = status ctx.body = { code: status, message } return null } function requireAuth() { return async (ctx, next) => { const token = extractToken(ctx) if (!token) return deny(ctx, 401, '未登录,请先登录') const user = await getUserByToken(token) if (!user) return deny(ctx, 401, '登录已失效,请重新登录') ctx.state.user = user return next() } } function requireRole(...roles) { const allow = new Set(roles) return async (ctx, next) => { const token = extractToken(ctx) if (!token) return deny(ctx, 401, '未登录,请先登录') const user = await getUserByToken(token) if (!user) return deny(ctx, 401, '登录已失效,请重新登录') if (!allow.has(user.role)) return deny(ctx, 403, '权限不足') ctx.state.user = user return next() } } const requireStaffAuth = () => requireRole(ROLE_STAFF, ROLE_ADMIN) const requireAdminAuth = () => requireRole(ROLE_ADMIN) module.exports = { ROLE_USER, ROLE_STAFF, ROLE_ADMIN, extractToken, getUserByToken, requireAuth, requireRole, requireStaffAuth, requireAdminAuth }