Files
alist-serve-resource/docs/N8N_WORKFLOWS.md
T
hoelee 414bf31ba0 feat(n8n): W5 footer purchase-check webhook (公开只读) + docs
- W5 gets username ?u= → Customers→CustomerProducts → {username,known,purchases}
- 无 HMAC(密钥会下发客户端): 改用 CORS 限 drive.digikedai.com + 最小数据 + CF WAF 建议
- 复用现有 NOCODB_* env, 零新增 env
- 2 节点: webhook(GET, lastNode, CORS 头) + Code(w5-body.js)
- footer v2.6 动态行数据源; 待手动导入 n8n
- docs: N8N_WORKFLOWS + PROJECT_STATE 记录 W5 + 导入步骤
2026-08-28 18:24:42 +08:00

6.1 KiB
Raw Blame History

n8n Workflow 说明(已实施)

n8n 运行在现有 auto.hoelee.com(bridge_hoelee 网络)。它是同步器,不是 SOT。 更新日期 2026-08-23。

已实现的 Workflow

Workflow ID 触发 职责
W1 Customer Provision & Status Lifecycle gU2ee9Eg5w1KzB5p NocoDB Customers webhook provision + 整户 status lifecycle
W2 CustomerProduct Sync D9OWAI7JUjKnRdOn NocoDB CustomerProducts webhook 重算该客有效 grants 并应用
W3 Expiry Sync zlEfjj5eK5IfILtk schedule */5 定时
W4 Daily Full Reconciliation pl8j9lpg5gjrd0dB 每日 03:00 + webhook alist-w4-reconcile 全量对账 + 用户/角色级 drift 修复 + ReconcileLogs
W5 Footer Purchase Check (导入后由 n8n 分配) GET webhook dk-purchase-check footer 动态行数据源(公开只读)

W1–W4 共享同一套算法 calculateEffectiveGrants(n8n/shared/effective-grants.js, 构建时经 gen_w1/w2/w3/w4.js 内联进各 Code 节点)。W5 是独立的公开只读 webhook(不属同步器)。

W1 — Customer Provision & Status Lifecycle

  • 触发:Customers 表 after-insert / after-update(webhook alist-customer-provision)
  • 单一 Code 节点,处理 5 状态:
    • active(无 user)→ 建 role + 建 user + 重算 grants + enable
    • active(有 user)→ re-enable + 重算 grants(不恢复旧值)+ 应用
    • pending/suspended/expired/deleted(有 user)→ disable + 清空 scopes
    • pending/suspended/expired/deleted(无 user)→ no-op
  • 回填 alist_user_id / alist_role_id,写 sync_status=synced

W2 — CustomerProduct Sync

  • 触发:CustomerProducts 表 after-insert / after-update(webhook alist-customerproduct-sync)
  • 读 CP → 定位 customer → 重算该客 grants → diff AList role → 有变化才 role/update 整体重写
  • customer link 为空时优雅跳过(不回写)

W3 — Expiry Sync(全量对账)

  • 触发:每 5 分钟 schedule
  • 逐客调 calculateEffectiveGrants → diff → 应用
  • Env 开关:W3_DRY_RUN=true(只打印计划)、ALIST_AUTO_DISABLE_ON_EXPIRE=true(scopes 变空时 disable 用户)

