Skip to content

URD: Phân quyền

ModulePhiên bảnCập nhật
CORE-02v0.82026-07-15

Module Phân quyền làm gì

Xác định cách kiểm soát truy cập vào tính năng và dữ liệu. Phân quyền cho quản trị viên gán vai trò cho người dùng, cấp quyền cho các vai trò đó, giới hạn vai trò trong phạm vi một organizer hoặc merchant cụ thể, và làm cho mọi truy vấn được lọc tự động theo đúng phạm vi mà người dùng yêu cầu được phép xem.

Toàn bộ chạy trên một mô hình RBAC dựa trên độ ưu tiên của Casbin, có phạm vi (domain) theo từng merchant.

Sáu ý cần hiểu trước

Đây là phần quan trọng nhất của tài liệu. Hiểu sáu ý dưới đây là hiểu 80% module.

Xuyên suốt phần này ta dùng một ví dụ duy nhất. Chị Hoa là Owner của organizer Cà phê Sáu Béo, có 3 merchant: Sáu Béo Quận 1 (trụ sở), Sáu Béo Thủ Đức, Sáu Béo Gò Vấp. Anh Tuấn là thu ngân ở Quận 1. Chị Mai là nhân viên phục vụ ở Thủ Đức.

1. Quyền được cấp theo cụm, không theo từng nút bấm

Cách nghĩ tự nhiên là: có bao nhiêu nút thì cấp bấy nhiêu quyền. Hệ thống không làm vậy. Toàn hệ có khoảng 755 thao tác có thể cấp quyền, chia thành 14 nhóm nghiệp vụ: Bán hàng, Kho, Sản phẩm, Thanh toán, Tài chính, Bảng giá, Hóa đơn, Thuế, Sổ công nợ, Giấy phép, Tài khoản, Chăm sóc khách, Cảnh báo, Hỗ trợ. Nếu cấp lẻ từng thao tác thì vai trò Owner sẽ phải mang 755 dòng quyền.

Thay vào đó hệ thống cấp một dòng cho cả một cụm, rồi tự nở ra. Nở theo hai chiều.

Chiều thứ nhất là cây tài nguyên: nhóm nghiệp vụ chứa các đối tượng, đối tượng chứa các thao tác. Cấp trên nhóm Bán hàng là tự động phủ Đơn hàng, Dòng hàng trong đơn, Ca làm việc, và mọi thao tác bên dưới chúng.

Chiều thứ hai là thang hành động: một mức cao thỏa mãn mọi mức thấp hơn nó.

Mức được cấpBao gồm những gì
Toàn quyền (manage)Đọc + Ghi + Thực thi. Cao nhất, phủ hết.
Ghi (write)Tạo, Sửa, Xóa
Đọc (read)Chỉ xem, không đổi được gì
Thực thi (execute)Chạy một thao tác nghiệp vụ (chốt ca, phát hành hóa đơn) mà không phải là ghi dữ liệu thường

Ghép hai chiều lại: vai trò Owner của chị Hoa chỉ mang đúng 14 dòng quyền - mỗi nhóm nghiệp vụ một dòng ở mức Toàn quyền. Vai trò Thu ngân của anh Tuấn mang ít hơn nhiều:

Nhóm nghiệp vụMức của Thu ngânNghĩa là
Bán hàngToàn quyềnMở đơn, sửa đơn, chốt đơn, chốt ca
Thanh toánGhiNhận tiền, ghi giao dịch
KhoĐọcXem còn bao nhiêu hàng, không được nhập/xuất
Sản phẩmĐọcXem danh mục món, không sửa được giá
Hóa đơnĐọcXem trạng thái hóa đơn của đơn vừa bán

Anh Tuấn không có dòng nào cho Bảng giá, Thuế, Sổ công nợ, Tài khoản. Không có dòng nghĩa là không có quyền. Không cần viết ra một dòng "cấm".

2. Quyền hiệu lực gộp từ nhiều nguồn, và một lệnh cấm luôn thắng một lệnh cho phép

Quyền của một người đến từ hai nguồn, cộng lại:

  1. Quyền theo vai trò - anh Tuấn là Thu ngân, nên anh có mọi thứ vai trò Thu ngân có.
  2. Quyền cấp thẳng cho cá nhân - chị Hoa cấp riêng cho anh Tuấn quyền Đọc trên Bảng giá, dù vai trò Thu ngân không có.

Hai nguồn gộp lại rồi khử trùng: một quyền có ở cả hai nguồn thì chỉ tính một lần. Khi màn hình hỏi "anh Tuấn thực sự được làm gì", hệ thống trả về tập đã gộp này. Có thể hỏi tách riêng "chỉ phần cấp thẳng" hoặc "chỉ phần thừa hưởng từ vai trò" khi cần soi ai đã cấp gì cho ai.

Nhưng gộp không phải là cộng dồn thuần túy. Một dòng quyền không chỉ mang mức, nó còn mang hiệu lực: cho phép hoặc cấm. Và luật là: cấm thắng cho phép, bất kể dòng nào rộng hơn.

