refactor: update authentication flow and cookie management
- Changed COOKIE_NAME from "peakSkills_userId" to "session_token" for better clarity. - Updated AuthClient to handle login and registration with new data structures. - Enhanced AuthWrapper to manage user sessions and display appropriate messages. - Added error handling in LoginForm and RegisterForm for better user feedback. - Refactored user service methods to streamline user creation and verification processes.
This commit is contained in:
@@ -2,8 +2,8 @@ import { cookies } from "next/headers";
|
||||
import { UserProfile } from "@/lib/types";
|
||||
import { userService } from "@/services/user-service";
|
||||
|
||||
// Constantes pour les cookies (définies ici car auth-service.ts a été supprimé)
|
||||
export const COOKIE_NAME = "peakSkills_userId";
|
||||
// Constantes pour les cookies
|
||||
export const COOKIE_NAME = "session_token";
|
||||
export const COOKIE_MAX_AGE = 30 * 24 * 60 * 60; // 30 jours
|
||||
|
||||
/**
|
||||
@@ -61,6 +61,8 @@ export class AuthService {
|
||||
|
||||
/**
|
||||
* Authentifie un utilisateur et retourne la configuration du cookie
|
||||
* Note: Cette méthode est maintenant obsolète avec le nouveau système d'auth
|
||||
* Utilisez login/register à la place
|
||||
*/
|
||||
static async authenticateUser(profile: UserProfile): Promise<{
|
||||
userUuid: string;
|
||||
@@ -78,24 +80,18 @@ export class AuthService {
|
||||
}> {
|
||||
// Vérifier si l'utilisateur existe déjà avec ces informations
|
||||
const existingUser = await userService.findUserByProfile(profile);
|
||||
let userUuid: string;
|
||||
|
||||
if (existingUser) {
|
||||
// Mettre à jour l'utilisateur existant si nécessaire
|
||||
if (existingUser.teamId !== profile.teamId) {
|
||||
await userService.updateUserByUuid(existingUser.uuid, profile);
|
||||
}
|
||||
userUuid = existingUser.uuid;
|
||||
} else {
|
||||
// Créer un nouvel utilisateur
|
||||
userUuid = await userService.upsertUserUuid(profile);
|
||||
if (!existingUser) {
|
||||
throw new Error(
|
||||
"Utilisateur non trouvé. Veuillez vous connecter avec votre email et mot de passe."
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
userUuid,
|
||||
userUuid: existingUser.uuid,
|
||||
cookieConfig: {
|
||||
name: COOKIE_NAME,
|
||||
value: userUuid,
|
||||
value: existingUser.uuid,
|
||||
options: {
|
||||
maxAge: COOKIE_MAX_AGE,
|
||||
httpOnly: true,
|
||||
@@ -106,4 +102,25 @@ export class AuthService {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une nouvelle session pour un utilisateur
|
||||
*/
|
||||
static async createSession(userUuid: string): Promise<string> {
|
||||
// Pour l'instant, on utilise l'UUID comme token de session
|
||||
// Plus tard, on pourra implémenter un système de JWT ou de sessions en base
|
||||
return userUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide un token de session et retourne l'UUID utilisateur
|
||||
*/
|
||||
static async validateSession(sessionToken: string): Promise<string | null> {
|
||||
// Pour l'instant, on considère que le token est valide s'il correspond à un UUID
|
||||
// Plus tard, on pourra ajouter une validation plus robuste
|
||||
if (sessionToken && sessionToken.length > 0) {
|
||||
return sessionToken;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getPool } from "./database";
|
||||
import { userService } from "./user-service";
|
||||
import { AuthService } from "./auth-service";
|
||||
import {
|
||||
UserEvaluation,
|
||||
UserProfile,
|
||||
@@ -121,7 +122,7 @@ export class EvaluationService {
|
||||
await client.query("BEGIN");
|
||||
|
||||
// 1. Upsert user avec UUID
|
||||
const userUuid = await userService.upsertUserUuid(evaluation.profile);
|
||||
const userUuid = await AuthService.getUserUuidFromCookie();
|
||||
|
||||
// 2. Upsert user_evaluation avec user_uuid
|
||||
const userEvalQuery = `
|
||||
@@ -413,7 +414,15 @@ export class EvaluationService {
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
|
||||
const userUuid = await userService.upsertUserUuid(profile);
|
||||
// Trouver l'utilisateur existant au lieu d'en créer un nouveau
|
||||
const existingUser = await userService.findUserByProfile(profile);
|
||||
if (!existingUser) {
|
||||
throw new Error(
|
||||
"Utilisateur non trouvé. Veuillez vous connecter avec votre email et mot de passe."
|
||||
);
|
||||
}
|
||||
|
||||
const userUuid = existingUser.uuid;
|
||||
|
||||
// Upsert user_evaluation avec user_uuid
|
||||
const userEvalResult = await client.query(
|
||||
@@ -609,7 +618,7 @@ export class EvaluationService {
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
|
||||
const userUuid = await userService.upsertUserUuid(profile);
|
||||
const userUuid = await AuthService.getUserUuidFromCookie();
|
||||
|
||||
// Supprimer directement la skill evaluation
|
||||
const deleteQuery = `
|
||||
|
||||
@@ -4,51 +4,9 @@ import { UserProfile } from "../lib/types";
|
||||
export class UserService {
|
||||
/**
|
||||
* Crée ou met à jour un utilisateur et retourne son UUID
|
||||
* Note: Cette méthode est pour la compatibilité avec l'ancien système
|
||||
* Les nouveaux utilisateurs doivent utiliser createUser avec email/password
|
||||
*/
|
||||
async upsertUserUuid(profile: UserProfile): Promise<string> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
// Créer un nouvel utilisateur avec UUID auto-généré
|
||||
const insertQuery = `
|
||||
INSERT INTO users (first_name, last_name, team_id, uuid_id)
|
||||
VALUES ($1, $2, $3, uuid_generate_v4())
|
||||
RETURNING uuid_id
|
||||
`;
|
||||
|
||||
const result = await client.query(insertQuery, [
|
||||
profile.firstName,
|
||||
profile.lastName,
|
||||
profile.teamId,
|
||||
]);
|
||||
|
||||
return result.rows[0].uuid_id;
|
||||
} catch (error: any) {
|
||||
// Si erreur de contrainte unique, l'utilisateur existe déjà
|
||||
if (
|
||||
error.code === "23505" &&
|
||||
error.constraint === "users_first_name_last_name_team_id_key"
|
||||
) {
|
||||
// Récupérer l'utilisateur existant
|
||||
const existingUserQuery = `
|
||||
SELECT uuid_id FROM users
|
||||
WHERE first_name = $1 AND last_name = $2 AND team_id = $3
|
||||
`;
|
||||
|
||||
const existingUser = await client.query(existingUserQuery, [
|
||||
profile.firstName,
|
||||
profile.lastName,
|
||||
profile.teamId,
|
||||
]);
|
||||
|
||||
return existingUser.rows[0].uuid_id;
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un utilisateur existant par son UUID
|
||||
@@ -314,6 +272,132 @@ export class UserService {
|
||||
throw new Error("Failed to fetch users");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un utilisateur par son email
|
||||
*/
|
||||
async getUserByEmail(email: string): Promise<{
|
||||
uuid_id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
team_id: string;
|
||||
} | null> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
const query = `
|
||||
SELECT uuid_id, first_name, last_name, email, team_id
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [email]);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.rows[0];
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouvel utilisateur avec email et mot de passe hashé
|
||||
*/
|
||||
async createUser(data: {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
passwordHash: string;
|
||||
teamId: string;
|
||||
}): Promise<{
|
||||
uuid_id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
team_id: string;
|
||||
} | null> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
const query = `
|
||||
INSERT INTO users (first_name, last_name, email, password_hash, team_id, uuid_id)
|
||||
VALUES ($1, $2, $3, $4, $5, uuid_generate_v4())
|
||||
RETURNING uuid_id, first_name, last_name, email, team_id
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [
|
||||
data.firstName,
|
||||
data.lastName,
|
||||
data.email,
|
||||
data.passwordHash,
|
||||
data.teamId,
|
||||
]);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.rows[0];
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie les identifiants de connexion
|
||||
*/
|
||||
async verifyCredentials(
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<{
|
||||
uuid_id: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
team_id: string;
|
||||
} | null> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
const query = `
|
||||
SELECT uuid_id, first_name, last_name, email, team_id, password_hash
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
`;
|
||||
|
||||
const result = await client.query(query, [email]);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = result.rows[0];
|
||||
|
||||
// Vérifier le mot de passe
|
||||
const bcrypt = require("bcryptjs");
|
||||
const isValidPassword = await bcrypt.compare(
|
||||
password,
|
||||
user.password_hash
|
||||
);
|
||||
|
||||
if (!isValidPassword) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retourner l'utilisateur sans le hash du mot de passe
|
||||
const { password_hash, ...userWithoutPassword } = user;
|
||||
return userWithoutPassword;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Instance singleton
|
||||
|
||||
Reference in New Issue
Block a user