All checks were successful
Build Docker Image / build (push) Successful in 1m12s
- Updated user schema to include a unique username field. - Modified authentication logic to support sign-in using either email or username. - Enhanced sign-up process to require a username and validate its uniqueness. - Updated login and profile routes to reflect changes in user identification. - Adjusted frontend forms to accommodate username input alongside email.
118 lines
3.1 KiB
TypeScript
118 lines
3.1 KiB
TypeScript
import { fail, redirect } from '@sveltejs/kit';
|
|
import type { Actions } from './$types';
|
|
import type { PageServerLoad } from './$types';
|
|
import { auth } from '$lib/server/auth';
|
|
import { db } from '$lib/server/db';
|
|
import { user } from '$lib/server/db/schema';
|
|
import { APIError } from 'better-auth/api';
|
|
import { sql } from 'drizzle-orm';
|
|
|
|
export const load: PageServerLoad = async (event) => {
|
|
if (event.locals.user) {
|
|
return redirect(302, '/');
|
|
}
|
|
return {};
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
signInEmail: async (event) => {
|
|
const formData = await event.request.formData();
|
|
const identifier = formData.get('identifier')?.toString().trim() ?? formData.get('email')?.toString().trim() ?? '';
|
|
const password = formData.get('password')?.toString() ?? '';
|
|
|
|
if (!identifier) {
|
|
return fail(400, { message: 'Email ou nom d\'utilisateur requis' });
|
|
}
|
|
|
|
let email = identifier;
|
|
if (!identifier.includes('@')) {
|
|
const [foundUser] = await db
|
|
.select({ email: user.email })
|
|
.from(user)
|
|
.where(sql`lower(${user.username}) = ${identifier.toLowerCase()}`)
|
|
.limit(1);
|
|
|
|
if (!foundUser) {
|
|
return fail(400, { message: 'Identifiants invalides' });
|
|
}
|
|
|
|
email = foundUser.email;
|
|
}
|
|
|
|
try {
|
|
await auth.api.signInEmail({
|
|
body: {
|
|
email,
|
|
password,
|
|
callbackURL: '/auth/verification-success'
|
|
}
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof APIError) {
|
|
return fail(400, { message: error.message || 'Signin failed' });
|
|
}
|
|
return fail(500, { message: 'Unexpected error' });
|
|
}
|
|
|
|
return redirect(302, '/');
|
|
},
|
|
signUpEmail: async (event) => {
|
|
const formData = await event.request.formData();
|
|
const email = formData.get('email')?.toString() ?? '';
|
|
const password = formData.get('password')?.toString() ?? '';
|
|
const confirmPassword = formData.get('confirmPassword')?.toString() ?? '';
|
|
const name = formData.get('name')?.toString() ?? '';
|
|
const username = formData.get('username')?.toString().trim() ?? '';
|
|
|
|
if (!username) {
|
|
return fail(400, { message: 'Nom d\'utilisateur requis' });
|
|
}
|
|
|
|
if (!/^[a-zA-Z0-9._-]{3,30}$/.test(username)) {
|
|
return fail(400, {
|
|
message: "Le nom d'utilisateur doit contenir 3 à 30 caractères (lettres, chiffres, ., _, -)"
|
|
});
|
|
}
|
|
|
|
const [existingUsername] = await db
|
|
.select({ id: user.id })
|
|
.from(user)
|
|
.where(sql`lower(${user.username}) = ${username.toLowerCase()}`)
|
|
.limit(1);
|
|
|
|
if (existingUsername) {
|
|
return fail(400, { message: "Ce nom d'utilisateur est déjà pris" });
|
|
}
|
|
|
|
if (password !== confirmPassword) {
|
|
return fail(400, { message: 'Les mots de passe ne correspondent pas' });
|
|
}
|
|
|
|
try {
|
|
await auth.api.signUpEmail({
|
|
body: {
|
|
email,
|
|
password,
|
|
name,
|
|
username,
|
|
callbackURL: '/auth/verification-success'
|
|
}
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof APIError) {
|
|
return fail(400, { message: error.message || 'Registration failed' });
|
|
}
|
|
return fail(500, { message: 'Unexpected error' });
|
|
}
|
|
|
|
return redirect(302, '/');
|
|
},
|
|
logout: async (event) => {
|
|
await auth.api.signOut({
|
|
headers: event.request.headers
|
|
});
|
|
|
|
return redirect(302, '/');
|
|
}
|
|
};
|