import { ApiRequestOptions } from '../hooks/useApi'; import api from '../api'; import { addCSRFTokenToHeaders } from '../utils/csrfUtils'; // ============================================================================ // TYPES & INTERFACES // ============================================================================ export interface LoginRequest { username: string; password: string; } export interface LoginResponse { type: 'local_auth_success'; accessToken?: string; tokenType?: string; authenticationAuthority?: string; label?: any; fieldLabels?: any; } export interface RegisterData { username: string; email: string; fullName: string; language?: string; enabled?: boolean; privilege?: string; registrationType?: 'personal' | 'company'; companyName?: string; } export interface RegisterRequest { userData: { username: string; email: string; fullName: string; language: string; enabled: boolean; privilege: string; authenticationAuthority: string; }; frontendUrl: string; registrationType?: string; companyName?: string; } export interface PasswordResetRequestResponse { success: boolean; message: string; } export interface PasswordResetResponse { success: boolean; message: string; } export interface RegisterResponse { success: boolean; message?: string; user?: { id: string; username: string; email: string; fullName: string; language: string; enabled: boolean; privilege: string; }; } export interface MsalRegisterData { username: string; email: string; fullName: string; language?: string; } export interface UsernameAvailabilityRequest { username: string; authenticationAuthority?: string; } export interface UsernameAvailabilityResponse { username: string; authenticationAuthority: string; available: boolean; message: string; } // User-Typ wird aus userApi.ts importiert // Hier nur für Rückwärtskompatibilität export interface AuthUser { id: string; username: string; email: string; fullName: string; language: string; enabled: boolean; roleLabels?: string[]; authenticationAuthority: string; isSysAdmin?: boolean; isPlatformAdmin?: boolean; [key: string]: any; } // Type for the request function passed to API functions export type ApiRequestFunction = (options: ApiRequestOptions) => Promise; // ============================================================================ // API REQUEST FUNCTIONS // ============================================================================ /** * Login with username and password * Endpoint: POST /api/local/login */ export async function loginApi(loginData: LoginRequest): Promise { // Create the form data in the exact format FastAPI OAuth2 expects const params = new URLSearchParams(); params.append('username', loginData.username); params.append('password', loginData.password); params.append('grant_type', 'password'); params.append('scope', ''); params.append('client_id', ''); params.append('client_secret', ''); // Prepare headers with CSRF token if available const headers: Record = { 'Content-Type': 'application/x-www-form-urlencoded' }; // Add CSRF token if available (for new security implementation) addCSRFTokenToHeaders(headers); // Use the existing api instance with custom headers for this request const response = await api.post('/api/local/login', params, { headers }); return response.data; } /** * Fetch current user data * Endpoint: GET /api/local/me | /api/msft/me | /api/google/me */ export async function fetchCurrentUserApi(authAuthority?: string): Promise { let endpoint = '/api/local/me'; if (authAuthority === 'msft') { endpoint = '/api/msft/me'; } else if (authAuthority === 'google') { endpoint = '/api/google/me'; } const response = await api.get(endpoint); return response.data; } /** * Register a new user (magic link based - no password required) * Endpoint: POST /api/local/register * * After registration, user receives an email with a magic link to set their password. */ export async function registerApi(registerData: RegisterData): Promise { // Prepare data to match backend expectations (no password - magic link flow) const dataToSend: RegisterRequest = { userData: { username: registerData.username, email: registerData.email, fullName: registerData.fullName, language: registerData.language || 'de', enabled: registerData.enabled !== undefined ? registerData.enabled : true, privilege: registerData.privilege || 'user', authenticationAuthority: 'local' }, frontendUrl: window.location.origin, registrationType: registerData.registrationType, companyName: registerData.companyName, }; // Prepare headers with CSRF token if available const headers: Record = { 'Content-Type': 'application/json' }; // Add CSRF token if available (for new security implementation) addCSRFTokenToHeaders(headers); const response = await api.post('/api/local/register', dataToSend, { headers }); const userData: any = response.data; return { success: true, message: 'Registration successful - check email for password setup link', user: userData && typeof userData === 'object' && 'id' in userData ? { id: String(userData.id || ''), username: String(userData.username || ''), email: String(userData.email || ''), fullName: String(userData.fullName || ''), language: String(userData.language || 'de'), enabled: Boolean(userData.enabled !== false), privilege: String(userData.privilege || 'user') } : undefined }; } /** * Request password reset by username * Endpoint: POST /api/local/password-reset-request * * Sends a reset email to the user's registered email address. */ export async function requestPasswordResetApi(username: string): Promise { const headers: Record = { 'Content-Type': 'application/json' }; addCSRFTokenToHeaders(headers); const response = await api.post( '/api/local/password-reset-request', { username, frontendUrl: window.location.origin }, { headers } ); return response.data; } /** * Reset password using token from magic link * Endpoint: POST /api/local/password-reset */ export async function resetPasswordApi(token: string, password: string): Promise { const headers: Record = { 'Content-Type': 'application/json' }; addCSRFTokenToHeaders(headers); const response = await api.post( '/api/local/password-reset', { token, password }, { headers } ); return response.data; } /** * Register with Microsoft account * Endpoint: POST /api/msft/register */ export async function registerWithMsalApi( request: ApiRequestFunction, userData: MsalRegisterData ): Promise { const response = await request({ url: '/api/msft/register', method: 'post', data: userData, additionalConfig: { headers: { 'Content-Type': 'application/json' } } }); const responseData: any = response; return { success: true, message: 'Registration successful', user: responseData && typeof responseData === 'object' && 'id' in responseData ? { id: String(responseData.id || ''), username: String(responseData.username || ''), email: String(responseData.email || ''), fullName: String(responseData.fullName || ''), language: String(responseData.language || 'en'), enabled: Boolean((responseData as any).enabled !== false), privilege: String((responseData as any).privilege || 'user') } : undefined }; } /** * Check username availability * Endpoint: GET /api/local/available */ export async function checkUsernameAvailabilityApi( username: string, authenticationAuthority: string = 'local' ): Promise { const response = await api.get('/api/local/available', { params: { username, authenticationAuthority } }); return response.data; } /** * Logout current user * Endpoint: POST /api/local/logout */ export async function logoutApi(): Promise { await api.post('/api/local/logout'); }