73 lines
1.9 KiB
JavaScript
73 lines
1.9 KiB
JavaScript
|
|
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
|
||
|
|
}
|