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
+38 -47
View File
@@ -2,14 +2,7 @@ import bcrypt from 'bcryptjs'
import { db } from '~/drizzle/db'
import { users } from '~/drizzle/schema'
import { eq } from 'drizzle-orm'
import { createApiError } from '~~/server/utils/apiError'
import { getAdminPasswordViolation } from '~~/server/utils/admin-password-policy'
const normalizeRequiredText = (value: unknown) => String(value || '').trim()
const normalizeOptionalText = (value: unknown) => {
const normalized = String(value || '').trim()
return normalized || null
}
import { getRoleLevel, isRoleHigher, canManageUserRole } from '~~/server/utils/permissions'
export default defineEventHandler(async (event) => {
// 检查认证和权限
@@ -22,21 +15,22 @@ export default defineEventHandler(async (event) => {
}
const body = await readBody(event)
const normalizedName = normalizeRequiredText(body.name)
const normalizedUsername = normalizeRequiredText(body.username)
const initialPassword = typeof body.password === 'string' ? body.password : ''
// 验证必填字段
if (!normalizedName || !normalizedUsername || !initialPassword) {
if (!body.name || !body.username || !body.password) {
throw createError({
statusCode: 400,
message: '姓名、用户名和密码不能为空'
message: '姓名、账号名和密码不能为空'
})
}
const violation = getAdminPasswordViolation(initialPassword)
if (violation) {
throw createApiError(400, violation.code, violation.message)
// 验证姓名和用户名只能包含汉字
const chineseRegex = /^[\u4e00-\u9fa5]+$/
if (!chineseRegex.test(body.name) || !chineseRegex.test(body.username)) {
throw createError({
statusCode: 400,
message: '姓名和账号名只能包含汉字'
})
}
try {
@@ -44,45 +38,35 @@ export default defineEventHandler(async (event) => {
const existingUserResult = await db
.select()
.from(users)
.where(eq(users.username, normalizedUsername))
.where(eq(users.username, body.username))
.limit(1)
const existingUser = existingUserResult[0]
if (existingUser) {
throw createError({
statusCode: 400,
message: '用户名已存在'
message: '账号名已存在'
})
}
// 加密密码
const hashedPassword = await bcrypt.hash(initialPassword, 10)
const hashedPassword = await bcrypt.hash(body.password, 10)
// 角色权限控制
// 角色权限控制(统一使用 canManageUserRole 数值化级别检查)
let validRole = 'USER'
if (body.role && ['USER', 'ADMIN', 'SONG_ADMIN', 'SUPER_ADMIN'].includes(body.role)) {
// 超级管理员可以创建任何角色的用户
if (user.role === 'SUPER_ADMIN') {
validRole = body.role
}
// 管理员只能创建管理员以下的角色(USER, SONG_ADMIN)
else if (user.role === 'ADMIN') {
if (['USER', 'SONG_ADMIN'].includes(body.role)) {
validRole = body.role
} else {
throw createError({
statusCode: 403,
message: '管理员只能创建用户和歌曲管理员角色'
})
}
}
// 其他角色不能创建用户
else {
const requestedRole = body.role
if (requestedRole) {
if (!canManageUserRole(user, requestedRole)) {
const currentLevel = getRoleLevel(user.role)
const targetLevel = getRoleLevel(requestedRole)
throw createError({
statusCode: 403,
message: '没有权限创建用户'
message: isRoleHigher(requestedRole, user.role) || currentLevel <= targetLevel
? `权限不足:${user.role} 无法创建级别高于或等于自身的角色(${requestedRole})`
: `没有权限创建 ${requestedRole} 角色的用户`
})
}
validRole = requestedRole
}
// 状态验证
@@ -95,13 +79,13 @@ export default defineEventHandler(async (event) => {
const newUserResult = await db
.insert(users)
.values({
name: normalizedName,
username: normalizedUsername,
name: body.name,
username: body.username,
password: hashedPassword,
role: validRole,
status: validStatus as 'active' | 'withdrawn' | 'graduate',
grade: normalizeOptionalText(body.grade),
class: normalizeOptionalText(body.class)
grade: body.grade,
class: body.class
})
.returning({
id: users.id,
@@ -116,16 +100,23 @@ export default defineEventHandler(async (event) => {
})
const newUser = newUserResult[0]
// 清除相关缓存
try {
const { cache } = await import('~~/server/utils/cache-helpers')
await cache.deletePattern('songs:*')
await cache.deletePattern('stats:*')
console.log('[Cache] 歌曲和统计缓存已清除(用户创建)')
} catch (cacheError) {
console.warn('[Cache] 清除缓存失败:', cacheError)
}
return {
success: true,
user: newUser,
message: '用户创建成功'
}
} catch (error: any) {
} catch (error) {
console.error('创建用户失败:', error)
if (error?.statusCode) {
throw error
}
throw createError({
statusCode: 500,
message: '创建用户失败'