- 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
2.9 KiB
2.9 KiB
权限模型说明(Permissions)
本文解释「最终生效的 AList 权限」是怎么从 NocoDB 数据算出来的。更新日期 2026-08-23。
最终生效权限的三要素
一个客户最终能访问哪些 AList 路径,由三样东西决定:
Customers.status— 整户开关(account-level)CustomerProducts— 买了哪些产品 + 何时到期(product entitlement)Product → Resources— 每个产品包含哪些路径(M2M),资源有alist_path
三者合起来 → n8n 调 calculateEffectiveGrants → 算出 desired scopes → 写到 AList Role。
计算规则(calculateEffectiveGrants)
对某个客户,desired scopes = 以下两类的并集:
(A) CustomerProduct 派生
遍历该客所有 CustomerProduct:
- 跳过
status != active的 - 跳过
expires_at <= 今天的(到期当天视为已过期) - 通过
productlink → Product 的 M2M Resources → 拿到每个 resource 的路径
(B) AccessGrant 派生(预留,当前不经 n8n 写入)
- 同 (A),跳过非 active / 已过期
合并规则
- 同一个 path 来自多个来源 → 取 MAX(expires_at)(两个产品共享一个资源时,取较晚的到期)
- permission:
readwrite覆盖read(readwrite=1,否则 0) - basis:本系统客户一律 只读(permission 0),读写在 AccessGrant 手工授权时可用
AList 侧落地(enforcement)
- 每个客户 = 1 个专属 AList Role(
name = customer-<username>) - Role 的
permission_scopes= desired scopes 的绝对路径数组 - 客户 User:
base_path = '/'(必须/,否则 JoinPath 双重前缀 → 全 403) - 客户 User:
permission = 16384(bit 14 = Check path limit 置位 → 只能访问 role scope 内的路径) disabled由 status 控制:非 active →disabled=true
多文件夹授权正确做法(已实测)
base_path = "/"+ role scope 用绝对路径(如/Class/Forex、/Template/Music)- 结果:客户只看到被授权路径,未授权挂载点(
/Book等)不泄露
到期与状态的关系
| 场景 | 结果 |
|---|---|
| CustomerProduct 到期 | 该产品派生的路径从 scopes 移除(W2/W3 对账自动修) |
| 整个 Customer status 变 non-active | 整户 disable + scopes 清空(W1) |
| non-active → active 恢复 | 重算当前有效 scopes,不恢复已过期产品 |
重要边界
Customers.status是账户级开关,不替代 CustomerProduct 的到期。- 例:Customer =
expired,其 Product A 仍 active 且未到期。恢复expired → active后 Product A 会自动回来;已过期的 Product B 不会回来。
- 例:Customer =
- 状态变化不自动改 CustomerProducts(不批量改 CP.status、不改 expires_at、不删除 CP)。
- AccessGrants 历史记录不删除;恢复时重算,不用旧 AccessGrant scope 直接恢复。