更新完善页面
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
const { query } = require('../config/database')
|
||||
const { verifyToken } = 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 = verifyToken(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
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* v2 API 响应转换中间件
|
||||
*
|
||||
* 用法:在 v2 路由组中挂载此中间件,自动将 v1 风格响应转为 v2 格式
|
||||
* v1: { code: 200, data, message } (HTTP 状态码作业务码)
|
||||
* v2: { code: 0, data, message } (0=成功,非零=错误)
|
||||
*
|
||||
* 路由示例:
|
||||
* router.use('/v2', v2Middleware(), v2Routes)
|
||||
*/
|
||||
|
||||
const { fromV1, SUCCESS, ERROR_MESSAGES } = require('../utils/error-codes')
|
||||
|
||||
function v2ResponseMiddleware() {
|
||||
return async (ctx, next) => {
|
||||
await next()
|
||||
|
||||
// 只处理 JSON 响应
|
||||
if (!ctx.body || typeof ctx.body !== 'object') return
|
||||
|
||||
// 如果已经是 v2 格式(code 为 0 或不在 v1 映射表中),跳过
|
||||
if (ctx.body.code === SUCCESS || ctx.body._v2) return
|
||||
|
||||
// 转换 v1 → v2
|
||||
ctx.body = fromV1(ctx.body)
|
||||
ctx.body._v2 = true
|
||||
|
||||
// 设置 v2 响应头标识
|
||||
ctx.set('X-API-Version', '2')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { v2ResponseMiddleware }
|
||||
Reference in New Issue
Block a user