diff --git a/backend/controllers/adminController.js b/backend/controllers/adminController.js index 214c683..4a7c468 100644 --- a/backend/controllers/adminController.js +++ b/backend/controllers/adminController.js @@ -138,7 +138,6 @@ const toggleUserActive = async (req, res) => { await user.save(); // Получаем глобальный массив активных пользователей из server.js - // Это напрямую обращается к глобальной переменной в server.js const activeUsers = req.app.get('activeUsers') || []; console.log(`[AdminController] Активные пользователи:`, activeUsers); @@ -147,42 +146,81 @@ const toggleUserActive = async (req, res) => { if (wasActive && !user.isActive) { console.log(`[AdminController] Блокировка пользователя ${userId}. Причина: ${reason || 'Не указана'}`); + // Создаем объект с информацией о блокировке + const blockData = { + message: 'Ваш аккаунт был заблокирован администратором.', + reason: reason || 'Нарушение правил сервиса', + timestamp: new Date().toISOString(), + blocked: true, + userId: user._id.toString() + }; + + // Отправляем глобальное событие блокировки всем клиентам + // Это обеспечит получение уведомления даже если в activeUsers неактуальная информация + io.emit('global_user_blocked', { + userId: user._id.toString(), + timestamp: new Date().toISOString() + }); + // Ищем пользователя среди активных пользователей const userSockets = activeUsers.filter(u => u.userId === userId); console.log(`[AdminController] Найдено активных записей пользователя: ${userSockets.length}`); + // Пытаемся отправить уведомление через все возможные сокеты + let notificationSent = false; + if (userSockets.length > 0) { - userSockets.forEach(userSocket => { + for (const userSocket of userSockets) { try { - const socket = io.sockets.sockets.get(userSocket.socketId); - if (socket) { - console.log(`[AdminController] Отправка уведомления о блокировке на сокет: ${userSocket.socketId}`); - socket.emit("account_blocked", { - message: 'Ваш аккаунт был заблокирован администратором.', - reason: reason || 'Нарушение правил сервиса', - timestamp: new Date().toISOString(), - blocked: true - }); + // Безопасно получаем сокет и проверяем его существование + if (io.sockets && io.sockets.sockets) { + const socket = io.sockets.sockets.get(userSocket.socketId); - // Принудительно отключаем сокет - setTimeout(() => { - try { - console.log(`[AdminController] Принудительное отключение сокета: ${userSocket.socketId}`); - socket.disconnect(true); - } catch (socketError) { - console.error(`[AdminController] Ошибка при отключении сокета ${userSocket.socketId}:`, socketError); - } - }, 500); + if (socket && socket.connected) { + console.log(`[AdminController] Отправка уведомления о блокировке на сокет: ${userSocket.socketId}`); + socket.emit("account_blocked", blockData); + notificationSent = true; + + // Принудительно отключаем сокет + setTimeout(() => { + try { + console.log(`[AdminController] Принудительное отключение сокета: ${userSocket.socketId}`); + socket.disconnect(true); + } catch (socketError) { + console.error(`[AdminController] Ошибка при отключении сокета ${userSocket.socketId}:`, socketError); + } + }, 500); + } else { + console.log(`[AdminController] Сокет не найден или не подключен для ID: ${userSocket.socketId}`); + } } else { - console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`); + console.log(`[AdminController] Коллекция сокетов недоступна`); } } catch (socketError) { console.error(`[AdminController] Ошибка при обработке сокета ${userSocket.socketId}:`, socketError); } - }); + } } else { console.log(`[AdminController] Пользователь ${userId} не найден в активных соединениях`); } + + // Очищаем устаревшие записи в списке активных пользователей + try { + const updatedActiveUsers = activeUsers.filter(u => { + // Оставляем записи, которые не принадлежат заблокированному пользователю + return u.userId !== userId; + }); + + // Обновляем список активных пользователей + req.app.set('activeUsers', updatedActiveUsers); + console.log(`[AdminController] Список активных пользователей обновлен, удалены записи для ${userId}`); + } catch (error) { + console.error(`[AdminController] Ошибка при обновлении списка активных пользователей:`, error); + } + + if (!notificationSent) { + console.log(`[AdminController] Уведомление о блокировке не было отправлено напрямую, но было отправлено глобальное уведомление`); + } } // Если пользователь был неактивным и теперь разблокируется else if (!wasActive && user.isActive) { @@ -201,8 +239,6 @@ const toggleUserActive = async (req, res) => { }; // Отправляем событие разблокировки всем клиентам (анонимно) - // Это необходимо, чтобы клиент, который залогинен с другого устройства, - // также получил уведомление о разблокировке io.emit('global_user_unblocked', { userId: user._id.toString(), timestamp: new Date().toISOString() @@ -210,24 +246,36 @@ const toggleUserActive = async (req, res) => { // Ищем пользователя среди активных пользователей (на случай, если он онлайн с другим аккаунтом) const userSockets = activeUsers.filter(u => u.userId === userId); + let notificationSent = false; if (userSockets.length > 0) { - userSockets.forEach(userSocket => { + for (const userSocket of userSockets) { try { - const socket = io.sockets.sockets.get(userSocket.socketId); - if (socket) { - console.log(`[AdminController] Отправка уведомления о разблокировке на сокет: ${userSocket.socketId}`); - socket.emit("account_unblocked", unblockInfo); + // Безопасно получаем сокет и проверяем его существование + if (io.sockets && io.sockets.sockets) { + const socket = io.sockets.sockets.get(userSocket.socketId); + + if (socket && socket.connected) { + console.log(`[AdminController] Отправка уведомления о разблокировке на сокет: ${userSocket.socketId}`); + socket.emit("account_unblocked", unblockInfo); + notificationSent = true; + } else { + console.log(`[AdminController] Сокет не найден или не подключен для ID: ${userSocket.socketId}`); + } } else { - console.log(`[AdminController] Не найден объект сокета для ID: ${userSocket.socketId}`); + console.log(`[AdminController] Коллекция сокетов недоступна`); } } catch (socketError) { console.error(`[AdminController] Ошибка при обработке сокета ${userSocket.socketId}:`, socketError); } - }); + } } else { console.log(`[AdminController] Пользователь ${userId} не найден в активных соединениях для отправки уведомления о разблокировке`); } + + if (!notificationSent) { + console.log(`[AdminController] Уведомление о разблокировке не было отправлено напрямую, но было отправлено глобальное уведомление`); + } } res.json({ diff --git a/src/services/socketService.js b/src/services/socketService.js index b44126e..349d799 100644 --- a/src/services/socketService.js +++ b/src/services/socketService.js @@ -145,6 +145,37 @@ export const connectSocket = () => { } }); + // Обработчик глобальной блокировки + socket.on('global_user_blocked', (data) => { + console.log('[SocketService] Получено глобальное уведомление о блокировке пользователя:', data); + + // Проверяем, относится ли это к нашему пользователю + if (user.value && user.value._id === data.userId) { + console.log('[SocketService] Это уведомление относится к текущему пользователю'); + wasAccountBlocked = true; + + // Вызываем обработчик блокировки для немедленного выхода + if (typeof handleAccountBlocked === 'function') { + try { + // Создаем объект с данными блокировки + const blockData = { + message: 'Ваш аккаунт был заблокирован администратором.', + timestamp: data.timestamp, + userId: data.userId, + blocked: true, + blockType: 'global_notification' + }; + + handleAccountBlocked(blockData); + } catch (error) { + console.error('[SocketService] Ошибка при обработке глобальной блокировки:', error); + // Аварийный выход в случае ошибки + window.location.href = '/login?blocked=true'; + } + } + } + }); + return socket; } else { console.warn('[SocketService] Не удалось подключиться: пользователь не аутентифицирован или нет ID.');