Appearance
Perm-v2: Gán phân quyền cho tính năng mới
Tài liệu này mô tả luồng chuẩn để cấp quyền cho:
- tính năng mới
- module mới
- table/query/mutation mới
- Hasura action mới
Trong hệ thống hiện tại, quyền được kiểm tra qua 2 lớp:
perm-v2trong auth middleware- Hasura metadata permission
Chỉ cần thiếu 1 trong 2 lớp thì tính năng vẫn không dùng được.
Hiểu Nhanh Về Cơ Chế
Flow hiện tại:
account_role -> role_module(module_id, portal, actions) -> auth allow-list -> Hasura table/action/function permission
Các điểm quan trọng:
- Auth middleware kiểm tra theo
root GraphQL operation - Một request GraphQL chỉ cần có 1 root operation chưa được map là cả request bị fail
- Có quyền menu không đồng nghĩa với có quyền gọi API
- Có Hasura permission không đồng nghĩa với qua được
perm-v2
Khi Nào Cần Dùng Tài Liệu Này
Áp dụng khi:
- thêm màn hình mới
- thêm table query/mutation mới
- thêm Hasura action mới
- thêm module mới trong phân quyền động
- màn hình đã được gán role nhưng vẫn bị
permission denied
Bước 1: Xác Định Tính Năng Thuộc Module Nào
Trước tiên cần chốt rõ:
- tính năng này thuộc
modulenào - tính năng này chạy ở
portalnào:admin,crm,pos,staff, ... - tính năng này cần action nào:
access,create,update,delete,approve,payment,view_all
Nếu đã có module sẵn:
- dùng lại
module_idhiện có
Nếu là module mới:
- thêm record vào
public.module - thêm các action vào
public.module_permission_action - thêm mapping operation vào
services/auth/server/config.go
Bước 2: Liệt Kê Toàn Bộ Root GraphQL Operation
Đây là bước dễ bị sót nhất.
Cần liệt kê toàn bộ root operation mà màn hình thực tế gọi, ví dụ:
groupgroup_membergroup_rolemodule_permission_actionrole_moduleupdateRoleModuleShowSumcardData
Lưu ý:
- không chỉ liệt kê table chính
- cần liệt kê cả các root query/mutation phụ trong cùng request
- nếu frontend gửi 1 request có nhiều root operation, chỉ cần 1 root chưa được map là cả request fail
Bước 3: Map Root Operation Vào Perm-v2
File chính:
services/auth/server/config.go
Hiện tại có 3 cách mở operation:
3.1. Common Operations
Thêm vào CommonQueryMutationList khi operation đó được phép cho mọi user phù hợp với flow chung của hệ thống.
Dùng cho các root operation thật sự mang tính dùng chung.
3.2. User Operations
Thêm vào UserQueryMutationList khi operation đó dành cho user đã xác thực nhưng không nhất thiết phải gắn vào 1 module nghiệp vụ cụ thể.
3.3. Module Operations
Thêm vào ModuleOperationMapping[module_id][action] khi operation thuộc về một module cụ thể.
Đây là cách ưu tiên cho feature nghiệp vụ.
Ví dụ:
- operation quản lý role, role_module, account_role thường nên gắn vào
internal_configuration - operation liên quan đến khách hàng, CRM, đơn hàng thường nên gắn vào
customer_management
Bước 4: Mở Hasura Metadata Permission
Sau khi request đi qua auth middleware, nó mới tới Hasura.
Vì vậy cần mở đúng metadata ở lớp Hasura:
- table:
services/controller/metadata/databases/.../tables/*.yaml - function:
services/controller/metadata/databases/.../functions/*.yaml - action:
services/controller/metadata/actions.yaml
Cần kiểm tra đúng loại permission:
select_permissionsinsert_permissionsupdate_permissionsdelete_permissions- action
permissions
Lưu ý:
perm-v2pass nhưng Hasura chưa mở thì vẫn fail- Hasura mở rồi nhưng auth config chưa map thì vẫn fail
Bước 5: Nếu Là Module Mới, Tạo Action Cho Module
Nếu module mới chưa có action trong UI phân quyền:
- thêm action vào
public.module_permission_action
Thông thường sẽ có:
accesscreateupdatedeleteapprovepaymentview_all
Nếu thiếu các action này thì UI phân quyền và dữ liệu role_module.actions sẽ không đầy đủ.
Bước 6: Cấp Quyền Cho Role
Cấp quyền bằng role_module.
Các trường quan trọng:
role_idmodule_idportalactions
Ví dụ:
sql
INSERT INTO public.role_module (role_id, module_id, portal, actions, priority)
VALUES (
'it_leader',
'internal_configuration',
'admin',
ARRAY['access', 'update'],
0
);Nếu role đã có row rồi thì cập nhật actions hoặc metadata, không nên insert trùng bừa.
Bước 7: Gán Role Cho User
Gán role cho user qua account_role.
sql
INSERT INTO public.account_role (account_id, role_id)
VALUES ('USER_ID', 'ROLE_ID');Nếu chỉ muốn đúng 1 user có quyền đó:
- tạo role riêng
- cấp
role_modulecho role đó - gán role vào user
Bước 8: Kiểm Tra Cache
Đây là điểm rất hay gây nhầm.
- thay đổi
role_modulethường được auth service clear cache - thay đổi
account_rolecó thể chưa làm auth cache được clear ngay
Nếu vừa gán role xong mà vẫn chưa ăn:
- đợi cache hết hạn
- hoặc clear cache auth/Redis theo quy trình nội bộ
Bước 9: Test Bằng Account Thật
Không nên chỉ test bằng admin hoặc account siêu quyền.
Cần test bằng đúng account:
- có
portalđúng - có
roleđúng - đi vào đúng màn hình thật
Nên test 3 mức:
- request GraphQL thật của màn hình
- auth log để xem bị chặn ở root operation nào
- Hasura response để xác định fail ở metadata hay fail từ auth middleware
Nếu Là Từng Loại Thay Đổi Thì Cần Làm Gì
A. Thêm Module Mới
Cần làm:
- thêm
public.module - thêm
public.module_permission_action - thêm
ModuleOperationMappingtrongservices/auth/server/config.go - mở Hasura metadata cho table/action/function liên quan
- cấp
role_module - gán
account_role
B. Thêm Table Query/Mutation Mới
Cần làm:
- xác định root operation tên gì
- map root đó vào auth config
- mở Hasura metadata permission cho table
- test bằng request thật
C. Thêm Hasura Action Mới
Cần làm:
- thêm action vào
services/controller/metadata/actions.yaml - thêm schema vào
services/controller/metadata/actions.graphql - set đúng
permissions - map tên mutation/action vào auth config
- test bằng role thật
Cách Debug Khi “Đã Có Quyền Rồi Mà Vẫn Không Chạy”
Kiểm tra theo đúng thứ tự này:
- Feature này thuộc module nào?
- Root operation nào đang được gọi thực tế?
- Root operation đó đã được map trong
services/auth/server/config.gochưa? - Hasura table/action/function permission đã mở chưa?
- User đã có
account_roleđúng chưa? - Role đã có
role_moduleđúngportalvàactionschưa? - Có đang dính cache auth không?
Các Lỗi Hay Gặp
1. View query group nhưng thực ra fail do group_role hoặc group_member
Rất nhiều màn hình không chỉ query 1 root.
Ví dụ 1 request có thể gọi cùng lúc:
groupgroup_membergroup_rolemodule_permission_action
Nếu chỉ mở group mà chưa mở các root còn lại thì cả view vẫn fail.
2. Có Hasura permission nhưng vẫn permission denied
Nguyên nhân thường là auth middleware chưa map root operation đó vào perm-v2.
3. Có role_module nhưng vẫn không chạy
Thường là do:
- sai
portal - thiếu action cần thiết
- user chưa được gán role đúng
- đang dùng cache cũ
4. Nghĩ Rằng Module Cha Tự Động Ăn Module Con
Hiện tại auth check theo operation mapping, không check đệ quy theo parent_id.
Nghĩa là:
- có module cha không đồng nghĩa tự động được tất cả operation bên dưới
- vẫn phải map đúng root operation vào module tương ứng
Checklist Copy-paste Cho Team
Trước khi merge feature có permission mới, kiểm tra:
- [ ] Feature thuộc module nào?
- [ ] Chạy ở portal nào?
- [ ] Cần action nào?
- [ ] Frontend gọi những root GraphQL operation nào?
- [ ] Đã map hết các root đó trong
services/auth/server/config.gochưa? - [ ] Đã mở Hasura metadata permission chưa?
- [ ] Nếu là action mới: đã khai báo trong
actions.yamlvàactions.graphqlchưa? - [ ] Đã cấp
role_modulecho role cần dùng chưa? - [ ] Đã gán
account_rolecho user test chưa? - [ ] Đã test bằng account thật chưa?
- [ ] Đã kiểm tra cache auth chưa?
Gợi Ý Quy Trình Thực Tế Khi Làm Feature Mới
Nên làm theo thứ tự này:
- Viết ra danh sách root operation của màn hình
- Map các operation đó vào
perm-v2 - Mở Hasura metadata
- Cấp
role_module - Gán role vào user test
- Test request thật
- Nếu fail thì đọc auth log để xem
denied_operation
Làm theo thứ tự này sẽ nhanh hơn rất nhiều so với việc sửa từng chỗ một cách mò mẫm.