фикс восстановления сессии

This commit is contained in:
Professional 2025-05-26 19:00:11 +07:00
parent c97efd7a5a
commit a9be72450c
3 changed files with 163 additions and 17 deletions

View File

@ -188,6 +188,26 @@ const toggleUserActive = async (req, res) => {
else if (!wasActive && user.isActive) { else if (!wasActive && user.isActive) {
console.log(`[AdminController] Разблокировка пользователя ${userId}`); console.log(`[AdminController] Разблокировка пользователя ${userId}`);
// Формируем объект с информацией о разблокировке для отправки через сокет
const unblockInfo = {
message: 'Ваш аккаунт был разблокирован администратором.',
timestamp: new Date().toISOString(),
userId: user._id.toString(),
unblockType: 'admin_action', // Указываем тип разблокировки
userName: user.name,
unblockData: {
canRestoreSession: true, // Флаг возможности восстановления сессии
}
};
// Отправляем событие разблокировки всем клиентам (анонимно)
// Это необходимо, чтобы клиент, который залогинен с другого устройства,
// также получил уведомление о разблокировке
io.emit('global_user_unblocked', {
userId: user._id.toString(),
timestamp: new Date().toISOString()
});
// Ищем пользователя среди активных пользователей (на случай, если он онлайн с другим аккаунтом) // Ищем пользователя среди активных пользователей (на случай, если он онлайн с другим аккаунтом)
const userSockets = activeUsers.filter(u => u.userId === userId); const userSockets = activeUsers.filter(u => u.userId === userId);
@ -197,10 +217,7 @@ const toggleUserActive = async (req, res) => {
const socket = io.sockets.sockets.get(userSocket.socketId); const socket = io.sockets.sockets.get(userSocket.socketId);
if (socket) { if (socket) {
console.log(`[AdminController] Отправка уведомления о разблокировке на сокет: ${userSocket.socketId}`); console.log(`[AdminController] Отправка уведомления о разблокировке на сокет: ${userSocket.socketId}`);
socket.emit("account_unblocked", { socket.emit("account_unblocked", unblockInfo);
message: 'Ваш аккаунт был разблокирован администратором.',
timestamp: new Date().toISOString()
});
} else { } else {
console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`); console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`);
} }

View File

@ -143,12 +143,27 @@ function handleAccountBlocked(data) {
// Сохраняем информацию о блокировке в localStorage для отображения на странице логина // Сохраняем информацию о блокировке в localStorage для отображения на странице логина
localStorage.setItem('accountBlockedInfo', JSON.stringify(blockInfo)); localStorage.setItem('accountBlockedInfo', JSON.stringify(blockInfo));
// Сохраняем данные текущей сессии для последующего восстановления при разблокировке
if (user.value && token.value) {
// Сохраняем только необходимые данные для восстановления сессии
const sessionBackup = {
userId: user.value._id,
email: user.value.email,
name: user.value.name,
token: token.value,
timestamp: new Date().toISOString()
};
// Сохраняем резервную копию данных сессии
localStorage.setItem('blockedSessionBackup', JSON.stringify(sessionBackup));
console.log('[Auth] Данные сессии сохранены для последующего восстановления');
}
// Немедленно очищаем все данные пользователя // Немедленно очищаем все данные пользователя
console.log('[Auth] Очистка данных пользователя из-за блокировки'); console.log('[Auth] Очистка данных пользователя из-за блокировки');
user.value = null; user.value = null;
token.value = null; token.value = null;
// Очистка localStorage - удаляем все ключи, которые могут содержать пользовательские данные // Очистка localStorage - удаляем токен, но сохраняем резервную копию сессии
localStorage.removeItem('userToken'); localStorage.removeItem('userToken');
localStorage.removeItem('userSettings'); localStorage.removeItem('userSettings');
localStorage.removeItem('userPreferences'); localStorage.removeItem('userPreferences');
@ -190,25 +205,90 @@ function handleAccountBlocked(data) {
} }
// Функция обработки события разблокировки аккаунта // Функция обработки события разблокировки аккаунта
function handleAccountUnblocked(data) { async function handleAccountUnblocked(data) {
console.log('Получено уведомление о разблокировке аккаунта:', data); console.log('[Auth] Получено уведомление о разблокировке аккаунта:', data);
// Удаляем информацию о блокировке, если она была сохранена // Удаляем информацию о блокировке, если она была сохранена
localStorage.removeItem('accountBlockedInfo'); localStorage.removeItem('accountBlockedInfo');
// Показываем уведомление пользователю, если он сейчас в приложении // Сохраняем информацию о разблокировке для отображения при следующем входе
// Можно использовать какую-то систему уведомлений в приложении const unblockedInfo = {
// или просто логировать это событие
// Если пользователь не залогинен, но его аккаунт был разблокирован,
// можно показать соответствующее сообщение при следующем входе
localStorage.setItem('accountUnblockedInfo', JSON.stringify({
unblocked: true, unblocked: true,
message: data?.message || 'Ваш аккаунт был разблокирован.', message: data?.message || 'Ваш аккаунт был разблокирован.',
timestamp: new Date().toISOString() timestamp: new Date().toISOString()
})); };
localStorage.setItem('accountUnblockedInfo', JSON.stringify(unblockedInfo));
console.log('Аккаунт пользователя разблокирован.'); // Проверяем, есть ли сохраненная сессия для восстановления
try {
const sessionBackupStr = localStorage.getItem('blockedSessionBackup');
if (sessionBackupStr) {
const sessionBackup = JSON.parse(sessionBackupStr);
console.log('[Auth] Найдены данные для восстановления сессии:', sessionBackup);
// Проверяем, что данные актуальны (не старше 30 дней)
const backupTime = new Date(sessionBackup.timestamp);
const now = new Date();
const thirtyDaysInMs = 30 * 24 * 60 * 60 * 1000;
if (now - backupTime < thirtyDaysInMs && sessionBackup.userId && sessionBackup.token) {
// Восстанавливаем сессию
console.log('[Auth] Восстановление сессии пользователя после разблокировки');
// Устанавливаем токен в localStorage
localStorage.setItem('userToken', sessionBackup.token);
token.value = sessionBackup.token;
// Пробуем загрузить актуальные данные пользователя
try {
console.log('[Auth] Загрузка актуальных данных пользователя');
await fetchUser();
if (user.value) {
console.log('[Auth] Сессия успешно восстановлена, перенаправление в приложение');
// Показываем уведомление о восстановлении сессии
const notificationEvent = new CustomEvent('show-toast', {
detail: {
message: 'Ваш аккаунт был разблокирован и сессия восстановлена.',
type: 'success',
duration: 5000
}
});
window.dispatchEvent(notificationEvent);
// Удаляем сохраненные данные сессии
localStorage.removeItem('blockedSessionBackup');
// Перенаправление на главную страницу или на последнюю просмотренную страницу
window.location.href = sessionBackup.lastPath || '/';
return true;
}
} catch (fetchError) {
console.error('[Auth] Ошибка при загрузке данных пользователя:', fetchError);
}
} else {
console.log('[Auth] Сохраненная сессия устарела или неполная, будет выполнен обычный вход');
// Удаляем устаревшие данные сессии
localStorage.removeItem('blockedSessionBackup');
}
} else {
console.log('[Auth] Сохраненная сессия не найдена, показываем только уведомление о разблокировке');
}
} catch (error) {
console.error('[Auth] Ошибка при восстановлении сессии после разблокировки:', error);
}
// Если мы дошли до этой точки, значит автоматическое восстановление не удалось
// или мы не нашли сохраненной сессии. Просто показываем уведомление.
console.log('[Auth] Аккаунт пользователя разблокирован без автоматического входа');
// Если пользователь уже на странице логина, добавляем параметр unblocked=true
if (window.location.pathname === '/login') {
router.replace({ path: '/login', query: { unblocked: 'true' } });
}
return false;
} }
// Экспортируем то, что понадобится в компонентах // Экспортируем то, что понадобится в компонентах

View File

@ -87,12 +87,61 @@ export const connectSocket = () => {
// Обработчик разблокировки аккаунта // Обработчик разблокировки аккаунта
socket.on('account_unblocked', (data) => { socket.on('account_unblocked', (data) => {
console.log('[SocketService] Получено уведомление о разблокировке аккаунта:', data); console.log('[SocketService] Получено уведомление о разблокировке аккаунта:', data);
// Сбрасываем флаг блокировки
wasAccountBlocked = false; wasAccountBlocked = false;
if (typeof handleAccountUnblocked === 'function') { if (typeof handleAccountUnblocked === 'function') {
handleAccountUnblocked(data); try {
console.log('[SocketService] Вызов обработчика разблокировки аккаунта');
handleAccountUnblocked(data);
} catch (error) {
console.error('[SocketService] Ошибка при обработке разблокировки аккаунта:', error);
}
} else { } else {
console.log('[SocketService] Аккаунт разблокирован, но обработчик не определен'); console.log('[SocketService] Аккаунт разблокирован, но обработчик не определен');
// Показываем уведомление с помощью стандартного API
if ('Notification' in window && Notification.permission === 'granted') {
new Notification('Аккаунт разблокирован', {
body: data.message || 'Ваш аккаунт был разблокирован администратором.'
});
}
}
});
// Новый обработчик для глобальных уведомлений о разблокировке
socket.on('global_user_unblocked', (data) => {
console.log('[SocketService] Получено глобальное уведомление о разблокировке пользователя:', data);
// Проверяем, относится ли это к нашему пользователю
if (user.value && user.value._id === data.userId) {
console.log('[SocketService] Это уведомление относится к текущему пользователю, сбрасываем флаг блокировки');
wasAccountBlocked = false;
// Проверяем наличие сохраненных данных о блокировке
const blockedInfoStr = localStorage.getItem('accountBlockedInfo');
if (blockedInfoStr) {
console.log('[SocketService] Найдена информация о блокировке, вызываем обработчик разблокировки');
if (typeof handleAccountUnblocked === 'function') {
try {
// Создаем объект с данными разблокировки
const unblockData = {
message: 'Ваш аккаунт был разблокирован администратором.',
timestamp: data.timestamp,
userId: data.userId,
unblockType: 'global_notification',
unblockData: {
canRestoreSession: true
}
};
handleAccountUnblocked(unblockData);
} catch (error) {
console.error('[SocketService] Ошибка при обработке глобальной разблокировки:', error);
}
}
}
} }
}); });