const BlockedDevice = require('../models/BlockedDevice'); const User = require('../models/User'); const { blockUserDevice, unblockDevice, getBlockedDevices } = require('../middleware/deviceBlockMiddleware'); /** * Контроллер для управления блокировками устройств */ // @desc Проверка блокировки устройства // @route POST /api/security/check-device // @access Public const checkDeviceBlockStatus = async (req, res) => { try { const { fingerprint, deviceInfo } = req.body; const deviceFingerprint = fingerprint || req.deviceFingerprint; if (!deviceFingerprint) { return res.status(400).json({ message: 'Device fingerprint требуется для проверки безопасности', code: 'DEVICE_FINGERPRINT_REQUIRED' }); } console.log('[SECURITY] Проверка блокировки устройства:', deviceFingerprint.substring(0, 16) + '...'); // Проверяем, заблокировано ли устройство const blockedDevice = await BlockedDevice.isDeviceBlocked(deviceFingerprint); if (blockedDevice) { console.log('[SECURITY] Устройство заблокировано:', blockedDevice._id); // Записываем попытку доступа await blockedDevice.addBypassAttempt({ type: 'api_request', ipAddress: req.ip || req.connection.remoteAddress, userAgent: req.headers['user-agent'] }); return res.status(403).json({ blocked: true, message: 'Доступ с данного устройства заблокирован', reason: blockedDevice.reason, blockedAt: blockedDevice.blockedAt, code: 'DEVICE_BLOCKED' }); } // Обновляем информацию об устройстве if (deviceInfo) { // Можно сохранить информацию об активном устройстве для мониторинга console.log('[SECURITY] Активное устройство:', { fingerprint: deviceFingerprint.substring(0, 16) + '...', userAgent: deviceInfo.userAgent, platform: deviceInfo.platform }); } res.json({ blocked: false, message: 'Устройство не заблокировано' }); } catch (error) { console.error('[SECURITY] Ошибка при проверке блокировки устройства:', error); res.status(500).json({ message: 'Ошибка системы безопасности', code: 'SECURITY_CHECK_ERROR' }); } }; // @desc Отчет о подозрительной активности // @route POST /api/security/report-suspicious // @access Private const reportSuspiciousActivity = async (req, res) => { try { const { activities, deviceInfo } = req.body; const deviceFingerprint = req.deviceFingerprint; if (!deviceFingerprint) { return res.status(400).json({ message: 'Device fingerprint требуется для отчета', code: 'DEVICE_FINGERPRINT_REQUIRED' }); } console.log('[SECURITY] Получен отчет о подозрительной активности:', { fingerprint: deviceFingerprint.substring(0, 16) + '...', activitiesCount: activities?.length || 0, userId: req.user?._id }); // Анализируем активность на предмет угроз const riskScore = calculateRiskScore(activities, deviceInfo); if (riskScore > 80) { console.warn('[SECURITY] Высокий уровень риска обнаружен:', riskScore); // Автоматическая блокировка при высоком риске if (req.user) { await blockUserDevice( req.user._id, req.user._id, // Автоматическая блокировка `Автоматическая блокировка: высокий уровень риска (${riskScore})`, deviceFingerprint ); console.log('[SECURITY] Устройство автоматически заблокировано из-за высокого риска'); return res.status(403).json({ blocked: true, message: 'Устройство заблокировано из-за подозрительной активности', reason: 'Автоматическая блокировка системы безопасности', code: 'DEVICE_BLOCKED' }); } } // Сохраняем отчет для анализа администраторами // Можно создать отдельную модель SuspiciousActivity или логировать console.log('[SECURITY] Отчет о подозрительной активности сохранен'); res.json({ message: 'Отчет получен и обработан', riskScore, action: riskScore > 80 ? 'blocked' : 'monitored' }); } catch (error) { console.error('[SECURITY] Ошибка при обработке отчета о подозрительной активности:', error); res.status(500).json({ message: 'Ошибка обработки отчета безопасности' }); } }; // @desc Блокировка устройства (админ) // @route POST /api/admin/block-device // @access Private/Admin const blockDevice = async (req, res) => { try { const { userId, deviceFingerprint, reason } = req.body; if (!userId || !deviceFingerprint || !reason) { return res.status(400).json({ message: 'ID пользователя, device fingerprint и причина обязательны' }); } // Проверяем, существует ли пользователь const user = await User.findById(userId); if (!user) { return res.status(404).json({ message: 'Пользователь не найден' }); } // Блокируем устройство const blockedDevice = await blockUserDevice( userId, req.user._id, reason, deviceFingerprint ); console.log('[ADMIN] Устройство заблокировано администратором:', { deviceId: blockedDevice._id, userId, adminId: req.user._id, reason }); res.status(201).json({ message: 'Устройство успешно заблокировано', blockedDevice: { id: blockedDevice._id, deviceFingerprint: blockedDevice.deviceFingerprint, reason: blockedDevice.reason, blockedAt: blockedDevice.blockedAt } }); } catch (error) { console.error('[ADMIN] Ошибка при блокировке устройства:', error); res.status(500).json({ message: 'Ошибка при блокировке устройства', error: error.message }); } }; // @desc Разблокировка устройства (админ) // @route POST /api/admin/unblock-device // @access Private/Admin const unblockDeviceAdmin = async (req, res) => { try { const { deviceFingerprint, reason } = req.body; if (!deviceFingerprint) { return res.status(400).json({ message: 'Device fingerprint обязателен' }); } // Разблокируем устройство const device = await unblockDevice( deviceFingerprint, req.user._id, reason || 'Разблокировано администратором' ); console.log('[ADMIN] Устройство разблокировано администратором:', { deviceId: device._id, adminId: req.user._id, reason }); res.json({ message: 'Устройство успешно разблокировано', device: { id: device._id, deviceFingerprint: device.deviceFingerprint, unblockedAt: new Date() } }); } catch (error) { console.error('[ADMIN] Ошибка при разблокировке устройства:', error); res.status(500).json({ message: 'Ошибка при разблокировке устройства', error: error.message }); } }; // @desc Получение списка заблокированных устройств // @route GET /api/admin/blocked-devices // @access Private/Admin const getBlockedDevicesList = async (req, res) => { try { const { page = 1, limit = 20, sortBy = 'blockedAt', sortOrder = 'desc', isActive = 'true', userId } = req.query; const filters = { page: parseInt(page), limit: parseInt(limit), sortBy, sortOrder, isActive: isActive === 'true', userId }; const result = await getBlockedDevices(filters); console.log('[ADMIN] Запрос списка заблокированных устройств:', { adminId: req.user._id, filters, totalItems: result.pagination.totalItems }); res.json({ success: true, data: result.devices, pagination: result.pagination }); } catch (error) { console.error('[ADMIN] Ошибка при получении списка заблокированных устройств:', error); res.status(500).json({ message: 'Ошибка при получении списка заблокированных устройств', error: error.message }); } }; // @desc Получение детальной информации о заблокированном устройстве // @route GET /api/admin/blocked-devices/:id // @access Private/Admin const getBlockedDeviceDetails = async (req, res) => { try { const { id } = req.params; const device = await BlockedDevice.findById(id) .populate('blockedBy', 'name email') .populate('blockedUserId', 'name email') .populate('unblockRequests.requestedBy', 'name email') .populate('unblockRequests.reviewedBy', 'name email'); if (!device) { return res.status(404).json({ message: 'Заблокированное устройство не найдено' }); } console.log('[ADMIN] Запрос деталей заблокированного устройства:', { deviceId: id, adminId: req.user._id }); res.json({ success: true, data: device }); } catch (error) { console.error('[ADMIN] Ошибка при получении деталей заблокированного устройства:', error); res.status(500).json({ message: 'Ошибка при получении информации об устройстве', error: error.message }); } }; // @desc Получение устройств пользователя // @route GET /api/admin/user/:userId/devices // @access Private/Admin const getUserDevices = async (req, res) => { try { const { userId } = req.params; // Проверяем, существует ли пользователь const user = await User.findById(userId); if (!user) { return res.status(404).json({ message: 'Пользователь не найден' }); } // Получаем список устройств пользователя по его ID const devices = await User.findUserDevices(userId); console.log(`[ADMIN] Запрос устройств пользователя ${userId}, найдено: ${devices.length}`); res.json({ success: true, data: devices }); } catch (error) { console.error('[ADMIN] Ошибка при получении устройств пользователя:', error); res.status(500).json({ message: 'Ошибка при получении устройств пользователя', error: error.message }); } }; // @desc Блокировка всех устройств пользователя // @route POST /api/admin/user/:userId/block-devices // @access Private/Admin const blockUserDevices = async (req, res) => { try { const { userId } = req.params; const { reason = 'Блокировка администратором', duration = 'permanent' } = req.body; // Проверяем, существует ли пользователь const user = await User.findById(userId); if (!user) { return res.status(404).json({ message: 'Пользователь не найден' }); } // Получаем все устройства пользователя const devices = await User.findUserDevices(userId); if (!devices.length) { return res.status(404).json({ message: 'У пользователя не найдено устройств для блокировки' }); } // Блокируем каждое устройство const blockedDevices = []; for (const device of devices) { try { const blockedDevice = await blockUserDevice( userId, req.user._id, reason, device.fingerprint, duration ); blockedDevices.push(blockedDevice); } catch (err) { console.error(`[ADMIN] Ошибка при блокировке устройства ${device.fingerprint}:`, err); } } console.log(`[ADMIN] Заблокированы устройства пользователя ${userId}, количество: ${blockedDevices.length}`); res.json({ success: true, message: `Заблокировано ${blockedDevices.length} из ${devices.length} устройств пользователя`, blockedDevices }); } catch (error) { console.error('[ADMIN] Ошибка при блокировке устройств пользователя:', error); res.status(500).json({ message: 'Ошибка при блокировке устройств пользователя', error: error.message }); } }; /** * Вычисляет уровень риска на основе подозрительной активности */ function calculateRiskScore(activities, deviceInfo) { let score = 0; if (!activities || activities.length === 0) return 0; activities.forEach(activity => { switch (activity.type) { case 'fingerprint_change': score += 30; // Изменение fingerprint - высокий риск break; case 'multiple_login_attempts': score += 20; break; case 'suspicious_user_agent': score += 15; break; case 'rapid_requests': score += 10; break; default: score += 5; } }); // Дополнительные факторы риска if (activities.length > 5) score += 10; // Много событий if (deviceInfo?.visitCount === 1) score += 15; // Новое устройство return Math.min(score, 100); // Максимум 100 } module.exports = { checkDeviceBlockStatus, reportSuspiciousActivity, blockDevice, unblockDeviceAdmin, getBlockedDevicesList, getBlockedDeviceDetails, getUserDevices, blockUserDevices };