owltide/server/api/admin/user.patch.ts

80 lines
1.8 KiB
TypeScript
Raw Normal View History

import { readUsers, type ServerUser, writeUsers } from "~/server/database";
import { type ApiUser, apiUserPatchSchema } from "~/shared/types/api";
import { z } from "zod/v4-mini";
import { broadcastEvent } from "~/server/streams";
function serverUserToApi(user: ServerUser): ApiUser {
if (user.deleted) {
return {
id: user.id,
updatedAt: user.updatedAt,
deleted: true,
}
}
return {
id: user.id,
updatedAt: user.updatedAt,
type: user.type,
name: user.name,
};
}
export default defineEventHandler(async (event) => {
const session = await requireServerSession(event);
if (session.account.type !== "admin") {
throw createError({
statusCode: 403,
statusMessage: "Forbidden",
});
}
const { success, error, data: patch } = apiUserPatchSchema.safeParse(await readBody(event));
if (!success) {
throw createError({
status: 400,
statusText: "Bad Request",
message: z.prettifyError(error),
});
}
const users = await readUsers();
const user = users.find(user => user.id === patch.id);
if (!user || user.deleted) {
throw createError({
status: 409,
statusText: "Conflict",
message: "User does not exist",
});
}
if (patch.type) {
if (patch.type === "anonymous" || user.type === "anonymous") {
throw createError({
status: 409,
statusText: "Conflict",
message: "Anonymous user type cannot be changed.",
});
}
user.type = patch.type;
}
if (patch.name) {
if (user.type === "anonymous") {
throw createError({
status: 409,
statusText: "Conflict",
message: "Anonymous user cannot have name set.",
});
}
user.name = patch.name;
}
user.updatedAt = new Date().toISOString();
await writeUsers(users);
broadcastEvent({
type: "user-update",
data: serverUserToApi(user),
})
// Update Schedule counts.
await updateScheduleInterestedCounts(users);
})