11
This commit is contained in:
199
api/middleware/schedule/services/accountValidator.js
Normal file
199
api/middleware/schedule/services/accountValidator.js
Normal file
@@ -0,0 +1,199 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user