Files
alist-serve-resource/docs/PERMISSIONS.md
T
hoelee 80eb2b71be 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
2026-08-23 07:30:41 +08:00

2.9 KiB
Raw Blame History

权限模型说明(Permissions)

本文解释「最终生效的 AList 权限」是怎么从 NocoDB 数据算出来的。更新日期 2026-08-23。

最终生效权限的三要素

一个客户最终能访问哪些 AList 路径,由三样东西决定:

  1. Customers.status — 整户开关(account-level)
  2. CustomerProducts — 买了哪些产品 + 何时到期(product entitlement)
  3. Product → Resources — 每个产品包含哪些路径(M2M),资源有 alist_path

三者合起来 → n8n 调 calculateEffectiveGrants → 算出 desired scopes → 写到 AList Role。

计算规则(calculateEffectiveGrants)

对某个客户,desired scopes = 以下两类的并集:

(A) CustomerProduct 派生

遍历该客所有 CustomerProduct:

  • 跳过 status != active 的
  • 跳过 expires_at <= 今天 的(到期当天视为已过期)
  • 通过 product link → 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 不会回来。
  • 状态变化不自动改 CustomerProducts(不批量改 CP.status、不改 expires_at、不删除 CP)。
  • AccessGrants 历史记录不删除;恢复时重算,不用旧 AccessGrant scope 直接恢复。