diff --git a/backend/controllers/authController.js b/backend/controllers/authController.js index dcaa53d..e478bb2 100644 --- a/backend/controllers/authController.js +++ b/backend/controllers/authController.js @@ -234,8 +234,22 @@ const loginUser = async (req, res, next) => { // Проверка если аккаунт неактивен (заблокирован) if (isMatch && !user.isActive && !user.isAdmin) { + console.log('[AuthController] Пользователь заблокирован, но создаем токен для восстановления сессии'); + + // Создаем токен для последующего восстановления сессии после разблокировки + const restorationToken = generateToken(user._id); + + // Обновляем дату последнего входа даже для заблокированного пользователя + user.lastSeen = new Date(); + await user.save(); + res.status(403); - throw new Error('Ваш аккаунт заблокирован. Пожалуйста, обратитесь в поддержку.'); + const error = new Error('Ваш аккаунт заблокирован. Пожалуйста, обратитесь в поддержку.'); + error.blocked = true; + error.userId = user._id; + error.restorationToken = restorationToken; // Добавляем токен для восстановления + error.userName = user.name; + throw error; } if (isMatch) { @@ -256,6 +270,19 @@ const loginUser = async (req, res, next) => { if (!res.statusCode || res.statusCode < 400) { res.status(401); } + + // Специальная обработка для заблокированных аккаунтов + if (error.blocked && error.restorationToken) { + return res.json({ + message: error.message, + blocked: true, + userId: error.userId, + restorationToken: error.restorationToken, + userName: error.userName, + stack: process.env.NODE_ENV === 'production' ? null : error.stack + }); + } + res.json({ message: error.message, stack: process.env.NODE_ENV === 'production' ? null : error.stack }); } }; diff --git a/src/auth.js b/src/auth.js index 6da0f1c..ecf8f7d 100644 --- a/src/auth.js +++ b/src/auth.js @@ -5,6 +5,7 @@ import router from './router'; // Vue Router для перенаправлен // Реактивные переменные для состояния пользователя и токена const user = ref(null); // Данные пользователя (или null, если не вошел) const token = ref(localStorage.getItem('userToken') || null); // Токен из localStorage или null +const loading = ref(false); // Состояние загрузки для операций аутентификации // Вычисляемое свойство для проверки, аутентифицирован ли пользователь const isAuthenticated = computed(() => !!token.value && !!user.value); @@ -142,69 +143,74 @@ async function fetchUser() { // Функция входа async function login(credentials) { try { - console.log('Попытка входа с учетными данными:', { email: credentials.email }); - + loading.value = true; 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); - - // Проверяем, была ли предыдущая блокировка и произошла ли разблокировка - const wasBlocked = localStorage.getItem('accountBlockedInfo'); - const sessionBackup = localStorage.getItem('blockedSessionBackup'); - - if (wasBlocked || sessionBackup) { - console.log('[Auth] Обнаружена предыдущая блокировка, пользователь теперь может войти - значит разблокирован'); + if (response?.data) { + setUserData(response.data, response.data.token); - // Очищаем данные о блокировке - localStorage.removeItem('accountBlockedInfo'); - localStorage.removeItem('blockedSessionBackup'); + // Очищаем данные о предыдущей блокировке при успешном входе + const wasBlocked = localStorage.getItem('accountBlockedInfo'); + const sessionBackup = localStorage.getItem('blockedSessionBackup'); - // Показываем уведомление о разблокировке - setTimeout(() => { - const notificationEvent = new CustomEvent('show-toast', { - detail: { - message: 'Ваш аккаунт был разблокирован. Добро пожаловать обратно!', - type: 'success', - duration: 5000 - } - }); - window.dispatchEvent(notificationEvent); - }, 1000); + if (wasBlocked || sessionBackup) { + console.log('[Auth] Обнаружена предыдущая блокировка, пользователь теперь может войти - значит разблокирован'); + + // Очищаем данные о блокировке + localStorage.removeItem('accountBlockedInfo'); + localStorage.removeItem('blockedSessionBackup'); + + // Показываем уведомление о разблокировке + setTimeout(() => { + const notificationEvent = new CustomEvent('show-toast', { + detail: { + message: 'Ваш аккаунт был разблокирован. Добро пожаловать обратно!', + type: 'success', + duration: 5000 + } + }); + window.dispatchEvent(notificationEvent); + }, 1000); + } + + router.push('/'); // Перенаправляем на главную после успешного входа + return response.data; } - - // Перед сохранением данных - 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('Ошибка сети или сервера при входе'); + console.error('[Auth] Ошибка входа:', error); + + // Обработка специального случая блокировки аккаунта + if (error.response?.status === 403 && error.response?.data?.blocked) { + const errorData = error.response.data; + console.log('[Auth] Аккаунт заблокирован, сохраняем данные для восстановления сессии'); + + // Сохраняем данные о блокировке + const blockedInfo = { + blocked: true, + message: errorData.message || 'Ваш аккаунт заблокирован администратором.', + timestamp: new Date().toISOString() + }; + localStorage.setItem('accountBlockedInfo', JSON.stringify(blockedInfo)); + + // Сохраняем данные для восстановления сессии, если есть токен восстановления + if (errorData.restorationToken && errorData.userId && errorData.userName) { + const sessionBackup = { + userId: errorData.userId, + userName: errorData.userName, + token: errorData.restorationToken, + timestamp: new Date().toISOString(), + lastPath: '/', // По умолчанию главная страница + credentials: credentials // Сохраняем credentials для повторного входа + }; + + localStorage.setItem('blockedSessionBackup', JSON.stringify(sessionBackup)); + console.log('[Auth] Сохранены данные для восстановления сессии заблокированного пользователя'); + } + } + + throw error; + } finally { + loading.value = false; } }