/* SPDX-FileCopyrightText: © 2025 Hornwitser SPDX-License-Identifier: AGPL-3.0-or-later */ import { readUsers, writeUsers, nextUserId, type ServerUser, readAuthenticationMethods, nextAuthenticationMethodId, writeAuthenticationMethods } from "~/server/database"; import { broadcastEvent } from "~/server/streams"; import type { ApiSession } from "~/shared/types/api"; export default defineEventHandler(async (event): Promise => { let session = await getServerSession(event, false); if (session?.accountId !== undefined) { throw createError({ status: 409, message: "Cannot create account while logged in to an account." }); } const body = await readBody(event); const name = body?.name; const users = await readUsers(); let user: ServerUser; if (typeof name === "string") { if (name === "") { throw createError({ status: 400, message: "Name cannot be blank", }); } if (users.some(user => user.name && user.name.toLowerCase() === name.toLowerCase())) { throw createError({ status: 409, message: "User already exists", }); } const firstUser = users.every(user => user.type === "anonymous"); user = { id: await nextUserId(), updatedAt: new Date().toISOString(), type: firstUser ? "admin" : "regular", name, }; } else if (name === undefined) { user = { id: await nextUserId(), updatedAt: new Date().toISOString(), type: "anonymous", }; } else { throw createError({ status: 400, message: "Invalid name", }); } if (user.type !== "anonymous") { if (!session?.authenticationProvider) { throw createError({ statusCode: 409, statusMessage: "Conflict", message: "User account need an authentication method associated with it.", }); } const authMethods = await readAuthenticationMethods(); const method = authMethods.find(method => ( method.provider === session.authenticationProvider && method.slug === session.authenticationSlug )); if (method) { throw createError({ statusCode: 409, statusMessage: "Conflict", message: "A user is already associated with the authentication method", }); } authMethods.push({ id: await nextAuthenticationMethodId(), userId: user.id, provider: session.authenticationProvider, slug: session.authenticationSlug!, name: session.authenticationName!, }) await writeAuthenticationMethods(authMethods); } users.push(user); await writeUsers(users); await broadcastEvent({ type: "user-update", data: user, }); const newSession = await setServerSession(event, user); return await serverSessionToApi(event, newSession); })