108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { ActionError, defineAction } from 'astro:actions';
|
|
import { z } from 'astro:schema';
|
|
import { db } from '@db/database.ts';
|
|
import { getJavaUuid } from '@util/minecraft.ts';
|
|
import { getSetting, SettingKey } from '@util/settings.ts';
|
|
import { sendWebhook, WebhookAction } from '@util/webhook.ts';
|
|
|
|
function getClientIp(context: { request: Request; clientAddress: string }) {
|
|
const forwardedFor = context.request.headers.get('x-forwarded-for');
|
|
|
|
if (forwardedFor) {
|
|
const ip = forwardedFor.split(',')[0].trim();
|
|
if (ip) return ip;
|
|
}
|
|
|
|
return context.clientAddress;
|
|
}
|
|
|
|
export const signup = {
|
|
signup: defineAction({
|
|
input: z.object({
|
|
firstname: z.string().trim().min(2),
|
|
lastname: z.string().trim().min(2),
|
|
birthday: z
|
|
.string()
|
|
.date()
|
|
// this will be inaccurate as it is evaluated only once
|
|
.max(Date.now() - 1000 * 60 * 60 * 24 * 365 * 6),
|
|
phone: z.string().trim().nullable(),
|
|
username: z.string().trim(),
|
|
edition: z.enum(['java', 'bedrock']),
|
|
code: z.string().nullish()
|
|
}),
|
|
handler: async (input, context) => {
|
|
// check if code given and if so, if it's valid and nobody has already used it
|
|
if (input.code) {
|
|
const directSignup = await db.getDirectSignupByCode({ code: input.code });
|
|
|
|
if (!directSignup) {
|
|
throw new ActionError({
|
|
code: 'NOT_FOUND'
|
|
});
|
|
} else if (directSignup.user) {
|
|
throw new ActionError({
|
|
code: 'CONFLICT'
|
|
});
|
|
}
|
|
}
|
|
// check if signup is allowed
|
|
else if (!(await getSetting(db, SettingKey.SignupEnabled))) {
|
|
throw new ActionError({
|
|
code: 'FORBIDDEN',
|
|
message: 'Die Anmeldung ist derzeit deaktiviert'
|
|
});
|
|
}
|
|
// check if the user were already signed up
|
|
else if (await db.getUserByUsername({ username: input.username })) {
|
|
throw new ActionError({
|
|
code: 'CONFLICT',
|
|
message: 'Du hast dich bereits registriert'
|
|
});
|
|
}
|
|
|
|
let uuid = null;
|
|
if (input.edition == 'java') {
|
|
try {
|
|
uuid = await getJavaUuid(input.username);
|
|
} catch (_) {
|
|
throw new ActionError({
|
|
code: 'NOT_FOUND',
|
|
message: `Es wurde kein Minecraft Java Account mit dem Username ${input.username} gefunden`
|
|
});
|
|
}
|
|
}
|
|
|
|
await db.transaction(async (tx) => {
|
|
const user = await tx.addUser({
|
|
firstname: input.firstname,
|
|
lastname: input.lastname,
|
|
birthday: input.birthday,
|
|
telephone: input.phone,
|
|
username: input.username,
|
|
edition: input.edition,
|
|
uuid: uuid
|
|
});
|
|
|
|
if (input.code) {
|
|
await tx.setDirectSignupUser({ code: input.code, userId: user.id });
|
|
}
|
|
if (uuid) {
|
|
await tx.linkDirectSignupUserByUuid({ uuid: uuid, userId: user.id });
|
|
}
|
|
});
|
|
|
|
sendWebhook(WebhookAction.Signup, {
|
|
firstname: input.firstname,
|
|
lastname: input.lastname,
|
|
birthday: new Date(input.birthday).toISOString().slice(0, 10),
|
|
telephone: input.phone,
|
|
username: input.username,
|
|
edition: input.edition,
|
|
uuid: uuid,
|
|
ip: getClientIp(context)
|
|
});
|
|
}
|
|
})
|
|
};
|