Skip to content

Commit ddaa056

Browse files
committed
test: update tests according model changes
1 parent 2c78e0e commit ddaa056

1 file changed

Lines changed: 83 additions & 40 deletions

File tree

openedx_authz/tests/test_enforcement.py

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""
2-
Tests for Casbin enforcement using model.conf and authz.policy files.
2+
Comprehensive test suite for Open edX authorization enforcement using Casbin.
33
4-
This module contains comprehensive tests for the authorization enforcement
5-
using Casbin with the configured model and policy files.
4+
This module validates the authorization system implemented with Casbin, testing
5+
various aspects of the permission model.
66
"""
77

88
import os
@@ -12,6 +12,8 @@
1212
import casbin
1313
from ddt import data, ddt, unpack
1414

15+
from openedx_authz import ROOT_DIRECTORY
16+
1517

1618
class AuthRequest(TypedDict):
1719
"""
@@ -43,27 +45,41 @@ class CasbinEnforcementTestCase(TestCase):
4345
"""
4446
Test case for Casbin enforcement policies.
4547
46-
This test class loads the model.conf and authz.policy files and runs
48+
This test class loads the model.conf and the provided policies and runs
4749
enforcement tests for different user roles and permissions.
4850
"""
4951

5052
@classmethod
5153
def setUpClass(cls) -> None:
52-
"""Set up the Casbin enforcer with model and policy files."""
54+
"""Set up the Casbin enforcer."""
5355
super().setUpClass()
5456

55-
engine_config_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "engine", "config")
57+
engine_config_dir = os.path.join(ROOT_DIRECTORY, "engine", "config")
5658
model_file = os.path.join(engine_config_dir, "model.conf")
5759

5860
if not os.path.isfile(model_file):
5961
raise FileNotFoundError(f"Model file not found: {model_file}")
6062

6163
cls.enforcer = casbin.Enforcer(model_file)
6264

63-
def _load_policy(self, policy: list[str] = None) -> None:
64-
"""Load policy into the enforcer."""
65+
def _load_policy(self, policy: list[str]) -> None:
66+
"""
67+
Load policy rules into the Casbin enforcer.
68+
69+
This method clears any existing policies and loads the provided policy rules
70+
into the appropriate policy stores (p for policies, g for role assignments,
71+
g2 for action groupings).
72+
73+
Args:
74+
policy (list[str]): List of policy rules where each rule is a
75+
list starting with the rule type ('p', 'g', or 'g2') followed by
76+
the rule parameters.
77+
78+
Raises:
79+
ValueError: If a policy rule has an invalid type (not 'p', 'g', or 'g2').
80+
"""
6581
self.enforcer.clear_policy()
66-
for rule in policy or []:
82+
for rule in policy:
6783
if rule[0] == "p":
6884
self.enforcer.add_named_policy("p", rule[1:])
6985
elif rule[0] == "g":
@@ -73,7 +89,7 @@ def _load_policy(self, policy: list[str] = None) -> None:
7389
else:
7490
raise ValueError(f"Invalid policy rule: {rule}")
7591

