feat: 迁移自定义功能至 1.5.9.9 版本

包含音乐源限制、CI 防 OOM 优化、数据库连接池优化、管理端权限及 UI 细节定制等功能
This commit is contained in:
2026-09-12 19:26:42 +08:00
parent 34f0679117
commit 1106aeea6c
161 changed files with 18963 additions and 27900 deletions
+22 -22
View File
@@ -1,8 +1,7 @@
import { apiKeyPermissions, apiKeys, db } from '~/drizzle/db'
import crypto from 'crypto'
import { z } from 'zod'
import { getBeijingTime } from '~/utils/timeUtils'
import { apiPermissionSchema } from './permissions'
import { generateApiKey, hashApiKey } from '~~/server/utils/apiKeyUtils'
/**
* 创建API Key
@@ -17,16 +16,16 @@ const createApiKeySchema = z.object({
.optional(),
expiresAt: z.union([z.string(), z.null(), z.undefined()]).optional(),
permissions: z.array(apiPermissionSchema).min(1, '至少需要选择一个权限')
permissions: z.array(z.enum(['schedules:read', 'songs:read'])).min(1, '至少需要选择一个权限')
})
export default defineEventHandler(async (event) => {
// 检查用户权限 - 只有超级管理员可以管理 API Key
// 检查用户权限 - 只有超级管理员可以管理API Key
const user = event.context.user
if (!user || user.role !== 'SUPER_ADMIN') {
throw createError({
statusCode: 403,
message: '只有超级管理员可以管理 API Key'
statusMessage: '只有超级管理员可以管理API Key'
})
}
@@ -38,7 +37,7 @@ export default defineEventHandler(async (event) => {
// 生成API Key
const apiKey = generateApiKey()
const keyPrefix = apiKey.substring(0, 10) // vhub_xxxxx
const keyHash = await hashApiKey(apiKey)
const keyHash = crypto.createHash('sha256').update(apiKey).digest('hex')
// 处理过期时间
let expiresAt: Date | null = null
@@ -60,14 +59,14 @@ export default defineEventHandler(async (event) => {
if (isNaN(expiresAt.getTime())) {
throw createError({
statusCode: 400,
message: '无效的过期时间格式'
statusMessage: '无效的过期时间格式'
})
}
// 验证过期时间不能是过去的时间
if (expiresAt <= getBeijingTime()) {
throw createError({
statusCode: 400,
message: '过期时间不能是过去的时间'
statusMessage: '过期时间不能是过去的时间'
})
}
}
@@ -77,7 +76,7 @@ export default defineEventHandler(async (event) => {
}
throw createError({
statusCode: 400,
message: '无效的过期时间格式'
statusMessage: '无效的过期时间格式'
})
}
}
@@ -100,15 +99,7 @@ export default defineEventHandler(async (event) => {
})
.returning({ id: apiKeys.id })
const createdApiKey = apiKeyResult[0]
if (!createdApiKey) {
throw createError({
statusCode: 500,
message: '创建 API Key 失败'
})
}
const apiKeyId = createdApiKey.id
const apiKeyId = apiKeyResult[0].id
// 插入权限记录
const permissionValues = validatedData.permissions.map((permission) => ({
@@ -120,7 +111,7 @@ export default defineEventHandler(async (event) => {
return {
id: apiKeyId,
apiKey,
apiKey, // 只在创建时返回完整的API Key
name: validatedData.name,
description: validatedData.description,
keyPrefix,
@@ -144,18 +135,27 @@ export default defineEventHandler(async (event) => {
throw error
}
// 处理 Zod 验证错误
// 处理Zod验证错误
if (error.name === 'ZodError') {
throw createError({
statusCode: 400,
message: `请求参数验证失败:${error.errors.map((e: any) => e.message).join(', ')}`
statusMessage: `请求参数验证失败: ${error.errors.map((e: any) => e.message).join(', ')}`
})
}
throw createError({
statusCode: 500,
message: `创建 API Key 失败:${error.message}`
statusMessage: `创建API Key失败: ${error.message}`
})
}
})
/**
* 生成API Key
* 格式: vhub_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (37字符)
*/
function generateApiKey(): string {
const prefix = 'vhub_'
const randomBytes = crypto.randomBytes(16).toString('hex') // 32字符
return prefix + randomBytes
}