Giao diện
Engine ACL
Không trùng với plugin plugin-acl (đồng bộ DB) - đây là thư viện runtime thuần bộ nhớ.
1) Tổng quan kiến trúc
2) Các thành phần chi tiết
| Thành phần | Trách nhiệm |
|---|---|
roles | Map<string, ACLRole> - định nghĩa qua define({ role, strategy?, actions?, snippets? }) |
allowManager | Đăng ký ngoại lệ "cho phép" resource/action theo điều kiện |
snippetManager | Nhóm quyền theo snippet (pattern action path, hỗ trợ ! phủ định) |
fixedParamsManager | Gộp params cố định vào kết quả can (filter bổ sung) |
availableActions | Action khả dụng từ plugin collection (export, import...) |
actionAlias | Mapping alias → action thực |
availableStrategy | Strategy mặc định cho role |
middlewares | Pipeline ACL (topo sort) - allow-manager trước core |
3) Luồng can() - kiểm tra quyền
can({ role, resource, action })hoặccan({ roles, resource, action }).- Nếu có
roottrongroles→ chỉ xétroot(superadmin). - Role thường: kiểm tra action trên
ACLRole; nếu không có config cụ thể → dùng strategy + snippet (minimatch trênresource:action). fixedParamsManager.getParams(resource, action)merge vàoparamskết quả.
4) allow() / AllowManager - ngoại lệ cho phép
Tra cứu hỗ trợ wildcard * cho resource hoặc action.
| Điều kiện | Ý nghĩa | Ví dụ |
|---|---|---|
'public' | Không cần đăng nhập | Login page, health check |
'loggedIn' | Chỉ cần có currentUser | Profile page |
'allowConfigure' | Role có allowConfigure trong strategy | Admin settings |
function | Custom logic | Check IP, check feature flag |
allow vs skip
Trong source code, allow còn có tên nội bộ skip (deprecated). Cả hai đều ủy quyền cho AllowManager. Dùng allow trong code mới.
5) Snippet - nhóm quyền theo pattern
registerSnippet({ name, actions })-actionslà glob pattern (minimatch) cho path dạngresource:action.- Role có thể được gán snippet; snippet quyết định mở API UI/plugin.
- Ví dụ:
ui.*match tất cả action liên quan UI,pm.*match tất cả plugin management. - Hỗ trợ
!phủ định:!pm.userstừ chối action trên resourcepm.users.
6) fixedParams - filter ẩn theo role
Fixed params cho phép inject filter vào mọi request cho resource/action cụ thể theo role:
| Tình huống | Fixed params | Hiệu ứng |
|---|---|---|
| "View own" | { filter: { createdById: currentUserId } } | User chỉ thấy record mình tạo |
| "Department scope" | { filter: { departmentId: { $in: userDepts } } } | User thấy record của department |
| "Field restriction" | { fields: ['name', 'email'] } | Chỉ trả về một số field |
Merge, không overwrite
Fixed params được merge vào can() result (dùng and-merge cho filter). Plugin hoặc client không thể bypass filter này vì nó được inject ở tầng ACL.
7) Middleware ACL
Pipeline middleware ACL gồm hai stage (topo):
allow-manager- kiểm tra ngoại lệ trước.core- kiểm tra quyền thực tế quacan().
8) setAvailableAction / strategy resource
| API | Mô tả |
|---|---|
setAvailableAction(name, config) | Plugin đăng ký action trên collection (export, import...) |
setStrategyResources(resources) | Set danh sách collection áp dụng strategy mặc định |
appendStrategyResource(resource) | Thêm một collection vào strategy list |
9) beforeGrantAction - hook phân quyền
Listener chuỗi beforeGrantAction:
- Merge
params.ownvới predicate (ví dụ:{ createdById: currentUser.id }). - Chuyển
fields→whitelistcho actioncreate/update.
10) Error handling
NoPermissionErrorvà các export trongerrors/- dùng khi từ chối quyền có kiểm soát.- Client nhận HTTP 403 với error code rõ ràng.
11) Phân biệt ACL engine vs plugin-acl
ACL Engine (@digiforce-nc/acl) | Plugin ACL (plugin-acl) | |
|---|---|---|
| Vị trí | packages/core/acl/ | packages/plugins/@digiforce-nc/plugin-acl/ |
| Dữ liệu | Trong bộ nhớ (Map) | Đồng bộ từ DB |
| Trách nhiệm | Check quyền runtime | CRUD cấu hình quyền, sync → engine |
| API | acl.define(), acl.can() | Admin UI, REST API quản lý roles |
Đọc tiếp
- Resourcer & Actions - action pipeline mà ACL bảo vệ
- DataSourceManager -
dataSource.acllà instance gắn với từng data source - Auth & AuthManager - xác thực trước phân quyền