47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { fail, redirect } from '@sveltejs/kit';
|
|
import { createSession, createUser, findUser } from '$lib/server/auth';
|
|
import { createCaptcha, verifyCaptcha } from '$lib/server/captcha';
|
|
import type { Actions, PageServerLoad } from './$types';
|
|
|
|
export const load: PageServerLoad = () => {
|
|
return { captcha: createCaptcha() };
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
default: async ({ request, cookies }) => {
|
|
const form = await request.formData();
|
|
const username = String(form.get('username') ?? '').trim();
|
|
const password = String(form.get('password') ?? '');
|
|
|
|
// honeypot: real browsers leave this hidden field empty
|
|
if (String(form.get('website') ?? '') !== '') {
|
|
return fail(400, { username, error: 'Signup rejected.' });
|
|
}
|
|
if (!verifyCaptcha(String(form.get('token') ?? ''), String(form.get('captcha') ?? ''))) {
|
|
return fail(400, { username, error: 'The characters did not match - try the new image.' });
|
|
}
|
|
|
|
if (!/^[a-zA-Z0-9_.-]{3,30}$/.test(username)) {
|
|
return fail(400, {
|
|
username,
|
|
error: 'Username must be 3-30 characters (letters, digits, _ . -).'
|
|
});
|
|
}
|
|
if (password.length < 8) {
|
|
return fail(400, { username, error: 'Password must be at least 8 characters.' });
|
|
}
|
|
if (findUser(username)) {
|
|
return fail(400, { username, error: 'That username is taken.' });
|
|
}
|
|
|
|
const user = createUser(username, password);
|
|
cookies.set('session', createSession(user.id), {
|
|
path: '/',
|
|
httpOnly: true,
|
|
sameSite: 'lax',
|
|
maxAge: 30 * 86400
|
|
});
|
|
redirect(303, '/');
|
|
}
|
|
};
|