Files
bakery-ia/frontend/src/api/services/auth.ts

238 lines
8.5 KiB
TypeScript
Raw Normal View History

2025-10-06 15:27:01 +02:00
// ================================================================
// frontend/src/api/services/auth.ts
// ================================================================
/**
2026-01-15 20:45:49 +01:00
* Auth Service - Atomic Registration Architecture
2025-10-06 15:27:01 +02:00
*
* Backend API structure (3-tier architecture):
* - OPERATIONS: auth_operations.py, onboarding_progress.py
*
2026-01-15 20:45:49 +01:00
* Last Updated: 2025-01-14
* Status: Complete - SetupIntent-first registration flow with 3DS support
*/
import { apiClient } from '../client';
import {
UserRegistration,
UserLogin,
TokenResponse,
RefreshTokenRequest,
PasswordChange,
PasswordReset,
UserResponse,
UserUpdate,
TokenVerificationResponse,
AuthHealthResponse,
2026-01-15 20:45:49 +01:00
RegistrationStartResponse,
RegistrationCompletionResponse,
RegistrationVerification,
} from '../types/auth';
export class AuthService {
private readonly baseUrl = '/auth';
2025-10-06 15:27:01 +02:00
// ===================================================================
2026-01-15 20:45:49 +01:00
// ATOMIC REGISTRATION: SetupIntent-First Approach
// These methods implement the secure registration flow with 3DS support
2025-10-06 15:27:01 +02:00
// ===================================================================
2026-01-15 20:45:49 +01:00
/**
* Start secure registration flow with SetupIntent-first approach
* This is the FIRST step in the atomic registration flow
* Backend: services/auth/app/api/auth_operations.py:start_registration()
*/
async startRegistration(userData: UserRegistration): Promise<RegistrationStartResponse> {
return apiClient.post<RegistrationStartResponse>(`${this.baseUrl}/start-registration`, userData);
}
2026-01-15 20:45:49 +01:00
/**
* Complete registration after 3DS verification
* This is the SECOND step in the atomic registration flow
* Backend: services/auth/app/api/auth_operations.py:complete_registration()
*/
async completeRegistration(verificationData: RegistrationVerification): Promise<RegistrationCompletionResponse> {
return apiClient.post<RegistrationCompletionResponse>(`${this.baseUrl}/complete-registration`, verificationData);
2026-01-13 22:22:38 +01:00
}
2026-01-15 20:45:49 +01:00
// ===================================================================
// OPERATIONS: Authentication
// Backend: services/auth/app/api/auth_operations.py
// ===================================================================
2026-01-14 13:15:48 +01:00
async login(loginData: UserLogin): Promise<TokenResponse> {
return apiClient.post<TokenResponse>(`${this.baseUrl}/login`, loginData);
}
async refreshToken(refreshToken: string): Promise<TokenResponse> {
const refreshData: RefreshTokenRequest = { refresh_token: refreshToken };
return apiClient.post<TokenResponse>(`${this.baseUrl}/refresh`, refreshData);
}
async verifyToken(token?: string): Promise<TokenVerificationResponse> {
// If token is provided, temporarily set it; otherwise use current token
const currentToken = apiClient.getAuthToken();
if (token && token !== currentToken) {
apiClient.setAuthToken(token);
}
const response = await apiClient.post<TokenVerificationResponse>(`${this.baseUrl}/verify`);
// Restore original token if we temporarily changed it
if (token && token !== currentToken) {
apiClient.setAuthToken(currentToken);
}
return response;
}
async logout(refreshToken: string): Promise<{ message: string }> {
const refreshData: RefreshTokenRequest = { refresh_token: refreshToken };
return apiClient.post<{ message: string }>(`${this.baseUrl}/logout`, refreshData);
}
async changePassword(passwordData: PasswordChange): Promise<{ message: string }> {
return apiClient.post<{ message: string }>(`${this.baseUrl}/change-password`, passwordData);
}
async resetPassword(resetData: PasswordReset): Promise<{ message: string }> {
return apiClient.post<{ message: string }>(`${this.baseUrl}/reset-password`, resetData);
}
2025-10-06 15:27:01 +02:00
// ===================================================================
2025-10-27 16:33:26 +01:00
// User Profile (authenticated)
// Backend: services/auth/app/api/auth_operations.py
2025-10-06 15:27:01 +02:00
// ===================================================================
async getProfile(): Promise<UserResponse> {
2025-10-27 16:33:26 +01:00
return apiClient.get<UserResponse>(`${this.baseUrl}/me`);
}
async updateProfile(updateData: UserUpdate): Promise<UserResponse> {
2025-10-27 16:33:26 +01:00
return apiClient.put<UserResponse>(`${this.baseUrl}/me`, updateData);
}
2025-10-06 15:27:01 +02:00
// ===================================================================
// OPERATIONS: Email Verification
// Backend: services/auth/app/api/auth_operations.py
// ===================================================================
async verifyEmail(
userId: string,
verificationToken: string
): Promise<{ message: string }> {
return apiClient.post<{ message: string }>(`${this.baseUrl}/verify-email`, {
user_id: userId,
verification_token: verificationToken,
});
}
2025-10-27 16:33:26 +01:00
// ===================================================================
// Account Management (self-service)
// Backend: services/auth/app/api/account_deletion.py
// ===================================================================
async deleteAccount(confirmEmail: string, password: string, reason?: string): Promise<{ message: string; deletion_date: string }> {
return apiClient.delete(`${this.baseUrl}/me/account`, {
data: {
confirm_email: confirmEmail,
password: password,
reason: reason || ''
}
});
}
2026-01-15 20:45:49 +01:00
async getAccountDeletionInfo(): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/account/deletion-info`);
}
// ===================================================================
// GDPR Consent Management
// Backend: services/auth/app/api/consent.py
// ===================================================================
async recordConsent(consentData: {
terms_accepted: boolean;
privacy_accepted: boolean;
marketing_consent?: boolean;
analytics_consent?: boolean;
consent_method: string;
consent_version?: string;
2026-01-15 20:45:49 +01:00
}): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.post(`${this.baseUrl}/me/consent`, consentData);
}
2026-01-15 20:45:49 +01:00
async getCurrentConsent(): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/consent/current`);
}
2026-01-15 20:45:49 +01:00
async getConsentHistory(): Promise<Record<string, unknown>[]> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/consent/history`);
}
async updateConsent(consentData: {
terms_accepted: boolean;
privacy_accepted: boolean;
marketing_consent?: boolean;
analytics_consent?: boolean;
consent_method: string;
consent_version?: string;
2026-01-15 20:45:49 +01:00
}): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.put(`${this.baseUrl}/me/consent`, consentData);
}
async withdrawConsent(): Promise<{ message: string; withdrawn_count: number }> {
return apiClient.post(`${this.baseUrl}/me/consent/withdraw`);
}
// ===================================================================
// Data Export (GDPR)
// Backend: services/auth/app/api/data_export.py
// ===================================================================
2026-01-15 20:45:49 +01:00
async exportMyData(): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/export`);
}
2026-01-15 20:45:49 +01:00
async getExportSummary(): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/export/summary`);
}
// ===================================================================
// Onboarding Progress
// Backend: services/auth/app/api/onboarding_progress.py
// ===================================================================
2026-01-15 20:45:49 +01:00
async getOnboardingProgress(): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.get(`${this.baseUrl}/me/onboarding/progress`);
}
2026-01-15 20:45:49 +01:00
async updateOnboardingStep(stepName: string, completed: boolean, data?: Record<string, unknown>): Promise<Record<string, unknown>> {
2025-10-27 16:33:26 +01:00
return apiClient.put(`${this.baseUrl}/me/onboarding/step`, {
step_name: stepName,
completed: completed,
data: data
});
}
async getNextOnboardingStep(): Promise<{ step: string }> {
return apiClient.get(`${this.baseUrl}/me/onboarding/next-step`);
}
async canAccessOnboardingStep(stepName: string): Promise<{ can_access: boolean }> {
return apiClient.get(`${this.baseUrl}/me/onboarding/can-access/${stepName}`);
}
async completeOnboarding(): Promise<{ success: boolean; message: string }> {
return apiClient.post(`${this.baseUrl}/me/onboarding/complete`);
}
2025-10-06 15:27:01 +02:00
// ===================================================================
// Health Check
// ===================================================================
async healthCheck(): Promise<AuthHealthResponse> {
return apiClient.get<AuthHealthResponse>(`${this.baseUrl}/health`);
}
}
2026-01-15 20:45:49 +01:00
export const authService = new AuthService();