template-monorepo/internal/model/permission/SDD.md

11 KiB
Raw Permalink Blame History

Permission Service

Permission Service — SRS/SDD Document

Version Version Date Editor Memo
1.0.0 2026/05/21 Gateway Team 初版Gateway Permission 模組 SDD對齊 frontend Permission Service SDD 格式)
1.1.0 新增 category 樹狀 Permission Catalog
1.2.0 多租戶 B2B RBAC + Casbin + RoleMapping

1. Introduction

1.1 Purpose

Permission 模組提供 Gateway 多租戶 B2B 自定義 RBAC:平台級 Permission Catalog + 租戶級 Role / RolePermission / UserRole / RoleMapping搭配 Casbin enforcer 進行 HTTP path/method 授權,並支援外部 IdPZITADEL / LDAP / SCIM角色映射同步。

1.2 Scope

範圍內Multiple tenants

  • 平台 Permission Catalog樹狀dot notation
  • 租戶 Role CRUD含 system role 防呆)
  • Role ↔ Permission 多對多(含 parent closure
  • User ↔ Role 多對多source: manual / zitadel / ldap / scim
  • 外部 group → 內部 Role.Key 映射RoleMapping
  • Casbin policy 物化Redis Set+ 多 pod Pub/Sub reload
  • GET /permissions/me 前端選單渲染

範圍外:

  • JWT 簽發 → Auth 模組
  • 會員資料 → Member 模組
  • Platform admin bypass → middleware 預檢(保留 audit

1.3 Definitions, Acronyms, and Abbreviation

縮寫 說明
RBAC Role-Based Access Control
Permission 平台級權限節點(可為分類或 leaf API 權限)
Role 租戶內角色,key 唯一且不可改
RolePermission Role 勾選的 Permission 集合
UserRole 使用者被指派的角色
RoleMapping 外部 IdP group/role → 內部 Role.Key
Casbin 授權引擎policy 存 Redis
Leaf Permission 有 http_path + http_methods 的可 enforcement 節點

1.4 Technologies to be used

項目 技術
Application Language Go 1.22+
Framework go-zero
Cache / Policy Store RedisCasbin rules Set + Pub/Sub
Database MongoDB
Authorization Engine CasbinkeyMatch2 + regexMatch
API Codegen goctl / .api

1.5 Overview

flowchart LR
    subgraph Platform["平台層"]
      Catalog[Permission Catalog]
    end
    subgraph Tenant["租戶層"]
      Role[Role]
      RP[RolePermission]
      UR[UserRole]
      RM[RoleMapping]
    end
    Catalog --> RP --> Role
    Role --> UR
    Role --> RM
    Tenant --> Casbin[(Casbin Enforcer<br/>Redis adapter)]
    Casbin --> MW[CasbinRBAC Middleware]
  • Permission 平台 seed 全局,租戶不可新增,只能勾選
  • Role / RolePermission / UserRole 租戶獨立
  • Role.Key 一旦建立 不可改(外部 IdP 對應用)
  • 多 pod 同步:Redis Pub/Sub 即時 + cron 兜底

2. System Overview

Permission 模組是 Gateway 授權子系統:

  1. 平台維護 Permission Catalogcmd/permission-seed
  2. 租戶管理員建立 Role、勾選 Permission
  3. 指派 UserRole手動或 SyncFromX 同步)
  4. RBACUseCase 物化 Casbin policy → middleware 檢查 (tenant, role.key, path, method)

前端透過 GET /permissions/me 取得當前使用者的 role keys 與 permission map含可選 tree


3. System Architecture

3.1 System Architecture

flowchart TD
    Logic[logic/permission] --> SVC[svc.ServiceContext]
    SVC --> AuthQ[AuthorizationQueryUseCase]
    SVC --> Perm[PermissionUseCase]
    SVC --> Role[RoleUseCase]
    SVC --> RolePerm[RolePermissionUseCase]
    SVC --> UserRole[UserRoleUseCase]
    SVC --> Mapping[RoleMappingUseCase]
    SVC --> RBAC[RBACUseCase]

    RBAC --> Adapter[Casbin Redis Adapter]
    Adapter --> Redis[(Redis)]
    RBAC --> Pub[Redis Pub/Sub casbin:reload]

    Perm --> PermR[(permissions)]
    Role --> RoleR[(roles)]
    RolePerm --> RPR[(role_permissions)]
    UserRole --> URR[(user_roles)]
    Mapping --> RMR[(role_mappings)]

3.2 Decomposition Description

套件 職責
config/ CasbinConfig、CacheConfig、ReloadConfig
domain/entity/ Permission、Role、RolePermission、UserRole、RoleMapping
domain/enum/ Status、PermissionType、RoleSource
domain/repository/ 5 個 Mongo repo 介面 + Casbin adapter port
domain/usecase/ 7 個 usecase 介面 + DTO
repository/ Mongo + Redis Casbin adapter
usecase/ 7 個 atomic usecase 實作 + permission_tree
seed/ catalog.json + Apply CLI

3.3 RBAC Model

Casbin 模型(etc/rbac.conf

[request_definition]
r = tenant, role, path, method

[policy_definition]
p = tenant, role, path, methods, name

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.tenant == p.tenant && r.role == p.role && keyMatch2(r.path, p.path) && regexMatch(r.method, p.methods)

授權檢查any-allow 使用者所有 open role 逐一 EnforceEx任一 allow 即通過。

sequenceDiagram
    participant MW as CasbinRBAC Middleware
    participant RBAC as RBACUseCase
    participant URR as UserRoleRepository
    participant Enf as casbin.Enforcer

    MW->>RBAC: Check{tenant, uid, path, method}
    RBAC->>URR: ListByUser
    loop each open role
        RBAC->>Enf: EnforceEx(tenant, role.key, path, method)
        alt allow
            RBAC-->>MW: Allow
        end
    end
    RBAC-->>MW: Deny → 403

3.4 Permission Tree

member.info.management            ← 分類(無 HTTP
├── member.basic.info
│   ├── member.info.select        GET   /api/v1/members/me
│   └── member.info.update        PATCH /api/v1/members/me
└── member.admin.list             GET   /api/v1/members

permission.role.management
├── permission.role.read          GET    /api/v1/permissions/roles
└── permission.role.write         POST/PUT/DELETE /api/v1/permissions/roles*

分類節點(無 http_path)不寫入 Casbin policyReplace RolePermission 時自動補齊 parent closure。

3.5 Policy Reload多 Pod

sequenceDiagram
    participant PodA as Pod A
    participant Redis
    participant PodB as Pod B

    PodA->>PodA: RolePermission.Replace + LoadPolicy
    PodA->>Redis: PUBLISH casbin:reload {tenant_id}
    Redis-->>PodB: message
    PodB->>PodB: LoadPolicy(tenant)

4. Data Design

4.1 Data Dictionary

permissionsMongoDB — 平台全局)

Field Type Comment Index
_id ObjectId PK PK
parent String 父節點 ObjectId hex parent
name String dot notation 唯一名稱 Unique
http_methods String GET 或 GET|POST|PATCH
http_path String keyMatch2 path pattern
status String open / close status
type String backend_user / frontend_user type
create_at Int64 建立時間 ms
update_at Int64 更新時間 ms

rolesMongoDB — 租戶範圍)

Field Type Comment Index
_id ObjectId PK PK
tenant_id String 租戶 ID Unique(tenant_id, key)
key String 角色 key不可改 Unique(tenant_id, key)
display_name String 顯示名稱
creator_uid String 建立者 UID
status String open / close (tenant_id, is_system)
is_system Bool 平台預設角色 (tenant_id, is_system)
create_at Int64 建立時間 ms
update_at Int64 更新時間 ms

role_permissionsMongoDB

Field Type Comment Index
_id ObjectId PK PK
tenant_id String 租戶 ID Unique(tenant_id, role_id, permission_id)
role_id String Role ObjectId hex (tenant_id, role_id)
permission_id String Permission ObjectId hex (tenant_id, permission_id)
create_at Int64 建立時間 ms

user_rolesMongoDB

Field Type Comment Index
_id ObjectId PK PK
tenant_id String 租戶 ID Unique(tenant_id, uid, role_id)
uid String 會員 UID (tenant_id, uid, source)
role_id String Role ObjectId hex (tenant_id, role_id)
source String manual / zitadel / ldap / scim (tenant_id, uid, source)
create_at Int64 建立時間 ms

role_mappingsMongoDB

Field Type Comment Index
_id ObjectId PK PK
tenant_id String 租戶 ID Unique(tenant_id, external_source, external_key)
external_source String zitadel / ldap / scim Unique(tenant_id, external_source, external_key)
external_key String 外部 group/role key Unique(tenant_id, external_source, external_key)
internal_role_id String 內部 Role ID (tenant_id, internal_role_id)
create_at Int64 建立時間 ms
update_at Int64 更新時間 ms

Redis Keys

Key Pattern 內容 TTL
permission:casbin:rules:{tenant_id} Set of JSON Casbin rules 永久
perm:user_roles:{tenant_id}:{uid} role keys 快取(預留) 300s
perm:role_perms:{tenant_id}:{role_id} permission names 快取(預留) 300s
(channel) casbin:reload Pub/Sub reload payload

Casbin rule 格式: [tenant, role.key, http_path, http_methods, perm.name]


5. API Design

Base Path /api/v1/permissions

Method Path 說明
GET /catalog 全局 Permission Catalogtree/list
GET /me 當前 user 的 roles + permissions
GET /roles 租戶角色清單
POST /roles 建立角色
PATCH /roles/:id 更新 display_name / status
DELETE /roles/:id 刪除角色
GET /roles/:id/permissions 角色 permission 集合
PUT /roles/:id/permissions 全量取代 + parent closure + reload
GET /users/:uid/roles 使用者 role 列表
POST /users/:uid/roles 指派角色
DELETE /users/:uid/roles/:role_id 撤銷角色
GET /role-mappings 外部映射列表
PUT /role-mappings Upsert 外部映射
DELETE /role-mappings 刪除外部映射
POST /policy/reload 強制重載 policy單租戶或 *

完整 schema 見 generate/api/permission.api


6. Resource

資源 路徑
API 定義 generate/api/permission.api
Logic internal/logic/permission/
Middleware internal/middleware/casbin_rbac.go
模組原始碼 internal/model/permission/
開發 README internal/model/permission/README.md
Casbin 模型 etc/rbac.conf
Seed 資料 internal/model/permission/seed/catalog.json
Seed CLI cmd/permission-seed
設定範例 etc/gateway.dev.example.yamlPermission 區塊
設計參考 docs/identity-member-design.md §6 / §7.3 / §13