136 lines
7.4 KiB
JavaScript
136 lines
7.4 KiB
JavaScript
import { ref, computed } from 'vue';
|
||
import api from './services/api'; // Наш API сервис
|
||
import router from './router'; // Vue Router для перенаправлений
|
||
|
||
// Реактивные переменные для состояния пользователя и токена
|
||
const user = ref(null); // Данные пользователя (или null, если не вошел)
|
||
const token = ref(localStorage.getItem('userToken') || null); // Токен из localStorage или null
|
||
|
||
// Вычисляемое свойство для проверки, аутентифицирован ли пользователь
|
||
const isAuthenticated = computed(() => !!token.value && !!user.value);
|
||
|
||
// Функция для установки токена и данных пользователя
|
||
function setUserData(userData, userToken) {
|
||
user.value = userData;
|
||
token.value = userToken;
|
||
localStorage.setItem('userToken', userToken); // Сохраняем токен в localStorage
|
||
// Устанавливаем токен в заголовки Axios для последующих запросов (если не используется интерсептор)
|
||
// Однако, наш интерсептор в api.js уже делает это, так что эта строка может быть избыточна,
|
||
// но не повредит, если интерсептор по какой-то причине не сработает сразу.
|
||
// api.defaults.headers.common['Authorization'] = `Bearer ${userToken}`;
|
||
}
|
||
|
||
// Функция для загрузки данных пользователя, если токен есть (например, при обновлении страницы)
|
||
async function fetchUser() {
|
||
if (token.value) {
|
||
try {
|
||
console.log('Пытаемся загрузить пользователя с токеном из localStorage...');
|
||
const response = await api.getMe(); // Используем наш API сервис
|
||
|
||
console.log('Ответ от /auth/me:', response);
|
||
|
||
// Проверяем структуру ответа
|
||
if (!response.data) {
|
||
throw new Error('Неверный формат ответа от сервера');
|
||
}
|
||
|
||
// Сохраняем данные пользователя
|
||
user.value = response.data;
|
||
console.log('Пользователь успешно загружен:', user.value);
|
||
console.log('isAuthenticated после загрузки пользователя:', isAuthenticated.value);
|
||
} catch (error) {
|
||
console.error('Не удалось загрузить пользователя по токену:', error.response ? error.response.data : error.message);
|
||
// Если токен невалиден, очищаем его и данные пользователя
|
||
await logout(); // Вызываем logout, чтобы очистить всё
|
||
}
|
||
} else {
|
||
console.log('Токен не найден, пользователь не загружен.');
|
||
}
|
||
}
|
||
|
||
// Функция входа
|
||
async function login(credentials) {
|
||
try {
|
||
console.log('Попытка входа с учетными данными:', { email: credentials.email });
|
||
|
||
const response = await api.login(credentials);
|
||
console.log('Ответ сервера при входе:', response);
|
||
|
||
// Проверяем структуру данных в ответе
|
||
if (!response.data || !response.data.token) {
|
||
throw new Error('Неверный формат ответа от сервера: отсутствует токен');
|
||
}
|
||
|
||
// response.data должен содержать { _id, name, email, token, message }
|
||
const { token: userToken, ...userData } = response.data;
|
||
|
||
// Убедимся, что userData содержит необходимые поля
|
||
console.log('Данные пользователя для сохранения:', userData);
|
||
|
||
// Перед сохранением данных
|
||
console.log('isAuthenticated ДО входа:', isAuthenticated.value);
|
||
console.log('Данные пользователя ДО входа:', user.value);
|
||
|
||
// Сохраняем данные пользователя и токен
|
||
setUserData(userData, userToken);
|
||
|
||
// После сохранения данных, но до перенаправления
|
||
console.log('isAuthenticated ПОСЛЕ входа:', isAuthenticated.value);
|
||
console.log('Данные пользователя ПОСЛЕ входа:', user.value);
|
||
console.log('Токен ПОСЛЕ входа:', token.value);
|
||
|
||
// Принудительное обновление состояния
|
||
setTimeout(() => {
|
||
console.log('isAuthenticated после таймаута:', isAuthenticated.value);
|
||
}, 0);
|
||
|
||
router.push('/'); // Перенаправляем на главную после входа
|
||
return true;
|
||
} catch (error) {
|
||
console.error('Ошибка входа:', error.response ? error.response.data : error.message);
|
||
// Возвращаем сообщение об ошибке, чтобы отобразить в компоненте
|
||
throw error.response ? error.response.data : new Error('Ошибка сети или сервера при входе');
|
||
}
|
||
}
|
||
|
||
// Функция регистрации
|
||
async function register(userData) {
|
||
try {
|
||
const response = await api.register(userData);
|
||
// response.data должен содержать { _id, name, email, token, message }
|
||
const { token: userToken, ...newUserData } = response.data;
|
||
setUserData(newUserData, userToken);
|
||
// Обычно после регистрации мы либо сразу логиним пользователя, либо просим его войти.
|
||
// Здесь мы его сразу "залогинили", сохранив токен и данные.
|
||
router.push('/'); // Перенаправляем на главную (или на страницу подтверждения email, если бы она была)
|
||
return true;
|
||
} catch (error) {
|
||
console.error('Ошибка регистрации:', error.response ? error.response.data : error.message);
|
||
throw error.response ? error.response.data : new Error('Ошибка сети или сервера при регистрации');
|
||
}
|
||
}
|
||
|
||
// Функция выхода
|
||
async function logout() {
|
||
user.value = null;
|
||
token.value = null;
|
||
localStorage.removeItem('userToken');
|
||
// Удаляем токен из заголовков Axios (если устанавливали его напрямую)
|
||
// delete apiClient.defaults.headers.common['Authorization']; // apiClient не экспортируется из api.js напрямую для этого
|
||
// Наш интерсептор запросов в api.js перестанет добавлять токен, так как его не будет в localStorage.
|
||
router.push('/login'); // Перенаправляем на страницу входа
|
||
console.log('Пользователь вышел из системы.');
|
||
}
|
||
|
||
// Экспортируем то, что понадобится в компонентах
|
||
export function useAuth() {
|
||
return {
|
||
user,
|
||
token,
|
||
isAuthenticated,
|
||
login,
|
||
register,
|
||
logout,
|
||
fetchUser, // Эту функцию нужно будет вызвать при инициализации приложения
|
||
};
|
||
} |