76-
def _test_enforcement(self, policy: list[str] = None, request: AuthRequest = None) -> None:
92+
def _test_enforcement(self, policy: list[str], request: AuthRequest) -> None:
7793
"""
7894
Helper method to test enforcement and provide detailed feedback.
7995
@@ -90,11 +106,18 @@ def _test_enforcement(self, policy: list[str] = None, request: AuthRequest = Non
90106

91107
@ddt
92108
class SystemWideRoleTests(CasbinEnforcementTestCase):
93-
"""Tests for system-wide roles with global access permissions."""
109+
"""
110+
Tests for system-wide roles with global access permissions.
111+
112+
This test class verifies that users assigned to system-wide roles (with global scope "*")
113+
can access resources across all scopes and namespaces. Platform administrators should
114+
have unrestricted access to manage any resource in the system, regardless of the
115+
specific scope (organization, course, library, etc.).
116+
"""
94117

95118
POLICY = [
96119
["p", "role:platform_admin", "act:manage", "*", "allow"],
97-
["g", "user:user-1", "role:platform_admin"],
120+
["g", "user:user-1", "role:platform_admin", "*"],
98121
] + COMMON_ACTION_GROUPING
99122

100123
GENERAL_CASES = [
@@ -132,11 +155,17 @@ def test_platform_admin_general_access(self, request: AuthRequest):
132155

133156
@ddt
134157
class ActionGroupingTests(CasbinEnforcementTestCase):
135-
"""Tests for action grouping."""
158+
"""
159+
Tests for action grouping and permission inheritance.
160+
161+
This test class verifies that action grouping works correctly, where high-level
162+
actions (like 'manage') automatically grant access to lower-level actions
163+
(like 'edit', 'read', 'write', 'delete') through the g2 grouping mechanism.
164+
"""
136165

137166
POLICY = [
138-
["p", "role:role-1", "act:manage", "org:any-org", "allow"],
139-
["g", "user:user-1", "role:role-1"],
167+
["p", "role:role-1", "act:manage", "org:*", "allow"],
168+
["g", "user:user-1", "role:role-1", "org:any-org"],
140169
] + COMMON_ACTION_GROUPING
141170

142171
CASES = [
@@ -174,29 +203,34 @@ def test_action_grouping_access(self, request: AuthRequest):
174203

175204
@ddt
176205
class RoleAssignmentTests(CasbinEnforcementTestCase):
177-
"""Tests for role assignment."""
206+
"""
207+
Tests for role assignment and scoped authorization.
208+
209+
This test class verifies that users with different roles can access resources
210+
within their assigned scopes.
211+
"""
178212

179213
POLICY = [
180214
# Policies
181215
["p", "role:platform_admin", "act:manage", "*", "allow"],
182-
["p", "role:org_admin", "act:manage", "org:any-org", "allow"],
183-
["p", "role:org_editor", "act:edit", "org:any-org", "allow"],
184-
["p", "role:org_author", "act:write", "org:any-org", "allow"],
185-
["p", "role:course_admin", "act:manage", "course-v1:any-org+any-course+any-course-run", "allow"],
186-
["p", "role:library_admin", "act:manage", "lib:any-library", "allow"],
187-
["p", "role:library_editor", "act:edit", "lib:any-library", "allow"],
188-
["p", "role:library_reviewer", "act:read", "lib:any-library", "allow"],
189-
["p", "role:library_author", "act:write", "lib:any-library", "allow"],
216+
["p", "role:org_admin", "act:manage", "org:*", "allow"],
217+
["p", "role:org_editor", "act:edit", "org:*", "allow"],
218+
["p", "role:org_author", "act:write", "org:*", "allow"],
219+
["p", "role:course_admin", "act:manage", "course-v1:*", "allow"],
220+
["p", "role:library_admin", "act:manage", "lib:*", "allow"],
221+
["p", "role:library_editor", "act:edit", "lib:*", "allow"],
222+
["p", "role:library_reviewer", "act:read", "lib:*", "allow"],
223+
["p", "role:library_author", "act:write", "lib:*", "allow"],
190224
# Role assignments
191-
["g", "user:user-1", "role:platform_admin"],
192-
["g", "user:user-2", "role:org_admin"],
193-
["g", "user:user-3", "role:org_editor"],
194-
["g", "user:user-4", "role:org_author"],
195-
["g", "user:user-5", "role:course_admin"],
196-
["g", "user:user-6", "role:library_admin"],
197-
["g", "user:user-7", "role:library_editor"],
198-
["g", "user:user-8", "role:library_reviewer"],
199-
["g", "user:user-9", "role:library_author"],
225+
["g", "user:user-1", "role:platform_admin", "*"],
226+
["g", "user:user-2", "role:org_admin", "org:any-org"],
227+
["g", "user:user-3", "role:org_editor", "org:any-org"],
228+
["g", "user:user-4", "role:org_author", "org:any-org"],
229+
["g", "user:user-5", "role:course_admin", "course-v1:any-org+any-course+any-course-run"],
230+
["g", "user:user-6", "role:library_admin", "lib:any-library"],
231+
["g", "user:user-7", "role:library_editor", "lib:any-library"],
232+
["g", "user:user-8", "role:library_reviewer", "lib:any-library"],
233+
["g", "user:user-9", "role:library_author", "lib:any-library"],
200234
] + COMMON_ACTION_GROUPING
201235

202236
CASES = [
@@ -264,12 +298,16 @@ def test_role_assignment_access(self, request: AuthRequest):
264298

265299
@ddt
266300
class DeniedAccessTests(CasbinEnforcementTestCase):
267-
"""Tests for denied access."""
301+
"""Tests for denied access scenarios.
302+
303+
This test class verifies that the authorization system correctly denies access
304+
when explicit deny rules override allow rules.
305+
"""
268306

269307
POLICY = [
270308
["p", "role:platform_admin", "act:manage", "*", "allow"],
271309
["p", "role:platform_admin", "act:manage", "org:restricted-org", "deny"],
272-
["g", "user:user-1", "role:platform_admin"],
310+
["g", "user:user-1", "role:platform_admin", "*"],
273311
] + COMMON_ACTION_GROUPING
274312

275313
CASES = [
@@ -319,7 +357,12 @@ def test_denied_access(self, request: AuthRequest):
319357

320358
@ddt
321359
class WildcardScopeTests(CasbinEnforcementTestCase):
322-
"""Tests for wildcard scope."""
360+
"""Tests for wildcard scope authorization patterns.
361+
362+
Verifies that users with roles assigned to wildcard scopes (like "*" for global access
363+
or "org:*" for organization-wide access) can properly access resources within their
364+
authorized scope boundaries.
365+
"""
323366

324367
POLICY = [
325368
# Policies
@@ -328,10 +371,10 @@ class WildcardScopeTests(CasbinEnforcementTestCase):
328371
["p", "role:course_admin", "act:manage", "course-v1:*", "allow"],
329372
["p", "role:library_admin", "act:manage", "lib:*", "allow"],
330373
# Role assignments
331-
["g", "user:user-1", "role:platform_admin"],
332-
["g", "user:user-2", "role:org_admin"],
333-
["g", "user:user-3", "role:course_admin"],
334-
["g", "user:user-4", "role:library_admin"],
374+
["g", "user:user-1", "role:platform_admin", "*"],
375+
["g", "user:user-2", "role:org_admin", "*"],
376+
["g", "user:user-3", "role:course_admin", "*"],
377+
["g", "user:user-4", "role:library_admin", "*"],
335378
] + COMMON_ACTION_GROUPING
336379

337380
@data(

0 commit comments

Comments
 (0)