Files
Henry_Du 4ce4649aaf
Build VoiceHub FPK / build-fpk (push) Failing after 56m5s
Build and Push Docker Image / build-and-push (push) Canceled after 1h9m35s
初次提交
2026-09-06 08:19:02 +08:00

257 lines
6.4 KiB
TypeScript

import { getCookie, getHeader, setCookie, getRequestURL, getRequestHeader } from 'h3'
import { JWTEnhanced } from './jwt-enhanced'
import { db, eq, users } from '~/drizzle/db'
interface AuthResult {
success: boolean
message: string
user?: any
}
/**
* 验证管理员权限
* @param event - Nuxt事件对象
* @returns 验证结果
*/
export async function verifyAdminAuth(event: any): Promise<AuthResult> {
try {
// 首先检查认证中间件是否已经验证了用户
if (event.context?.user) {
const user = event.context.user
// 检查用户角色
if (user.role !== 'ADMIN' && user.role !== 'SUPER_ADMIN') {
return {
success: false,
message: '权限不足,需要管理员权限'
}
}
return {
success: true,
message: '认证成功',
user: user
}
}
// 如果context中没有用户信息,尝试从Authorization头或cookie获取token
let token: string | null = null
const authHeader = getHeader(event, 'authorization')
if (authHeader && authHeader.startsWith('Bearer ')) {
token = authHeader.substring(7)
}
if (!token) {
token = getCookie(event, 'auth-token') || null
}
if (!token) {
return {
success: false,
message: '缺少认证令牌'
}
}
// 验证JWT token
let decoded: any
try {
decoded = JWTEnhanced.verifyToken(token)
} catch (jwtError) {
console.error('JWT验证失败:', jwtError)
return {
success: false,
message: '认证令牌无效或已过期'
}
}
// 从数据库获取用户信息
const userResult = await db
.select({
id: users.id,
username: users.username,
name: users.name,
role: users.role,
passwordChangedAt: users.passwordChangedAt
})
.from(users)
.where(eq(users.id, decoded.userId))
.limit(1)
const user = userResult[0]
if (!user) {
console.error('获取用户信息失败: 用户不存在')
return {
success: false,
message: '用户不存在'
}
}
// 检查token是否在密码修改之前签发(强制旧token失效)
if (user.passwordChangedAt && decoded.iat) {
const passwordChangedTime = Math.floor(new Date(user.passwordChangedAt).getTime() / 1000)
if (decoded.iat < passwordChangedTime) {
// 主动清除Cookie
const isSecure =
getRequestURL(event).protocol === 'https:' ||
getRequestHeader(event, 'x-forwarded-proto') === 'https'
setCookie(event, 'auth-token', '', {
httpOnly: true,
secure: isSecure,
sameSite: 'lax',
maxAge: 0,
path: '/'
})
return {
success: false,
message: '密码已修改,请重新登录'
}
}
}
// 检查用户角色
if (user.role !== 'ADMIN' && user.role !== 'SUPER_ADMIN') {
return {
success: false,
message: '权限不足,需要管理员权限'
}
}
return {
success: true,
message: '认证成功',
user: user
}
} catch (error) {
console.error('权限验证过程中出错:', error)
return {
success: false,
message: '权限验证失败'
}
}
}
/**
* 验证超级管理员权限
* @param event - Nuxt事件对象
* @returns 验证结果
*/
export async function verifySuperAdminAuth(event: any): Promise<AuthResult> {
const authResult = await verifyAdminAuth(event)
if (!authResult.success) {
return authResult
}
if (authResult.user?.role !== 'SUPER_ADMIN') {
return {
success: false,
message: '权限不足,需要超级管理员权限'
}
}
return authResult
}
/**
* 验证用户权限(包括普通用户)
* @param event - Nuxt事件对象
* @returns 验证结果
*/
export async function verifyUserAuth(event: any): Promise<AuthResult> {
try {
// 首先检查认证中间件是否已经验证了用户
if (event.context?.user) {
return {
success: true,
message: '认证成功',
user: event.context.user
}
}
// 如果context中没有用户信息,尝试从Authorization头或cookie获取token
let token: string | null = null
const authHeader = getHeader(event, 'authorization')
if (authHeader && authHeader.startsWith('Bearer ')) {
token = authHeader.substring(7)
}
if (!token) {
token = getCookie(event, 'auth-token') || null
}
if (!token) {
return {
success: false,
message: '缺少认证令牌'
}
}
// 验证JWT token
let decoded: any
try {
decoded = JWTEnhanced.verifyToken(token)
} catch (jwtError) {
console.error('JWT验证失败:', jwtError)
return {
success: false,
message: '认证令牌无效或已过期'
}
}
// 从数据库获取用户信息
const userResult = await db
.select({
id: users.id,
username: users.username,
name: users.name,
role: users.role,
passwordChangedAt: users.passwordChangedAt
})
.from(users)
.where(eq(users.id, decoded.userId))
.limit(1)
const user = userResult[0]
if (!user) {
console.error('获取用户信息失败: 用户不存在')
return {
success: false,
message: '用户不存在'
}
}
// 检查token是否在密码修改之前签发(强制旧token失效)
if (user.passwordChangedAt && decoded.iat) {
const passwordChangedTime = Math.floor(new Date(user.passwordChangedAt).getTime() / 1000)
if (decoded.iat < passwordChangedTime) {
// 主动清除Cookie
const isSecure =
getRequestURL(event).protocol === 'https:' ||
getRequestHeader(event, 'x-forwarded-proto') === 'https'
setCookie(event, 'auth-token', '', {
httpOnly: true,
secure: isSecure,
sameSite: 'lax',
maxAge: 0,
path: '/'
})
return {
success: false,
message: '密码已修改,请重新登录'
}
}
}
return {
success: true,
message: '认证成功',
user: user
}
} catch (error) {
console.error('权限验证过程中出错:', error)
return {
success: false,
message: '权限验证失败'
}
}
}