52 lines
2.4 KiB
TypeScript

import { getServerSession } from 'next-auth'
import { NextResponse } from 'next/server'
import { authOptions } from '@/lib/auth'
import { isSuperAdmin } from '@/lib/department-permission'
import { prisma } from '@/lib/prisma'
export class DetailGeneratorError extends Error {
constructor(message: string, readonly status = 400, readonly code = 'invalid_request') {
super(message)
this.name = 'DetailGeneratorError'
}
}
/** Beta access is deliberately independent of ordinary administrator roles. */
export async function assertDetailGeneratorUser(userId: string | null | undefined): Promise<string> {
if (!userId) throw new DetailGeneratorError('请先登录', 401, 'unauthenticated')
if (process.env.DETAIL_GENERATOR_ENABLED !== 'true') throw new DetailGeneratorError('详情页生成功能尚未启用', 403, 'feature_disabled')
if (!(await isSuperAdmin(userId))) {
throw new DetailGeneratorError('此功能暂仅向超级管理员开放', 403, 'forbidden')
}
const user = await prisma.user.findUnique({ where: { id: userId }, select: { status: true, isActive: true, archivedAt: true } })
const status = user?.status || (user?.isActive ? 'active' : 'pending')
if (!user || status !== 'active' || user.archivedAt) throw new DetailGeneratorError('账号当前不可用,无法使用详情页生成', 403, 'account_inactive')
return userId
}
export async function requireDetailGeneratorUser(): Promise<string> {
const session = await getServerSession(authOptions)
return assertDetailGeneratorUser((session?.user as { id?: string } | undefined)?.id)
}
export async function assertDetailGeneratorAccess(session: { user?: { id?: string } } | null): Promise<string> {
return assertDetailGeneratorUser(session?.user?.id)
}
export function detailGeneratorErrorResponse(error: unknown): NextResponse {
const known = error instanceof DetailGeneratorError
return NextResponse.json({
error: known ? error.message : '详情页操作暂未完成,请稍后重试',
code: known ? error.code : 'internal_error',
}, { status: known ? error.status : 500, headers: { 'Cache-Control': 'private, no-store' } })
}
export async function detailGeneratorRoute<T>(action: (userId: string) => Promise<T>): Promise<NextResponse> {
try {
const userId = await requireDetailGeneratorUser()
return NextResponse.json(await action(userId), { headers: { 'Cache-Control': 'private, no-store' } })
} catch (error) {
return detailGeneratorErrorResponse(error)
}
}