import { getSession } from '$lib/server/session'; import { Permissions } from '$lib/permissions'; import { error, type RequestHandler } from '@sveltejs/kit'; import { User } from '$lib/server/database'; import { type Attributes, Op } from 'sequelize'; import { ApiError, getJavaUuid, getNoAuthUuid, RateLimitError, UserNotFoundError } from '$lib/server/minecraft'; import { UserAddSchema, UserDeleteSchema, UserEditSchema, UserListSchema } from './schema'; export const POST = (async ({ request, cookies }) => { if (getSession(cookies, { permissions: [Permissions.Users] }) == null) { return new Response(null, { status: 401 }); } const parseResult = await UserListSchema.safeParseAsync(await request.json()); if (!parseResult.success) { return new Response(null, { status: 400 }); } const data = parseResult.data; const usersFindOptions: Attributes<User> = {}; if (data.name) { Object.assign(usersFindOptions, { [Op.or]: { firstname: { [Op.like]: `%${data.name}%` }, lastname: { [Op.like]: `%${data.name}%` }, username: { [Op.like]: `%${data.name}%` } } }); } else if (data.search) { Object.assign(usersFindOptions, { [Op.or]: { username: { [Op.like]: `%${data.search}%` }, uuid: { [Op.like]: `%${data.search}%` } } }); } if (data.playertype) { usersFindOptions.playertype = data.playertype; } const users = await User.findAll({ where: usersFindOptions, attributes: data.slim ? ['username', 'uuid'] : undefined, offset: data.from || 0, limit: data.limit || 100, order: data.sort ? [[data.sort.key, data.sort.asc ? 'ASC' : 'DESC']] : undefined }); return new Response(JSON.stringify(users)); }) satisfies RequestHandler; export const PATCH = (async ({ request, cookies }) => { if (getSession(cookies, { permissions: [Permissions.Users] }) == null) { return new Response(null, { status: 401 }); } const parseResult = await UserEditSchema.safeParseAsync(await request.json()); if (!parseResult.success) { return new Response(null, { status: 400 }); } const data = parseResult.data; const user = await User.findOne({ where: { id: data.id } }); if (!user) { return new Response(null, { status: 400 }); } if (data.firstname) user.firstname = data.firstname; if (data.lastname) user.lastname = data.lastname; if (data.birthday) user.birthday = data.birthday; if (data.telephone) user.telephone = data.telephone; if (data.username) user.username = data.username; if (data.playertype) user.playertype = data.playertype; if (data.uuid) user.uuid = data.uuid; await user.save(); return new Response(); }) satisfies RequestHandler; export const PUT = (async ({ request, cookies }) => { if (getSession(cookies, { permissions: [Permissions.Users] }) == null) { return new Response(null, { status: 401 }); } const parseResult = await UserAddSchema.safeParseAsync(await request.json()); if (!parseResult.success) { return new Response(null, { status: 400 }); } const data = parseResult.data; let uuid: string | null; try { switch (data.playertype) { case 'java': uuid = await getJavaUuid(data.username); break; case 'bedrock': uuid = null; // uuid = await getBedrockUuid(username); break; case 'noauth': uuid = getNoAuthUuid(data.username); break; default: throw new Error(`invalid player type (${data.playertype})`); } } catch (e) { if (e instanceof UserNotFoundError) { throw error(400, `Der Spielername ${data.username} existiert nicht`); } else if (e instanceof ApiError) { console.error((e as Error).message); uuid = null; } else if (e instanceof RateLimitError) { console.error(`uuid request rate limited for user '${data.username}'`); uuid = null; } else { console.error((e as Error).message); throw error(500); } } if (uuid && (await User.findOne({ where: { uuid: uuid } }))) { throw error(400, 'Dieser Minecraft-Account wurde bereits registriert'); } else if ( await User.findOne({ where: { firstname: data.firstname, lastname: data.lastname, birthday: new Date(data.birthday).toUTCString() } }) ) { throw error(400, 'Ein Nutzer mit demselben Namen und Geburtstag wurde bereits registriert'); } await User.create({ firstname: data.firstname, lastname: data.lastname, birthday: new Date(data.birthday).toUTCString(), telephone: data.telephone, username: data.username, playertype: data.playertype, password: null, uuid: uuid }); return new Response(); }) satisfies RequestHandler; export const DELETE = (async ({ request, cookies }) => { if (getSession(cookies, { permissions: [Permissions.Users] }) == null) { return new Response(null, { status: 401 }); } const parseResult = await UserDeleteSchema.safeParseAsync(await request.json()); if (!parseResult.success) { return new Response(null, { status: 400 }); } const data = parseResult.data; await User.destroy({ where: { id: data.id } }); return new Response(); }) satisfies RequestHandler;