const db = require('../../dbProxy'); const authorizationService = require('../../../services/authorization_service'); const deviceManager = require('../core/deviceManager'); /** * 账户验证服务 * 统一处理账户启用状态、授权状态、在线状态的检查 */ class AccountValidator { /** * 检查账户是否启用 * @param {string} sn_code - 设备序列号 * @returns {Promise<{enabled: boolean, reason?: string}>} */ async checkEnabled(sn_code) { try { const pla_account = db.getModel('pla_account'); const account = await pla_account.findOne({ where: { sn_code, is_delete: 0 }, attributes: ['is_enabled', 'name'] }); if (!account) { return { enabled: false, reason: '账户不存在' }; } if (!account.is_enabled) { return { enabled: false, reason: '账户未启用' }; } return { enabled: true }; } catch (error) { console.error(`[账户验证] 检查启用状态失败 (${sn_code}):`, error); return { enabled: false, reason: '检查失败' }; } } /** * 检查账户授权状态 * @param {string} sn_code - 设备序列号 * @returns {Promise<{authorized: boolean, days?: number, reason?: string}>} */ async checkAuthorization(sn_code) { try { const result = await authorizationService.checkAuthorization(sn_code); if (!result.is_authorized) { return { authorized: false, days: result.days_remaining || 0, reason: result.message || '授权已过期' }; } return { authorized: true, days: result.days_remaining }; } catch (error) { console.error(`[账户验证] 检查授权状态失败 (${sn_code}):`, error); return { authorized: false, reason: '授权检查失败' }; } } /** * 检查设备是否在线 * @param {string} sn_code - 设备序列号 * @param {number} offlineThreshold - 离线阈值(毫秒) * @returns {{online: boolean, lastHeartbeat?: number, reason?: string}} */ checkOnline(sn_code, offlineThreshold = 3 * 60 * 1000) { const device = deviceManager.devices.get(sn_code); if (!device) { return { online: false, reason: '设备从未发送心跳' }; } const now = Date.now(); const lastHeartbeat = device.lastHeartbeat || 0; const elapsed = now - lastHeartbeat; if (elapsed > offlineThreshold) { const minutes = Math.round(elapsed / (60 * 1000)); return { online: false, lastHeartbeat, reason: `设备离线(最后心跳: ${minutes}分钟前)` }; } if (!device.isOnline) { return { online: false, lastHeartbeat, reason: '设备标记为离线' }; } return { online: true, lastHeartbeat }; } /** * 综合验证(启用 + 授权 + 在线) * @param {string} sn_code - 设备序列号 * @param {object} options - 验证选项 * @param {boolean} options.checkEnabled - 是否检查启用状态(默认 true) * @param {boolean} options.checkAuth - 是否检查授权(默认 true) * @param {boolean} options.checkOnline - 是否检查在线(默认 true) * @param {number} options.offlineThreshold - 离线阈值(默认 3分钟) * @returns {Promise<{valid: boolean, reason?: string, details?: object}>} */ async validate(sn_code, options = {}) { const { checkEnabled = true, checkAuth = true, checkOnline = true, offlineThreshold = 3 * 60 * 1000 } = options; const details = {}; // 检查启用状态 if (checkEnabled) { const enabledResult = await this.checkEnabled(sn_code); details.enabled = enabledResult; if (!enabledResult.enabled) { return { valid: false, reason: enabledResult.reason, details }; } } // 检查授权状态 if (checkAuth) { const authResult = await this.checkAuthorization(sn_code); details.authorization = authResult; if (!authResult.authorized) { return { valid: false, reason: authResult.reason, details }; } } // 检查在线状态 if (checkOnline) { const onlineResult = this.checkOnline(sn_code, offlineThreshold); details.online = onlineResult; if (!onlineResult.online) { return { valid: false, reason: onlineResult.reason, details }; } } return { valid: true, details }; } /** * 批量验证多个账户 * @param {string[]} sn_codes - 设备序列号数组 * @param {object} options - 验证选项 * @returns {Promise<{valid: string[], invalid: Array<{sn_code: string, reason: string}>}>} */ async validateBatch(sn_codes, options = {}) { const valid = []; const invalid = []; for (const sn_code of sn_codes) { const result = await this.validate(sn_code, options); if (result.valid) { valid.push(sn_code); } else { invalid.push({ sn_code, reason: result.reason }); } } return { valid, invalid }; } /** * 检查账户是否已登录(通过心跳数据) * @param {string} sn_code - 设备序列号 * @returns {boolean} */ checkLoggedIn(sn_code) { const device = deviceManager.devices.get(sn_code); return device?.isLoggedIn || false; } } // 导出单例 const accountValidator = new AccountValidator(); module.exports = accountValidator;