dressed_for_succes_store/frontend/lib/auth-api.ts

199 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ApiResponse } from './api';
import { PUBLIC_API_URL } from './api';
// Интерфейс для запроса входа
interface LoginCredentials {
username: string;
password: string;
}
// Интерфейс для ответа с токеном
interface TokenResponse {
access_token: string;
token_type: string;
}
// Интерфейс для пользователя
interface User {
id: number;
email: string;
first_name: string;
last_name: string;
is_admin: boolean;
role?: string;
}
// Константа для ключа в localStorage
// Используем только один ключ 'token' для хранения токена
const TOKEN_KEY = 'token';
// API для аутентификации
export const authApi = {
// Вход в систему
login: async (email: string, password: string): Promise<ApiResponse<any>> => {
try {
// Создаем FormData для отправки данных в формате x-www-form-urlencoded
const formData = new URLSearchParams();
formData.append('username', email);
formData.append('password', password);
console.log(`Попытка входа на ${PUBLIC_API_URL}/auth/login с email: ${email}`);
// Выполняем запрос напрямую через fetch
const response = await fetch(`${PUBLIC_API_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString(),
});
const data = await response.json();
console.log('Ответ сервера при входе:', data);
// Обрабатываем ответ
if (!response.ok) {
console.error('Ошибка входа, код', response.status, data);
return {
success: false,
error: data.detail || 'Ошибка при авторизации',
message: 'Не удалось войти в систему',
};
}
// Проверяем, содержит ли ответ токен
if (!data.access_token) {
console.error('Ответ не содержит access_token');
return {
success: false,
error: 'Неверный формат ответа от сервера',
message: 'Ответ сервера не содержит токен доступа',
};
}
// Сохраняем токен в localStorage с явным преобразованием в строку
try {
localStorage.setItem(TOKEN_KEY, String(data.access_token));
console.log('Токен сохранен в localStorage:', String(data.access_token).substring(0, 20) + '...');
// Проверяем, что токен действительно сохранился
const savedToken = localStorage.getItem(TOKEN_KEY);
console.log('Проверка сохранения токена:', savedToken ? 'токен сохранен' : 'токен НЕ сохранен');
// Удаляем устаревший ключ, если он есть
if (localStorage.getItem('auth_token')) {
localStorage.removeItem('auth_token');
console.log('Устаревший ключ auth_token удален');
}
} catch (storageError) {
console.error('Ошибка при сохранении токена в localStorage:', storageError);
}
return {
success: true,
data: {
access_token: data.access_token,
token_type: data.token_type
}
};
} catch (error) {
console.error('Ошибка при входе:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Ошибка при авторизации',
message: 'Не удалось войти в систему'
};
}
},
// Получение профиля текущего пользователя
getProfile: async (): Promise<User | null> => {
try {
const token = localStorage.getItem(TOKEN_KEY);
console.log('Получение профиля с токеном:', token ? token.substring(0, 20) + '...' : 'нет токена');
if (!token) {
console.log('Токен отсутствует, профиль не запрашиваем');
return null;
}
console.log(`Запрос профиля на ${PUBLIC_API_URL}/users/me`);
const response = await fetch(`${PUBLIC_API_URL}/users/me`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorText = await response.text();
console.error(`Ошибка получения профиля: HTTP ${response.status}:`, errorText);
throw new Error(`Ошибка при получении профиля: ${response.status}`);
}
const responseData = await response.json();
console.log('Полный ответ с профилем пользователя:', responseData);
// Защита от неожиданных форматов ответа
if (!responseData) {
console.error('Ответ от сервера пуст');
return null;
}
// Обрабатываем вложенную структуру - пользователь может быть в поле 'user'
const userData = responseData.user || responseData;
console.log('Данные пользователя после обработки:', userData);
// Проверяем, что полученный объект содержит необходимые поля
if (!userData || typeof userData !== 'object' || !('id' in userData)) {
console.error('Полученные данные не содержат необходимых полей пользователя');
return null;
}
// Если у пользователя нет явного признака администратора,
// но он имеет роль "admin", устанавливаем is_admin = true
const userWithAdminCheck = { ...userData };
if (userData.role === 'admin' && userData.is_admin === undefined) {
userWithAdminCheck.is_admin = true;
console.log('Установлен флаг is_admin=true на основе роли admin');
}
// Убедимся, что is_admin является булевым значением
if (typeof userWithAdminCheck.is_admin !== 'boolean') {
userWithAdminCheck.is_admin = Boolean(userWithAdminCheck.is_admin);
console.log('Преобразовали is_admin в булево значение:', userWithAdminCheck.is_admin);
}
return userWithAdminCheck as User;
} catch (error) {
console.error('Ошибка при получении профиля:', error);
return null;
}
},
// Выход из системы
logout: (): void => {
try {
localStorage.removeItem(TOKEN_KEY);
// Удаляем устаревший ключ, если он есть
if (localStorage.getItem('auth_token')) {
localStorage.removeItem('auth_token');
}
console.log('Токен удален из localStorage');
} catch (error) {
console.error('Ошибка при удалении токена:', error);
}
},
// Проверка, авторизован ли пользователь
isAuthenticated: (): boolean => {
try {
const token = localStorage.getItem(TOKEN_KEY);
return !!token;
} catch (error) {
console.error('Ошибка при проверке токена:', error);
return false;
}
}
};