feat: 重构定投评估工具并优化Cloud工具体验
- 重构市场定投评估逻辑:优先读取本地估值快照,必要时通过探针补抓海外数据,后端接口新增force参数支持强制刷新,更新前后端注释与交互文案 - 优化Cloud工具全链路: - 新增运营商登录页地址字段,支持一键复制账号密码并打开对应登录页 - 缓存密钥派生结果,避免重复阻塞事件循环,提升列表加载性能 - 完善接口错误处理,新增面板级加载失败提示与自动重试功能 - 修复云资源代理转发时的Cookie缺失问题 - 并行加载所有面板数据,优化首屏渲染速度 - 新增登录按钮样式与错误提示样式 - 新增4个Cloud工具调试脚本,用于性能测试、解密审计、回归验证与加载耗时统计 - 启动定投评估工具的定时调度任务
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
// 调试脚本:逐行审计 cloud ecs/vas 加密字段,区分"明文原本为空"与"解密失败"
|
||||
// 用法:node dev_test_scripts/debug/debug_cloud_decrypt_audit.js
|
||||
const crypto = require('crypto')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
|
||||
// 与 index.js 相同的凭据加载逻辑
|
||||
const userProfile = process.env.USERPROFILE || process.env.HOME || os.homedir()
|
||||
const credsPath = path.join(userProfile, 'Toolbox_local_creds.env.local')
|
||||
if (fs.existsSync(credsPath)) {
|
||||
fs.readFileSync(credsPath, 'utf-8').split(/\r?\n/).forEach(line => {
|
||||
const t = line.trim()
|
||||
if (!t || t.startsWith('#')) return
|
||||
const i = t.indexOf('=')
|
||||
if (i <= 0) return
|
||||
const k = t.slice(0, i).trim()
|
||||
const v = t.slice(i + 1).trim()
|
||||
if (k && !Object.prototype.hasOwnProperty.call(process.env, k)) process.env[k] = v
|
||||
})
|
||||
console.log('creds loaded from', credsPath)
|
||||
} else {
|
||||
console.log('WARN: creds file not found')
|
||||
}
|
||||
|
||||
const { db } = require('../../src/server/db')
|
||||
const cfg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'config', 'cloud.json'), 'utf-8'))
|
||||
const saltStr = String(cfg.machine_salt || '')
|
||||
const passphrase = process.env.CLOUD_PASSPHRASE || process.env.SYSTEM_AUTH_PASS_93220 || ''
|
||||
console.log('passphrase present:', !!passphrase)
|
||||
const key = crypto.scryptSync(passphrase + saltStr, Buffer.from(saltStr || 'default', 'utf-8'), 32)
|
||||
|
||||
const audit = (table, ec, ivc, tagc) => {
|
||||
const rows = db.prepare(`SELECT id, ${ec}, ${ivc}, ${tagc} FROM ${table}`).all()
|
||||
let empty = 0
|
||||
let fail = 0
|
||||
let ok = 0
|
||||
for (const r of rows) {
|
||||
if (!r[ec] || !r[ivc] || !r[tagc]) continue
|
||||
try {
|
||||
const d = crypto.createDecipheriv('aes-256-gcm', key, r[ivc])
|
||||
d.setAuthTag(r[tagc])
|
||||
const pt = Buffer.concat([d.update(r[ec]), d.final()]).toString('utf-8')
|
||||
if (pt === '') { empty++; console.log(`${table} id=${r.id}: 解密成功但明文为空(原本就没填)`) } else ok++
|
||||
} catch (e) { fail++; console.log(`${table} id=${r.id}: 解密失败 ${String(e.message)}`) }
|
||||
}
|
||||
console.log(`${table}: ok_non_empty=${ok} empty_plaintext=${empty} auth_fail=${fail}`)
|
||||
}
|
||||
|
||||
audit('cloud_operators', 'login_password_enc', 'login_password_iv', 'login_password_tag')
|
||||
audit('cloud_ecs', 'rdp_password_enc', 'rdp_password_iv', 'rdp_password_tag')
|
||||
audit('cloud_vas', 'access_text_enc', 'access_text_iv', 'access_text_tag')
|
||||
console.log('audit done')
|
||||
Reference in New Issue
Block a user