Đây là chỗ phản trực giác nhất của cả module. Nó tồn tại để khoét một lỗ nhỏ trong một quyền lớn, thay vì phải bỏ quyền lớn đi rồi liệt kê lại từng thao tác nhỏ.

Ba ví dụ đang chạy thật trong hệ thống:

AiDòng cho phép (rộng)Dòng cấm (hẹp)Kết quả thật
Chị Mai (Nhân viên)Ghi trên cả nhóm Bán hàngCấm Ghi trên Ca làm việcMai mở đơn, sửa đơn được, nhưng không mở/chốt được ca - chỉ xem ca
Anh Tuấn (Thu ngân)Toàn quyền trên nhóm Bán hàngCấm Toàn quyền trên Điều chỉnh caTuấn chốt ca bình thường, nhưng không sửa được số liệu ca đã chốt - chỉ Owner sửa
Chị Hoa (Owner)Toàn quyền trên nhóm Tài khoảnCấm Ghi trên Danh mục quyền gốcHoa xem được danh sách quyền để đi cấp cho nhân viên, nhưng không tự chế ra quyền mới - đó là việc của hệ thống

Chú ý ví dụ cuối: ngay cả Owner - người cao nhất trong một organizer - vẫn bị cấm ở vài chỗ. "Owner có toàn quyền" là một câu nói sai.

Ngoại lệ duy nhất: ba vai trò nội bộ Super Admin, Admin, Operator của đội vận hành không đi qua bộ máy này. Họ được cho qua thẳng, không xét quyền, không xét cấm, không bị lọc dữ liệu. Vì thế họ cũng không cần một dòng quyền nào cả.

3. Bậc ưu tiên: không ai đụng được vai trò ngang hoặc trên mình

Mỗi vai trò mang một con số ưu tiên. Con số này là cái cầu thang của cả hệ.

Vai tròƯu tiên
Super Admin999
Admin900
Operator600
Owner500
Cashier (Thu ngân)110
Employee (Nhân viên)100
Customer (Khách)10
Guest (Khách vãng lai)1

Vai trò tự tạo chỉ được nằm trong khoảng 100 tới 499 - tức luôn thấp hơn Owner, luôn cao hơn hoặc bằng Nhân viên. Không ai tạo được một vai trò tự chế ngang hàng Owner.

Luật chặn có một câu: muốn tạo, sửa, xóa, hay cấp phát một vai trò thì số ưu tiên của vai trò đó phải THẤP HƠN HẲN số ưu tiên cao nhất của chính mình. Ngang bằng cũng không được.

Chị Hoa (Owner, 500) muốn tạo vai trò "Quản lý merchant" ưu tiên 300 cho quản lý ở Thủ Đức: được. Chị đặt ưu tiên 500 cho vai trò đó: bị chặn. Chị muốn sửa vai trò Operator (600) của đội vận hành: bị chặn. Chị muốn gán vai trò Owner cho người khác trong organizer của mình: cũng bị chặn, vì Owner ngang chị.

Một chi tiết dễ hụt: hệ thống lấy số cao nhất trong các vai trò của người đang thao tác. Nếu một người vừa là Nhân viên (100) vừa là Quản lý merchant (300) thì trần của họ là 300, không phải 100.

Bậc ưu tiên còn quyết định nhìn thấy gì: khi chị Hoa mở màn chọn vai trò để gán cho nhân viên, danh sách chỉ hiện các vai trò dưới 500. Vai trò Operator, Admin, Super Admin thậm chí không xuất hiện trong danh sách.

4. Trần cấp phát: không cho được thứ mình không có

Bậc ưu tiên mới chỉ trả lời "được đụng vào vai trò nào". Nó chưa trả lời "được nhét quyền gì vào vai trò đó". Đây là hai khóa khác nhau và cả hai đều phải mở.

Luật thứ hai: mức bạn cấp cho người khác không được cao hơn mức bạn đang có trên chính tài nguyên đó.

Mức mình đang cóMức mình được phép cấp cho người khác
Toàn quyềnĐọc, Ghi, Thực thi, Toàn quyền (tất cả)
GhiChỉ Ghi
ĐọcChỉ Đọc
Thực thiChỉ Thực thi

Quay lại Sáu Béo. Chị Hoa có Toàn quyền trên nhóm Kho, nên chị cấp mức nào trên Kho cho vai trò "Quản lý merchant" cũng được.

Nhưng giả sử chị Hoa cấp cho vai trò "Quản lý merchant" mức Đọc trên Kho. Anh quản lý Thủ Đức mang vai trò đó, và anh muốn tạo tiếp một vai trò "Phụ kho" (ưu tiên 200 - thấp hơn 300 của anh, nên qua được khóa ưu tiên) rồi cấp cho nó mức Ghi trên Kho. Bị chặn. Anh chỉ có Đọc, anh chỉ được phát ra Đọc. Anh không thể tự nâng cấp mình bằng cách tạo một vai trò mạnh hơn mình rồi tự gán vào.

Khóa này chỉ đọc các quyền anh có qua vai trò. Quyền cấp thẳng cho cá nhân không làm trần của anh cao lên - đó là lựa chọn cố ý, thà chặn nhầm còn hơn mở nhầm. Và ba vai trò nội bộ của đội vận hành thì bỏ qua khóa này, như mọi thứ khác.