W4 — Daily Full Reconciliation(每日全量对账)

  • 触发:每日 03:00 cron + 手动 webhook(/webhook/alist-w4-reconcile,?dryRun=true 出计划)
  • 单向同步:NocoDB status 是 SOT,W4 只修 AList,永不反向改 NocoDB status
  • 覆盖 W3 不管的 drift:缺 user/role → 按 username 反查防重再 provision;悬空引用 → adopt/recreate; 非 active → disable + 清 scopes;base_path/permission 修回 canonical(/ + 16384); username drift → detect + log_only;修复后逐个 verify 回读,失败记 verify_failed
  • 写 ReconcileLogs(表 mktsb7le6fqr2u1),只记 drift/repair/error 行;customer 链接用 FK 列
  • 密码随 repair 不推送(方案 C)
  • 详见 docs/W4-DESIGN.md
  • 触发:GET /webhook/dk-purchase-check?u=<username>(公网经 auto.hoelee.com)
  • 职责:footer v2.6 动态行数据源——按 username 查 Customers → 拉该客 CustomerProducts → 返回 { username, known, purchases:[{product, expires_at, display_state}] }
  • 安全模型(无 HMAC——key 会随 footer JS 下发到客户端=空话):
    • CORS:webhook options.responseHeaders 设 Access-Control-Allow-Origin: https://drive.digikedai.com → 仅 AList 门户 origin 能读响应
    • 最小数据:只回 product 名 + 到期 + display_state,不含内部 Id
    • 服务器枚举靠 CF WAF 在 auto.hoelee.com 上做限流 + Origin/Referer 规则(见交付指南)
  • 零 AList 认证请求:username 由 footer 本地解码用户自己的 JWT(localStorage['token'])取出 → 无「空客户端设备驱逐」风险(v2.3 事故机制完全不涉及)
  • 复用现有 env(NOCODB_URL/NOCODB_TOKEN/NOCODB_TABLE_CUSTOMERS/NOCODB_TABLE_CUSTOMERPRODUCTS),零新增 env
  • 生成:node n8n/gen_w5.js → W5-purchase-check.json(2 节点:webhook[GET, lastNode, CORS 头] + Code「Lookup Purchases」)
  • 导入(手动):n8n → Import from File → W5-purchase-check.json → 记下 Webhook URL(应为 https://auto.hoelee.com/webhook/dk-purchase-check)→ 激活。测试: curl 'https://auto.hoelee.com/webhook/dk-purchase-check?u=tester' 应回 JSON 含 known:true + 2 条 purchases

共用 env 变量

n8n Code 节点内用 $env.VAR(process.env 不可靠)。下表是本项目需要的 env:

变量 说明
NOCODB_URL / NOCODB_TOKEN NocoDB 地址 + xc-token
NOCODB_TABLE_CUSTOMERS / ..._CUSTOMERPRODUCTS / ..._PRODUCTS / ..._RESOURCES / ..._ACCESSGRANTS / ..._RECONCILELOGS 各表 model_id(ReconcileLogs = mktsb7le6fqr2u1)
NOCODB_FK_RECONCILELOG_CUSTOMER ReconcileLogs.customer 的 FK 列名 nc_jitu___Customers_id(W4 写链接必须用 FK 列)
NOCODB_LINK_PROD_RESOURCES Product↔Resource M2M 列 id(c4ko4x8kwi16swg)
ALIST_URL http://alist-serve-resource:5244(n8n 容器内)
ALIST_ADMIN_USERNAME / ALIST_ADMIN_PASSWORD AList admin 登录
W3_DRY_RUN / ALIST_AUTO_DISABLE_ON_EXPIRE W3 开关

幂等规则

所有操作 = get current → compare → apply diff。重跑不产生重复 user/role/scope。 更新 scope 一律「整体重写该 role 的 permission_scopes」。

Loop 防护(重要)

  • n8n 只写回 bookkeeping 字段(alist_user_id/alist_role_id/sync_status/sync_required/last_sync/last_sync_error)。
  • W1 用 old/new field comparison(NocoDB previous_rows vs rows)区分「业务变更」vs「echo」;echo 直接短路。
  • writeBack() 值比对守卫:字段值不变就不发 PATCH,掐断 echo loop。

依赖的 AList API(源码级验证,见 API_INTEGRATION.md)

  • 登录:POST /api/auth/login
  • User:/api/admin/user/{list,get,create,update,delete}
  • Role:/api/admin/role/{list,get,create,update,delete}(delete 用 ?id= query param)