/** * API модуль для аутентификации */ import apiClient from '@/lib/api-client'; export interface LoginCredentials { email: string; password: string; } export interface RegisterData { email: string; password: string; password_confirm: string; first_name?: string; last_name?: string; role?: 'mentor' | 'client' | 'parent'; city?: string; timezone?: string; } export interface AuthResponse { access: string; refresh?: string; user?: any; } export interface User { id: number; email: string; first_name?: string; last_name?: string; phone?: string; role: 'mentor' | 'client' | 'parent'; is_verified?: boolean; avatar_url?: string | null; avatar?: string | null; telegram_id?: number | null; universal_code?: string; invitation_link?: string; invitation_link_token?: string; timezone?: string; language?: string; city?: string; country?: string; onboarding_tours_seen?: Record; } /** * Вход в систему */ export async function login(credentials: LoginCredentials): Promise { console.log('[auth.login] Sending request to /auth/login/', credentials.email); const response = await apiClient.post('/auth/login/', credentials); console.log('[auth.login] Raw response:', response); console.log('[auth.login] response.data:', response.data); // API возвращает { success, message, data: { user, tokens: { access, refresh } } } const data = response.data?.data; console.log('[auth.login] Parsed data:', data); console.log('[auth.login] Tokens:', data?.tokens); if (data?.tokens) { const result = { access: data.tokens.access, refresh: data.tokens.refresh, user: data.user }; console.log('[auth.login] Returning:', { ...result, access: result.access?.substring(0, 20) + '...' }); return result; } // Fallback для старого формата console.log('[auth.login] Using fallback structure'); return response.data?.data || response.data; } /** * Регистрация */ export async function register(data: RegisterData): Promise { const response = await apiClient.post('/auth/register/', data); // API возвращает { success, message, data: { user, tokens: { access, refresh } } } const responseData = response.data?.data; if (responseData?.tokens) { return { access: responseData.tokens.access, refresh: responseData.tokens.refresh, user: responseData.user }; } // Fallback для старого формата return response.data?.data || response.data; } /** * Выход из системы */ export async function logout(): Promise { await apiClient.post('/auth/logout/'); } /** * Получить текущего пользователя * Endpoint: GET /api/profile/me/ */ export async function getCurrentUser(): Promise { try { // Используем ProfileViewSet.me() - возвращает request.user console.log('[getCurrentUser] Requesting /profile/me/'); const response = await apiClient.get('/profile/me/'); console.log('[getCurrentUser] Success:', response.data); return response.data; } catch (error: any) { console.error('[getCurrentUser] Error with /profile/me/:', error); console.error('[getCurrentUser] Error status:', error.response?.status); console.error('[getCurrentUser] Error data:', error.response?.data); console.error('[getCurrentUser] Error config:', error.config?.url); // Fallback: используем UserViewSet с ID из токена const token = typeof window !== 'undefined' ? localStorage.getItem('access_token') : null; if (!token) { console.error('[getCurrentUser] No token found for fallback'); throw error; } try { const payload = JSON.parse(atob(token.split('.')[1])); const userId = payload.user_id; if (!userId) { console.error('[getCurrentUser] No user_id in token payload:', payload); throw error; } console.log('[getCurrentUser] Trying fallback /users/' + userId + '/'); const userResponse = await apiClient.get(`/users/${userId}/`); console.log('[getCurrentUser] Fallback success:', userResponse.data); return userResponse.data; } catch (e) { console.error('[getCurrentUser] Fallback error:', e); throw error; // Бросаем оригинальную ошибку, а не fallback ошибку } } } /** * Обновить access-токен по refresh-токену (запрос без Authorization, чтобы не слать истёкший токен). */ export async function refreshToken(refresh: string): Promise<{ access: string }> { const response = await apiClient.getInstance().post<{ access: string }>( '/auth/token/refresh/', { refresh }, { __skipAuth: true } as any ); return response.data; } /** * Смена пароля */ export async function changePassword( oldPassword: string, newPassword: string ): Promise { await apiClient.post('/auth/change-password/', { old_password: oldPassword, new_password: newPassword, }); } /** * Запрос на сброс пароля */ export async function requestPasswordReset(data: { email: string }): Promise { await apiClient.post('/auth/password-reset/', data); } /** * Подтверждение email по токену из письма */ export async function verifyEmail(token: string): Promise<{ success: boolean; message?: string }> { const response = await apiClient.post<{ success: boolean; message?: string }>( '/auth/verify-email/', { token }, { __skipAuth: true } as any ); return response.data; } /** * Подтверждение сброса пароля (по ссылке из письма) */ export async function confirmPasswordReset( token: string, newPassword: string, newPasswordConfirm: string ): Promise { await apiClient.post( '/auth/password-reset-confirm/', { token, new_password: newPassword, new_password_confirm: newPasswordConfirm, }, { __skipAuth: true } as any ); }