e4f84caa23
- 重构市场定投评估逻辑:优先读取本地估值快照,必要时通过探针补抓海外数据,后端接口新增force参数支持强制刷新,更新前后端注释与交互文案 - 优化Cloud工具全链路: - 新增运营商登录页地址字段,支持一键复制账号密码并打开对应登录页 - 缓存密钥派生结果,避免重复阻塞事件循环,提升列表加载性能 - 完善接口错误处理,新增面板级加载失败提示与自动重试功能 - 修复云资源代理转发时的Cookie缺失问题 - 并行加载所有面板数据,优化首屏渲染速度 - 新增登录按钮样式与错误提示样式 - 新增4个Cloud工具调试脚本,用于性能测试、解密审计、回归验证与加载耗时统计 - 启动定投评估工具的定时调度任务
47 lines
2.6 KiB
JavaScript
47 lines
2.6 KiB
JavaScript
// 调试脚本:cloud 重启后鉴权链路 + 解密数据完整性回归
|
|
// 用法:node dev_test_scripts/debug/debug_cloud_regression.js
|
|
const BASE = 'http://localhost:8976'
|
|
|
|
const main = async () => {
|
|
const r1 = await fetch(BASE + '/go?systemId=Tools-cloud', { redirect: 'manual' })
|
|
console.log('entry:', r1.status, r1.headers.get('location') ? '(redirect ok)' : '(NO LOCATION)')
|
|
const r2 = await fetch(new URL(r1.headers.get('location'), BASE), { redirect: 'manual' })
|
|
const setc = String(r2.headers.get('set-cookie') || '')
|
|
console.log('index hop:', r2.status, /cloud_gate=1/.test(setc) ? '(cookie ok)' : '(NO COOKIE)')
|
|
const r3 = await fetch(BASE + '/tools/cloud/index.html', { headers: { Cookie: 'cloud_gate=1' } })
|
|
console.log('index.html:', r3.status)
|
|
const r4 = await fetch(BASE + '/tools/cloud/cloud.js', { headers: { Cookie: 'cloud_gate=1' } })
|
|
console.log('cloud.js:', r4.status)
|
|
|
|
const H = { Cookie: 'cloud_gate=1' }
|
|
const j = async u => (await fetch(BASE + u, { headers: H })).json()
|
|
|
|
const ops = await j('/api/cloud/operators')
|
|
const opsEnc = (ops.rows || []).filter(r => r.login_password_enc)
|
|
const opsDecOk = opsEnc.filter(r => String(r.login_password || '') !== '').length
|
|
console.log(`operators: ok=${ops.ok} rows=${(ops.rows || []).length} enc=${opsEnc.length} decrypted_non_empty=${opsDecOk}`)
|
|
|
|
const ecs = await j('/api/cloud/ecs')
|
|
const ecsEnc = (ecs.rows || []).filter(r => r.rdp_password_enc)
|
|
const ecsDecOk = ecsEnc.filter(r => String(r.rdp_password || '') !== '').length
|
|
console.log(`ecs: ok=${ecs.ok} rows=${(ecs.rows || []).length} enc=${ecsEnc.length} decrypted_non_empty=${ecsDecOk}`)
|
|
|
|
const vas = await j('/api/cloud/vas')
|
|
const vasEnc = (vas.rows || []).filter(r => r.access_text_enc)
|
|
const vasDecOk = vasEnc.filter(r => String(r.access_text || '') !== '').length
|
|
console.log(`vas: ok=${vas.ok} rows=${(vas.rows || []).length} enc=${vasEnc.length} decrypted_non_empty=${vasDecOk}`)
|
|
|
|
const rn = await j('/api/cloud/renew')
|
|
console.log(`renew: ok=${rn.ok} rows=${(rn.rows || []).length}`)
|
|
const nt = await j('/api/cloud/notes')
|
|
console.log(`notes: ok=${nt.ok} rows=${(nt.rows || []).length}`)
|
|
const bs = await j('/api/cloud/balance_alerts/status')
|
|
console.log(`balance status: ok=${bs.ok} proxied=${!!bs.proxied_to_automation} listener=${bs.data && bs.data.listener ? 'present' : 'n/a'}`)
|
|
|
|
const bad = (opsEnc.length !== opsDecOk) || (ecsEnc.length !== ecsDecOk) || (vasEnc.length !== vasDecOk)
|
|
console.log(bad ? 'REGRESSION FAIL: 存在解密为空的行' : 'REGRESSION PASS')
|
|
process.exit(bad ? 1 : 0)
|
|
}
|
|
|
|
main().catch(e => { console.error('ERR', e.message); process.exit(1) })
|