Cơ chế phân quyền trong Odoo
Odoo là một phần mềm ERP mã nguồn mở (và phần trả phí riêng) theo mô hình all-in-one, Odoo khá phù hợp cho doanh nghiệp vừa và nhỏ
- Trang chủ: https://www.odoo.com/
- Source code: https://github.com/odoo/odoo
bài viết này tham khảo tài liệu: https://www.odoo.com/documentation/13.0/developer/reference/addons/security.html
Ngoài cách quản lý quyền truy cập thủ công bằng custom code, Odoo cung cấp 2 cơ chế chính để cho phép hoặc từ chối quyền truy cập đến dữ liệu.
Cả 2 cơ chế trên đều liên kết đến đối tượng user
thông qua các group
: một user thuộc về 1 hoặc nhiều group, theo đó cơ chế bảo mật tương ứng với từng group sẽ áp dụng với các user trong group.
Access Control
Được quản lý bởi model ir.model.access
, xác định các quyền truy cập đối với toàn model.
Mỗi record trong ir.model.access
cho biết:
- model nào áp dụng
- cho phép các quyền gì (gồm 4 quyền)
- và (tùy chọn) áp dụng cho group nào.
Access Control mang tính thêm vào (additive), tức với model bất kỳ, user sẽ có tất cả các quyền tổng hợp từ tất cả các group mà user thuộc về, ví dụ: user thuộc về 1 group có quyền write
và user cũng thuộc 1 group khác có quyền delete
, tổng hợp lại, user sẽ có 2 quyền write
và delete
.
Nếu không có group nào được xác định, access control áp dụng cho tất cả các users, ngược lại, chỉ áp dụng cho các thành viên của nhóm tương ứng.
4 quyền tương ứng là:
- Quyền tạo
perm_create
- Quyền đọc
perm_read
- Quyền ghi
perm_write
- Quyền xóa
perm_unlink
Để tạo access control record, có thể dùng UI (menu Technical > Security > Access Rights) hoặc tạo file .csv
trong module, ví dụ:
nội dung file ir.model.access.csv
để phân quyền cho model social.account.link
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_social_account_link,social_account.social_account_link,model_social_account_link,base.group_user,1,0,0,0
sẽ tạo access control record như sau:
Record Rules
Record rules là các điều kiện mà dữ liệu cần thỏa để cho phép thực thi một hoạt động nào đó (tạo, đọc, ghi hoặc xóa), nó áp dụng theo cơ chế record-by-record (từng record một) sau khi access control đã áp dụng.
Một record rule bao gồm:
- Model nào áp dụng
- Danh sách các quyền áp dụng (có 4 quyền như trên)
- Danh sách các group áp dụng (nếu để trống, record rule trở thành Global rule)
- Một
domain
dùng để lọc các records sẽ áp dụng rule.Domain
được thiết lập với 2 biến giá trị trong context:user
(là user hiện tại đang login) vàtime
(là time module)
Global rule (áp dụng cho tất cả user) và group rule (áp dụng cho một nhóm user) có sự khác biệt:
- Global rule mang tính giảm trừ (subtractive), tức tất cả các global rule phải thỏa thì record mới truy cập được
- Group rule mang tính thêm vào (additive), tức chỉ cần 1 trong các rule thỏa (và đã thỏa global rule) thì record có thể truy cập
Điều này có nghĩa, với group rule, rule thứ nhất là từ chối truy cập, nhưng các group rule khác vẫn có thể mở rộng nó (cho phép một nhóm user nào đó truy cập), trong khi với global rule, chỉ có thể từ chối (hoặc sẽ không hiệu lực).
Để tạo record rules, có thể dùng UI (menu Technical > Security > Record Rules) hoặc tạo file .xml
trong module, ví dụ:
<record model="ir.rule" id="rule_change_request_global">
<field name="name">Change Request Global</field>
<field name="model_id" ref="model_document_page_history" />
<field name="groups" eval="[(6, 0, [ref('knowledge.group_document_user')])]" />
<field name="domain_force">['|',('state','=','approved'),('create_uid','=',user.id)]</field>
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />
<field name="perm_unlink" eval="True" />
<field name="perm_create" eval="True" />
</record>
sẽ tạo record rule như sau:
Chú ý: Record rule không áp dụng cho nhóm
superuser
Ngoài ra, Odoo cho phép quy định quyền truy cập với field
trong ORM model, với thuộc tính groups
để cho phép 1 tùy chọn các group (cách nhau bởi dấu phẩy) được quyền truy cập (read, write), cụ thể như sau:
Fields Access
Field
trong một ORM model có thể giới hạn quyền truy cập cho 1 số groups, ví dụ:
signup_token = fields.Char(copy=False, groups="base.group_erp_manager")
signup_type = fields.Char(string='Signup Token Type', copy=False, groups="base.group_erp_manager")
Nếu user hiện tại không thuộc trong danh sach các nhóm quy định, user sẽ không có quyền truy cập field (restricted fields):
- restricted fields sẽ tự động được loại bỏ trong views
- restricted fields bị remove trong
fields_get()
responses - hành động (cố tình) đọc hoặc ghi đến restricted fields sẽ raise
access error