62 lines
2.8 KiB
JavaScript
62 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* 手机接入线 S5 · **运维急停**夹具(独立进程,2026-09-27)。
|
||
*
|
||
* ## 为什么必须是独立进程
|
||
* 路由侧读的是 `process.env.DSHS_DEVICE_WEB`,而 ESM 模块**只求值一次** ——
|
||
* 在同一个进程里改 `process.env` 之后再 import,改动拿不到(实测假绿过一次)。
|
||
* 独立进程 + 环境变量与生产 systemd 的形态**完全同构**(e2e 脚本就是往 drop-in 里写这个键)。
|
||
*
|
||
* ## 判据(两条,缺一条就不算通过)
|
||
* ① `DSHS_DEVICE_WEB=0` 且**用户开关是开的** ⇒ 设备入口必须被拒,且码 = `switch-off`
|
||
* (⛔ 不是 `user-switch-off` —— 糊了就分不清"该运维动"还是"该用户动")
|
||
* ② 同一份夹具在**未设**该键时必须**不通过**(由调用方断言)⇒ 证明本脚本真的读了 env,
|
||
* 而不是恒真。
|
||
*
|
||
* ⚠️ **HTTP 状态 = 404**(既有 S3 口径:`switch-off` 本来就走 404,本棒⛔ 没动它):
|
||
* 判据在**响应体里的具名码**,不在状态码 —— 这点必须写清,否则下一个人会以为 404 是写漏了。
|
||
*
|
||
* 用法:`DSHS_DEVICE_WEB=0 node test/fixtures/device-switch-forceoff.mjs`
|
||
* 退出码:0 = 急停生效(期望);1 = 没生效(不合期望)。
|
||
*/
|
||
import Fastify from 'fastify'
|
||
|
||
import { deviceWebRoutes } from '../../lib/web/routes/device-web.js'
|
||
import { hashSessionToken } from '../../lib/web/auth.js'
|
||
import { indexRelayStatus, resolveDeviceReachability } from '../../lib/net/relay-endpoints.js'
|
||
|
||
const USER = 'u-1'
|
||
const NET = `u:${USER}`
|
||
const HOST = 'd-u-1-aaaaaaaa'
|
||
const SID = 'sid-token'
|
||
const COOKIE_HASH = hashSessionToken(SID)
|
||
|
||
const app = Fastify()
|
||
app.decorate('db', {
|
||
findSessionWithUser: async (hash) =>
|
||
hash === COOKIE_HASH ? { expiresAt: Date.now() + 60_000, user: { id: USER, role: 'active' } } : undefined,
|
||
findOverlayDevice: async () => ({ status: 'active', kind: 'desktop' }),
|
||
// 🔴 用户开关**开着** —— 这正是"急停要压过用户开关"的判据面
|
||
getDeviceWebEnabled: async () => true,
|
||
})
|
||
app.decorate('imInstanceTokens', undefined)
|
||
await app.register(deviceWebRoutes, {
|
||
resolve: ({ hostId }) =>
|
||
resolveDeviceReachability(
|
||
indexRelayStatus({ endpoints: [{ hostId, network: NET, port: 20090, localPort: 42000, online: true }] }),
|
||
{ network: NET, hostId },
|
||
),
|
||
})
|
||
await app.ready()
|
||
|
||
const res = await app.inject({ method: 'GET', url: `/u/${USER}/desk/${HOST}/`, headers: { cookie: `sid=${SID}` } })
|
||
await app.close()
|
||
|
||
const body = res.payload === '' ? {} : JSON.parse(res.payload)
|
||
if (res.statusCode === 404 && body.error === 'switch-off') {
|
||
console.log(`FORCE-OFF-OK status=404 error=switch-off env=${JSON.stringify(process.env.DSHS_DEVICE_WEB)}`)
|
||
process.exit(0)
|
||
}
|
||
console.error(`FORCE-OFF-FAILED status=${res.statusCode} body=${res.payload}`)
|
||
process.exit(1)
|