docs: architecture, permissions, admin guide + refresh schema/workflows
- New ARCHITECTURE.md (3-layer model + data flow + lifecycle matrix) - New PERMISSIONS.md (grant calculation rules + enforcement) - New ADMIN_GUIDE.md (華文极简:Customer/CustomerProduct 授权 + Product/Resource 管理) - Rewrite N8N_WORKFLOWS.md from WF1-6 (obsolete) to actual W1/W2/W3 - Update DATABASE_SCHEMA.md: fix status enum (drop 'disabled'), add 5-status semantics - Update README.md doc index
This commit is contained in:
+51
-38
@@ -1,54 +1,67 @@
|
||||
# n8n Workflow 说明(Phase 3–6 — 待实施)
|
||||
# n8n Workflow 说明(已实施)
|
||||
|
||||
> n8n 运行在现有 auto.hoelee.com(`bridge_hoelee` 网络)。它是同步器,不是 SOT。
|
||||
> n8n 运行在现有 auto.hoelee.com(`bridge_hoelee` 网络)。它是**同步器,不是 SOT**。
|
||||
> 更新日期 2026-08-23。
|
||||
|
||||
## 依赖的 AList API(已源码验证,见 API_INTEGRATION.md)
|
||||
## 已实现的三个 Workflow
|
||||
|
||||
- 登录换 token:`POST http://alist-serve-resource:5244/api/auth/login`
|
||||
- User:`/api/admin/user/{list,get,create,update,delete,cancel_2fa}`
|
||||
- Role:`/api/admin/role/{list,get,create,update,delete}`
|
||||
| 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 | schedule `*/5` | 定时 | 全量对账 + drift 修复 |
|
||||
|
||||
## 需要的 Workflow
|
||||
三个 workflow 共享同一套算法 `calculateEffectiveGrants`(`n8n/shared/effective-grants.js`,
|
||||
构建时经 `gen_w1/w2/w3.js` 内联进各 Code 节点)。
|
||||
|
||||
### WF1 — Customer Create(trigger: Customers 新记录)
|
||||
1. 校验 customer。
|
||||
2. 查重 username → 建/改 AList user(`base_path=/Class`,`role=[专属role]`,`permission=16384`)。
|
||||
3. 建专属 role(`name=customer-<username>`,空 scopes)。
|
||||
4. 用 `/api/admin/user/update` 把 user 绑定到新 role(显式传 role ID,勿留空)。
|
||||
5. 回填 `alist_user_id` / `alist_role_id` 到 NocoDB。
|
||||
6. `sync_status=synced`。
|
||||
## W1 — Customer Provision & Status Lifecycle
|
||||
|
||||
### WF2 — AccessGrant Create/Update(trigger: AccessGrants 记录变更)
|
||||
1. 找 customer + resource path。
|
||||
2. 判断当前日期 vs start_at/expires_at。
|
||||
3. 若 active → 把该 path 并入该客专属 role 的 `permission_scopes`(permission=0)。
|
||||
4. 若非 active → 不加入。
|
||||
5. 整体 `post /api/admin/role/update` 重写 scopes(幂等)。
|
||||
6. 记录 `sync_status` / `last_sync_at` / `last_sync_error`。
|
||||
- 触发: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`
|
||||
|
||||
### WF3 — Expiry Sync(schedule: every 5 min)
|
||||
1. 查所有 active/scheduled grants。
|
||||
2. 计算 desired scopes(NocoDB 有效 grants 并集)。
|
||||
3. 对比 AList 实际 scopes(`role/get`)。
|
||||
4. 移除过期 scope、加入新生效 scope。
|
||||
5. 若无剩余 active grant 且政策启用 → disable 该 customer(`user/update disabled=true`)。
|
||||
6. 记录结果;失败发通知。
|
||||
## W2 — CustomerProduct Sync
|
||||
|
||||
### WF4 — Full Reconciliation(schedule: daily)
|
||||
- desired(NocoDB) vs actual(AList) 全量 diff,修复 AList,记录 reconciliation。
|
||||
- 触发:CustomerProducts 表 after-insert / after-update(webhook `alist-customerproduct-sync`)
|
||||
- 读 CP → 定位 customer → 重算该客 grants → diff AList role → 有变化才 `role/update` 整体重写
|
||||
- `customer` link 为空时优雅跳过(不回写)
|
||||
|
||||
### WF5 — Customer Suspension(trigger: status=suspended)
|
||||
- `user/update disabled=true` + 清空 role scopes;恢复时重算。
|
||||
## W3 — Expiry Sync(全量对账)
|
||||
|
||||
### WF6 — Customer Delete(soft delete)
|
||||
- NocoDB `status=deleted`;AList 禁用用户 + 清空 scopes,不物理删除。
|
||||
- 触发:每 5 分钟 schedule
|
||||
- 逐客调 `calculateEffectiveGrants` → diff → 应用
|
||||
- Env 开关:`W3_DRY_RUN=true`(只打印计划)、`ALIST_AUTO_DISABLE_ON_EXPIRE=true`(scopes 变空时 disable 用户)
|
||||
|
||||
## 幂等规则(规格 §28)
|
||||
## 共用 env 变量
|
||||
|
||||
n8n Code 节点内用 `$env.VAR`(`process.env` 不可靠)。下表是本项目需要的 env:
|
||||
|
||||
| 变量 | 说明 |
|
||||
|---|---|
|
||||
| `NOCODB_URL` / `NOCODB_TOKEN` | NocoDB 地址 + `xc-token` |
|
||||
| `NOCODB_TABLE_CUSTOMERS` / `..._CUSTOMERPRODUCTS` / `..._PRODUCTS` / `..._RESOURCES` / `..._ACCESSGRANTS` | 各表 model_id |
|
||||
| `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 内网访问 AList 的 host 名(预期 `http://alist-serve-resource:5244`)。
|
||||
- 登录 token 缓存 / 刷新策略(JWT_EXPIRE=2h → 建议每次 workflow 起手先 login)。
|
||||
- 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)
|
||||
|
||||
Reference in New Issue
Block a user