veza/apps/web/src/features/auth/services/authService.ts
2025-12-03 22:56:50 +01:00

201 lines
5.3 KiB
TypeScript

import { apiClient } from '@/services/api/client';
import axios, { AxiosError } from 'axios';
import type {
LoginFormData,
RegisterFormData,
ForgotPasswordFormData,
ResetPasswordFormData,
} from '../types';
export interface AuthResponse {
user: {
id: number;
email: string;
username?: string;
};
token: {
access_token: string;
refresh_token: string;
expires_in: number;
};
}
export interface ApiError {
message: string;
code?: string;
details?: Record<string, unknown>;
}
/**
* Gère les erreurs API de manière standardisée
*/
function handleApiError(error: unknown): never {
if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError<{ error?: string; message?: string }>;
if (axiosError.response) {
// Erreur de réponse du serveur
const errorMessage =
axiosError.response.data?.error ||
axiosError.response.data?.message ||
'An error occurred';
const apiError: ApiError = {
message: errorMessage,
code: axiosError.response.status.toString(),
details: axiosError.response.data as Record<string, unknown>,
};
throw apiError;
} else if (axiosError.request) {
// Requête envoyée mais pas de réponse
throw {
message: 'Network error: Unable to connect to server',
code: 'NETWORK_ERROR',
} as ApiError;
}
}
// Erreur inconnue
throw {
message: error instanceof Error ? error.message : 'An unexpected error occurred',
code: 'UNKNOWN_ERROR',
} as ApiError;
}
/**
* Authentifie un utilisateur avec email et mot de passe
* @param data - Données de connexion (email, password)
* @returns Promise avec les tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
export async function login(data: LoginFormData): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/login', data);
return response.data;
} catch (error) {
return handleApiError(error);
}
}
/**
* Enregistre un nouvel utilisateur
* @param data - Données d'inscription (email, password, username)
* @returns Promise avec les tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
export async function register(data: RegisterFormData): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/register', {
email: data.email,
password: data.password,
password_confirm: data.confirmPassword, // Envoyer la confirmation du mot de passe
username: data.username,
});
return response.data;
} catch (error) {
return handleApiError(error);
}
}
/**
* Déconnecte l'utilisateur actuel
* @throws ApiError en cas d'erreur
*/
export async function logout(): Promise<void> {
try {
await apiClient.post('/auth/logout');
} catch (error) {
return handleApiError(error);
}
}
/**
* Rafraîchit le token d'accès avec un refresh token
* @param refreshToken - Le refresh token
* @returns Promise avec les nouveaux tokens et les informations utilisateur
* @throws ApiError en cas d'erreur
*/
export async function refreshToken(refreshToken: string): Promise<AuthResponse> {
try {
const response = await apiClient.post<AuthResponse>('/auth/refresh', {
refreshToken,
});
return response.data;
} catch (error) {
return handleApiError(error);
}
}
/**
* Demande une réinitialisation de mot de passe
* @param data - Données contenant l'email
* @throws ApiError en cas d'erreur
*/
export async function requestPasswordReset(
data: ForgotPasswordFormData
): Promise<void> {
try {
await apiClient.post('/auth/password/reset-request', data);
} catch (error) {
return handleApiError(error);
}
}
/**
* Réinitialise le mot de passe avec un token
* @param data - Données contenant le token et le nouveau mot de passe
* @throws ApiError en cas d'erreur
*/
export async function resetPassword(data: ResetPasswordFormData): Promise<void> {
try {
await apiClient.post('/auth/password/reset', {
token: data.token,
password: data.password,
});
} catch (error) {
return handleApiError(error);
}
}
/**
* Vérifie l'email avec un token de vérification
* @param token - Token de vérification
* @throws ApiError en cas d'erreur
*/
export async function verifyEmail(token: string): Promise<void> {
try {
await apiClient.get(`/auth/verify-email?token=${token}`);
} catch (error) {
return handleApiError(error);
}
}
/**
* Renvoie l'email de vérification
* @param email - Email de l'utilisateur
* @throws ApiError en cas d'erreur
*/
export async function resendVerificationEmail(email: string): Promise<void> {
try {
await apiClient.post('/auth/resend-verification', { email });
} catch (error) {
return handleApiError(error);
}
}
/**
* Vérifie la disponibilité d'un nom d'utilisateur
* @param username - Le nom d'utilisateur à vérifier
* @returns Promise avec true si disponible, false sinon
* @throws ApiError en cas d'erreur
*/
export async function checkUsernameAvailability(username: string): Promise<boolean> {
try {
const response = await apiClient.get<{ available: boolean }>(`/auth/check-username?username=${encodeURIComponent(username)}`);
return response.data.available;
} catch (error) {
return handleApiError(error);
}
}