|
6 | 6 | import random |
7 | 7 | from unittest.mock import Mock, patch |
8 | 8 |
|
9 | | -import casbin |
10 | | -import pkg_resources |
11 | 9 | import ddt |
12 | 10 | from ccx_keys.locator import CCXLocator |
13 | 11 | from django.test import RequestFactory |
14 | 12 | from opaque_keys.edx.locations import CourseLocator |
| 13 | +from openedx_authz.api.users import assign_role_to_user_in_scope |
| 14 | +from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_EDITOR, COURSE_STAFF |
15 | 15 |
|
16 | 16 | from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient |
17 | 17 | from cms.djangoapps.contentstore.utils import delete_course |
|
34 | 34 | UserBasedRole |
35 | 35 | ) |
36 | 36 | from common.djangoapps.student.tests.factories import UserFactory |
37 | | -from common.djangoapps.util import course |
38 | 37 | from openedx.core.djangoapps.content.course_overviews.models import CourseOverview |
39 | 38 | from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory |
40 | 39 | from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES |
41 | 40 | from openedx.core.djangolib.testing.utils import AUTHZ_TABLES |
| 41 | +from openedx.core.djangoapps.authz.tests.mixins import AuthzTestMixin |
| 42 | +from openedx.core import toggles as core_toggles |
42 | 43 | from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order |
43 | 44 | from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order |
44 | 45 | from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order |
|
48 | 49 |
|
49 | 50 | QUERY_COUNT_TABLE_IGNORELIST = WAFFLE_TABLES + AUTHZ_TABLES |
50 | 51 |
|
51 | | -from rest_framework.test import APIClient |
52 | | -from openedx_authz.api.users import assign_role_to_user_in_scope |
53 | | -from openedx_authz.constants.roles import COURSE_STAFF, COURSE_EDITOR, COURSE_DATA_RESEARCHER |
54 | | -from openedx_authz.engine.enforcer import AuthzEnforcer |
55 | | -from openedx_authz.engine.utils import migrate_policy_between_enforcers |
56 | | - |
57 | | -from openedx.core import toggles as core_toggles |
58 | | - |
59 | | - |
60 | | -class AuthzTestMixin: |
61 | | - """ |
62 | | - Minimal reusable mixin for AuthZ-enabled tests. |
63 | | - """ |
64 | | - |
65 | | - @classmethod |
66 | | - def setUpClass(cls): |
67 | | - cls.toggle_patcher = patch.object( |
68 | | - core_toggles.AUTHZ_COURSE_AUTHORING_FLAG, |
69 | | - "is_enabled", |
70 | | - return_value=True, |
71 | | - ) |
72 | | - cls.toggle_patcher.start() |
73 | | - super().setUpClass() |
74 | | - |
75 | | - @classmethod |
76 | | - def tearDownClass(cls): |
77 | | - cls.toggle_patcher.stop() |
78 | | - super().tearDownClass() |
79 | | - |
80 | | - def setUp(self): |
81 | | - super().setUp() |
82 | | - |
83 | | - self._seed_policies() |
84 | | - |
85 | | - self.authorized_user = UserFactory() |
86 | | - self.unauthorized_user = UserFactory() |
87 | | - |
88 | | - self.authorized_client = APIClient() |
89 | | - self.authorized_client.force_authenticate(user=self.authorized_user) |
90 | | - |
91 | | - self.unauthorized_client = APIClient() |
92 | | - self.unauthorized_client.force_authenticate(user=self.unauthorized_user) |
93 | | - |
94 | | - def tearDown(self): |
95 | | - super().tearDown() |
96 | | - AuthzEnforcer.get_enforcer().clear_policy() |
97 | | - |
98 | | - def add_user_to_role(self, user, role, course_key): |
99 | | - """Helper method to add a user to a role for the course.""" |
100 | | - assign_role_to_user_in_scope( |
101 | | - user.username, |
102 | | - role, |
103 | | - str(course_key) |
104 | | - ) |
105 | | - AuthzEnforcer.get_enforcer().load_policy() |
106 | | - |
107 | | - @classmethod |
108 | | - def _seed_policies(cls): |
109 | | - global_enforcer = AuthzEnforcer.get_enforcer() |
110 | | - global_enforcer.load_policy() |
111 | | - |
112 | | - model_path = pkg_resources.resource_filename( |
113 | | - "openedx_authz.engine", |
114 | | - "config/model.conf", |
115 | | - ) |
116 | | - |
117 | | - policy_path = pkg_resources.resource_filename( |
118 | | - "openedx_authz.engine", |
119 | | - "config/authz.policy", |
120 | | - ) |
121 | | - |
122 | | - migrate_policy_between_enforcers( |
123 | | - source_enforcer=casbin.Enforcer(model_path, policy_path), |
124 | | - target_enforcer=global_enforcer, |
125 | | - ) |
126 | 52 |
|
127 | 53 | @ddt.ddt |
128 | 54 | class TestCourseListing(ModuleStoreTestCase): |
@@ -497,6 +423,7 @@ def setUp(self): |
497 | 423 | self.factory = RequestFactory() |
498 | 424 |
|
499 | 425 | def _create_course(self, course_key): |
| 426 | + """Helper method to create a course and its overview.""" |
500 | 427 | course = CourseFactory.create( |
501 | 428 | org=course_key.org, |
502 | 429 | number=course_key.course, |
@@ -663,20 +590,38 @@ def mock_is_enabled(*args, **kwargs): |
663 | 590 | # so these three courses should be returned in the course listing even if the toggle is enabled |
664 | 591 | # for authz_enable_course_3 but no role is assigned for it. |
665 | 592 | self.assertEqual(len(courses), 3) |
666 | | - self.assertTrue(all(course.id in [authz_enable_course_1.id, authz_enable_course_2.id, legacy_course_1.id] for course in courses)) |
| 593 | + self.assertTrue( |
| 594 | + all(course.id in [authz_enable_course_1.id, authz_enable_course_2.id, legacy_course_1.id] |
| 595 | + for course in courses |
| 596 | + ) |
| 597 | + ) |
667 | 598 |
|
668 | 599 | # Case 2: Staff user should have access to all courses regardless of authz permissions. |
669 | 600 | # Pending authz_course_3 to check as staff |
670 | 601 | GlobalStaff().add_users(self.authorized_user) |
671 | 602 | courses_list, _ = get_courses_accessible_to_user(request) |
672 | 603 | courses = list(courses_list) |
673 | 604 | self.assertEqual(len(courses), 6) |
674 | | - self.assertTrue(all(course.id in [authz_enable_course_1.id, authz_enable_course_2.id, authz_enable_course_3.id, legacy_course_1.id, legacy_course_2.id, legacy_course_3.id] for course in courses)) |
| 605 | + self.assertTrue( |
| 606 | + all( |
| 607 | + course.id in |
| 608 | + [authz_enable_course_1.id, authz_enable_course_2.id, authz_enable_course_3.id, |
| 609 | + legacy_course_1.id, legacy_course_2.id, legacy_course_3.id] |
| 610 | + for course in courses |
| 611 | + ) |
| 612 | + ) |
675 | 613 |
|
676 | 614 | # Case 3: Superuser should have access to all courses regardless of authz permissions. |
677 | 615 | superuser = UserFactory(is_superuser=True) |
678 | 616 | request.user = superuser |
679 | 617 | courses_list, _ = get_courses_accessible_to_user(request) |
680 | 618 | courses = list(courses_list) |
681 | 619 | self.assertEqual(len(courses), 6) |
682 | | - self.assertTrue(all(course.id in [authz_enable_course_1.id, authz_enable_course_2.id, authz_enable_course_3.id, legacy_course_1.id, legacy_course_2.id, legacy_course_3.id] for course in courses)) |
| 620 | + self.assertTrue( |
| 621 | + all( |
| 622 | + course.id in |
| 623 | + [authz_enable_course_1.id, authz_enable_course_2.id, authz_enable_course_3.id, |
| 624 | + legacy_course_1.id, legacy_course_2.id, legacy_course_3.id] |
| 625 | + for course in courses |
| 626 | + ) |
| 627 | + ) |
0 commit comments