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

164 lines
4.7 KiB
TypeScript

import { apiKeyPermissions, apiKeys, db } from '~/drizzle/db'
import { eq } from 'drizzle-orm'
import { z } from 'zod'
import { getBeijingTime } from '~/utils/timeUtils'
/**
* 更新API Key
* PUT /api/admin/api-keys/[id]
*/
// 请求体验证schema
const updateApiKeySchema = z.object({
name: z
.string()
.min(1, 'API Key名称不能为空')
.max(100, 'API Key名称不能超过100个字符')
.optional(),
description: z.string().max(500, '描述不能超过500个字符').optional().nullable(),
isActive: z.boolean().optional(),
expiresAt: z.string().optional().nullable(),
permissions: z
.array(z.enum(['schedules:read', 'songs:read']))
.min(1, '至少需要选择一个权限')
.optional()
})
export default defineEventHandler(async (event) => {
// 检查用户权限 - 只有超级管理员可以管理API Key
const user = event.context.user
if (!user || user.role !== 'SUPER_ADMIN') {
throw createError({
statusCode: 403,
statusMessage: '只有超级管理员可以管理API Key'
})
}
const apiKeyId = getRouterParam(event, 'id')
if (!apiKeyId) {
throw createError({
statusCode: 400,
statusMessage: 'API Key ID不能为空'
})
}
try {
// 验证请求体
const body = await readBody(event)
const validatedData = updateApiKeySchema.parse(body)
// 检查API Key是否存在
const existingApiKey = await db
.select({ id: apiKeys.id })
.from(apiKeys)
.where(eq(apiKeys.id, apiKeyId))
.limit(1)
if (existingApiKey.length === 0) {
throw createError({
statusCode: 404,
statusMessage: 'API Key不存在'
})
}
// 处理过期时间
let expiresAt = undefined
if ('expiresAt' in validatedData) {
if (validatedData.expiresAt === null) {
expiresAt = null
} else if (validatedData.expiresAt) {
try {
// 处理预设选项格式 (3d, 7d, 30d, 60d, 90d)
if (validatedData.expiresAt.match(/^\d+d$/)) {
const days = parseInt(validatedData.expiresAt.replace('d', ''))
expiresAt = getBeijingTime()
expiresAt.setDate(expiresAt.getDate() + days)
} else {
// 处理传统的日期时间格式(向后兼容)
expiresAt = new Date(validatedData.expiresAt)
// 验证日期是否有效
if (isNaN(expiresAt.getTime())) {
throw createError({
statusCode: 400,
statusMessage: '无效的过期时间格式'
})
}
// 验证过期时间不能是过去的时间
if (expiresAt <= getBeijingTime()) {
throw createError({
statusCode: 400,
statusMessage: '过期时间不能是过去的时间'
})
}
}
} catch (error: any) {
if (error.statusCode) {
throw error
}
throw createError({
statusCode: 400,
statusMessage: '无效的过期时间格式'
})
}
}
}
// 开始事务
const result = await db.transaction(async (tx) => {
// 准备更新数据
const updateData: any = {}
if (validatedData.name !== undefined) updateData.name = validatedData.name
if ('description' in validatedData) updateData.description = validatedData.description
if (validatedData.isActive !== undefined) updateData.isActive = validatedData.isActive
if ('expiresAt' in validatedData) updateData.expiresAt = expiresAt
// 更新API Key基本信息
await tx.update(apiKeys).set(updateData).where(eq(apiKeys.id, apiKeyId))
// 更新权限(如果提供了权限数据)
if (validatedData.permissions) {
// 删除现有权限
await tx.delete(apiKeyPermissions).where(eq(apiKeyPermissions.apiKeyId, apiKeyId))
// 插入新权限
const permissionValues = validatedData.permissions.map((permission) => ({
apiKeyId,
permission
}))
await tx.insert(apiKeyPermissions).values(permissionValues)
}
return { apiKeyId }
})
return {
success: true,
message: 'API Key更新成功',
data: {
id: result.apiKeyId
}
}
} catch (error: any) {
if (error.statusCode) {
throw error
}
// 处理Zod验证错误
if (error.name === 'ZodError') {
throw createError({
statusCode: 400,
statusMessage: `请求参数验证失败: ${error.errors.map((e: any) => e.message).join(', ')}`
})
}
throw createError({
statusCode: 500,
statusMessage: `更新API Key失败: ${error.message}`
})
}
})