JessieExcel/api/middleware/requireAuth.ts
2026-03-25 01:54:12 +08:00

47 lines
1.4 KiB
TypeScript

import type { NextFunction, Request, Response } from 'express'
import { verifyToken } from '../auth.js'
import { getDb } from '../db.js'
import type { PublicUser, Role, UserRecord } from '../../shared/types.js'
export type AuthedRequest = Request & { user: PublicUser }
const findUserById = (users: UserRecord[], id: string): UserRecord | undefined =>
users.find((u) => u.id === id)
export const requireAuth = async (
req: Request,
res: Response,
next: NextFunction,
): Promise<void> => {
const header = req.headers.authorization
const token = header?.startsWith('Bearer ') ? header.slice(7) : ''
const decoded = token ? verifyToken(token) : null
if (!decoded) {
res.status(401).json({ success: false, error: 'UNAUTHORIZED' })
return
}
const db = await getDb()
const record = findUserById(db.users, decoded.userId)
if (!record || record.status !== 'active') {
res.status(401).json({ success: false, error: 'UNAUTHORIZED' })
return
}
const { passwordHash: _pw, ...user } = record
;(req as AuthedRequest).user = user
next()
}
export const requireRole = (roles: Role[]) => {
return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
const user = (req as AuthedRequest).user
if (!user || !roles.includes(user.role)) {
res.status(403).json({ success: false, error: 'FORBIDDEN' })
return
}
next()
}
}