feat: Pro 买断门禁、SFTP 精简与批量多机改造
新增 entitlement/license IPC 与 Waffo 一次性结账服务骨架,挂载 AI/转发/代理/串口/广播/批量导入导出门禁;批量执行改为结果矩阵并复用连接池,SFTP 工具栏图标化并去掉已连接条,同时完善跨平台本地终端与窗口配置。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
101d2164b4
commit
fea6d8db04
72 files changed
+3307
-396
No files matched your search
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env node
|
||||
import { createHmac } from 'node:crypto'
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const ROOT = join(__dirname, '..')
|
||||
|
||||
function loadEnv() {
|
||||
const envPath = join(ROOT, '.env')
|
||||
if (!existsSync(envPath)) return
|
||||
for (const line of readFileSync(envPath, 'utf8').split('\n')) {
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed || trimmed.startsWith('#')) continue
|
||||
const eq = trimmed.indexOf('=')
|
||||
if (eq <= 0) continue
|
||||
const key = trimmed.slice(0, eq).trim()
|
||||
let value = trimmed.slice(eq + 1).trim()
|
||||
if (
|
||||
(value.startsWith('"') && value.endsWith('"')) ||
|
||||
(value.startsWith("'") && value.endsWith("'"))
|
||||
) {
|
||||
value = value.slice(1, -1)
|
||||
}
|
||||
if (!(key in process.env)) process.env[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
loadEnv()
|
||||
|
||||
const args = process.argv.slice(2)
|
||||
function arg(name, fallback) {
|
||||
const idx = args.indexOf(`--${name}`)
|
||||
if (idx >= 0 && args[idx + 1]) return args[idx + 1]
|
||||
return fallback
|
||||
}
|
||||
|
||||
const deviceId = arg('deviceId', '*')
|
||||
const daysArg = arg('days', null)
|
||||
const secret =
|
||||
process.env.OPSX_LICENSE_HMAC || 'opsxshell-dev-license-hmac-v1-change-in-prod'
|
||||
|
||||
function b64url(buf) {
|
||||
return Buffer.from(buf)
|
||||
.toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=+$/g, '')
|
||||
}
|
||||
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const payload = {
|
||||
plan: 'pro',
|
||||
deviceId,
|
||||
iat: now,
|
||||
features: ['*'],
|
||||
}
|
||||
if (daysArg != null) {
|
||||
payload.exp = now + Number(daysArg) * 86400
|
||||
}
|
||||
const payloadB64 = b64url(JSON.stringify(payload))
|
||||
const sig = createHmac('sha256', secret).update(payloadB64).digest()
|
||||
const token = `opsx1.${payloadB64}.${b64url(sig)}`
|
||||
|
||||
console.log(JSON.stringify({ token, payload }, null, 2))
|
||||
Reference in new issue
Block a user