13 changed files with 396 additions and 58 deletions
Binary file not shown.
@ -0,0 +1,85 @@ |
|||||
|
import { dbGlobal } from "drizzle-pkg/lib/db"; |
||||
|
import { users } from "drizzle-pkg/lib/schema/auth"; |
||||
|
import { eq } from "drizzle-orm"; |
||||
|
import { UNAUTHORIZED_MESSAGE } from "#server/constants/auth"; |
||||
|
import { toPublicAuthError } from "#server/service/auth/errors"; |
||||
|
|
||||
|
export default defineWrappedResponseHandler(async (event) => { |
||||
|
try { |
||||
|
const user = await event.context.auth.requireUser(); |
||||
|
if (!user) { |
||||
|
throw createError({ |
||||
|
statusCode: 401, |
||||
|
statusMessage: UNAUTHORIZED_MESSAGE, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const body = await readBody<{ |
||||
|
username?: string; |
||||
|
email?: string; |
||||
|
nickname?: string; |
||||
|
}>(event); |
||||
|
|
||||
|
if (!body || Object.keys(body).length === 0) { |
||||
|
throw createError({ |
||||
|
statusCode: 400, |
||||
|
statusMessage: "请提供要更新的字段", |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const updateData: Partial<{ |
||||
|
username: string; |
||||
|
email: string | null; |
||||
|
nickname: string | null; |
||||
|
}> = {}; |
||||
|
|
||||
|
if (body.username !== undefined) { |
||||
|
if (typeof body.username !== "string" || body.username.trim().length === 0) { |
||||
|
throw createError({ statusCode: 400, statusMessage: "用户名不能为空" }); |
||||
|
} |
||||
|
if (body.username.length < 2 || body.username.length > 50) { |
||||
|
throw createError({ statusCode: 400, statusMessage: "用户名长度需在2-50字符之间" }); |
||||
|
} |
||||
|
updateData.username = body.username.trim(); |
||||
|
} |
||||
|
|
||||
|
if (body.email !== undefined) { |
||||
|
if (body.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(body.email)) { |
||||
|
throw createError({ statusCode: 400, statusMessage: "邮箱格式不正确" }); |
||||
|
} |
||||
|
updateData.email = body.email?.trim() || null; |
||||
|
} |
||||
|
|
||||
|
if (body.nickname !== undefined) { |
||||
|
updateData.nickname = body.nickname?.trim() || null; |
||||
|
} |
||||
|
|
||||
|
if (Object.keys(updateData).length > 0) { |
||||
|
await dbGlobal |
||||
|
.update(users) |
||||
|
.set(updateData) |
||||
|
.where(eq(users.id, user.id)); |
||||
|
|
||||
|
// Invalidate me cache
|
||||
|
await event.context.cache.del(`auth:me:${user.id}`); |
||||
|
} |
||||
|
|
||||
|
// Fetch updated user data
|
||||
|
const [row] = await dbGlobal |
||||
|
.select({ |
||||
|
id: users.id, |
||||
|
username: users.username, |
||||
|
email: users.email, |
||||
|
role: users.role, |
||||
|
nickname: users.nickname, |
||||
|
avatar: users.avatar, |
||||
|
}) |
||||
|
.from(users) |
||||
|
.where(eq(users.id, user.id)) |
||||
|
.limit(1); |
||||
|
|
||||
|
return R.success({ user: row }); |
||||
|
} catch (err) { |
||||
|
throw toPublicAuthError(err); |
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,13 @@ |
|||||
|
import { deleteExecution } from "#server/service/scheduler"; |
||||
|
|
||||
|
export default defineWrappedResponseHandler(async (event) => { |
||||
|
const id = getRouterParam(event, "id"); |
||||
|
if (!id) return R.throwError(400, "Missing id", null); |
||||
|
|
||||
|
const deleted = await deleteExecution(id); |
||||
|
|
||||
|
await event.context.cache.del('scheduler:executions:1:20:all:all') |
||||
|
await event.context.cache.del('scheduler:stats') |
||||
|
|
||||
|
return R.success({ deleted }); |
||||
|
}); |
||||
@ -0,0 +1,13 @@ |
|||||
|
import { deleteAllExecutions } from "#server/service/scheduler"; |
||||
|
|
||||
|
export default defineWrappedResponseHandler(async (event) => { |
||||
|
const query = getQuery(event); |
||||
|
const taskId = query.taskId as string | undefined; |
||||
|
|
||||
|
const deleted = await deleteAllExecutions(taskId); |
||||
|
|
||||
|
await event.context.cache.del('scheduler:executions:1:20:all:all') |
||||
|
await event.context.cache.del('scheduler:stats') |
||||
|
|
||||
|
return R.success({ deleted }); |
||||
|
}); |
||||
Loading…
Reference in new issue