5. Đứng ở merchant nào thì chỉ thấy merchant đó

Đây là ý hay bị hiểu sai nhất, và hiểu sai thì lộ dữ liệu.

Chị Hoa sở hữu cả 3 merchant. Trực giác nói: chị mở màn Đơn hàng ra thì phải thấy đơn của cả 3. Không phải.

Mỗi request lên hệ thống đều mang theo merchant đang đứng - đúng một merchant, do màn hình đang chọn. Bộ lọc dữ liệu chỉ lọc theo đúng merchant đó. Chị Hoa đang đứng ở Quận 1 thì màn Đơn hàng chỉ ra đơn của Quận 1. Muốn xem Thủ Đức thì phải đổi merchant đang xem trên thanh chọn, rồi màn hình nạp lại.

Quyền của chị và merchant chị đang đứng là hai thứ tách rời:

Câu hỏiTrả lời bằng
Chị Hoa được làm gì?Các dòng quyền của vai trò Owner (điểm 1)
Chị Hoa được làm ở đâu?Danh sách merchant chị là thành viên
Lần bấm này chị đang làm ở merchant nào?Merchant đang đứng, đi kèm từng request

Các dòng quyền của Owner, Thu ngân, Nhân viên không ghim vào một merchant nào cả. Chúng có hiệu lực ở bất kỳ merchant nào mà người đó là thành viên. Nghĩa là ranh giới thật không nằm ở dòng quyền - nó nằm ở danh sách thành viên.

Nên: anh Tuấn là thành viên của Quận 1, không phải thành viên của Gò Vấp. Vai trò Thu ngân của anh cho anh mở đơn - nhưng chỉ ở Quận 1. Nếu anh đổi merchant đang đứng sang Gò Vấp, quyền Thu ngân của anh không theo sang, vì anh không phải thành viên ở đó.

Một điểm nhỏ nhưng quan trọng khi test: khi ai đó gọi thẳng một bản ghi ngoài phạm vi bằng mã của nó, hệ thống trả "không tìm thấy", chứ không trả "không có quyền". Cố ý như vậy - trả lời "không có quyền" là đã vô tình xác nhận bản ghi đó có tồn tại.

Có một cửa nằm ngoài luật này: các quyền dành cho khách vãng lai (người chưa đăng nhập, chưa có merchant nào) được đánh dấu toàn hệ. Nhờ vậy màn đăng ký organizer mới, tra cứu gói dịch vụ, tra mã số thuế vẫn chạy được ở thời điểm chưa hề tồn tại một merchant nào để mà đứng vào.

6. Owner lan xuống merchant mới bằng cách chép quyền vào, không phải tự suy ra

Chị Hoa mở merchant thứ 4: Sáu Béo Bình Thạnh. Chị vào quản lý được ngay, không ai phải cấp gì thêm. Câu hỏi là: hệ thống làm điều đó bằng cách nào?

Trực giác nói: hệ thống "hiểu" rằng Bình Thạnh nằm dưới organizer Cà phê Sáu Béo, và Hoa là Owner của organizer, nên suy ra Hoa có quyền ở Bình Thạnh. Không phải vậy. Hệ thống không suy ra gì cả.

Thứ thật sự xảy ra: ngay tại giây phút Bình Thạnh được tạo, hệ thống quét ngược lại, tìm mọi người vừa mang vai trò Owner vừa là thành viên của organizer Cà phê Sáu Béo - ra chị Hoa - rồi ghi thêm một dòng thành viên mới: "Hoa là thành viên của Bình Thạnh". Dòng đó là thật, nằm trong dữ liệu, đếm được.

Hệ quả phải nhớ, vì nó là nguồn của phần lớn lỗi phân quyền khó hiểu:

  • Việc chép chỉ chạy một lần, lúc tạo merchant. Ai được phong Owner sau khi các merchant đã tồn tại thì không tự nhiên có mặt ở các merchant cũ - phải thêm thành viên cho từng merchant.
  • Muốn cắt quyền của một Owner tại một merchant, phải gỡ đúng dòng thành viên của merchant đó. Gỡ ở organizer không làm các dòng merchant biến mất.
  • Số dòng thành viên nở theo số merchant. Một organizer 30 merchant thì mỗi Owner mang 30 dòng.

Ba luật của điểm 3, 4, 5 và cơ chế chép này giải thích được gần như mọi câu "tại sao người này không bấm được nút kia" mà đội hỗ trợ nhận hằng ngày.

Module có những gì

Bảy nhóm feature. Bấm vào mã AREA để sang tab Chi tiết đọc yêu cầu của nhóm đó.

AREATênTrạng thái
ROLEVai trò cố địnhMột phần
CROLEVai trò tùy chỉnhMột phần
PERMDanh mục quyềnĐã dựng
GRANTCấp / Thu hồiMột phần
EFFQuyền hiệu lực & Phạm viMột phần
HIERPhân cấp Tài nguyên, Hành động & DomainMột phần
DECLKhai báo quyềnMột phần

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.