|
7 | 7 | from django.core.management import CommandError, call_command |
8 | 8 | from django.test import TestCase |
9 | 9 |
|
| 10 | +from openedx_authz.api.data import OrgCourseOverviewGlobData |
10 | 11 | from openedx_authz.api.users import batch_unassign_role_from_users, get_user_role_assignments_in_scope |
11 | 12 | from openedx_authz.constants.roles import ( |
12 | 13 | COURSE_ADMIN, |
@@ -1001,3 +1002,60 @@ def test_migrate_authz_to_legacy_course_roles_with_library_env(self): |
1001 | 1002 |
|
1002 | 1003 | self.assertEqual(len(errors), 0) |
1003 | 1004 | self.assertEqual(len(successes), 12) |
| 1005 | + |
| 1006 | + @patch("openedx_authz.api.data.CourseOverview", CourseOverview) |
| 1007 | + def test_migrate_org_level_scope_creates_org_glob_assignment(self): |
| 1008 | + """A CourseAccessRole with org set and blank course_id maps to an OrgCourseOverviewGlobData scope. |
| 1009 | +
|
| 1010 | + Expected result: |
| 1011 | + User has a COURSE_ADMIN assignment under the org-level glob scope. |
| 1012 | + """ |
| 1013 | + org_short_name_new = f"{OBJECT_PREFIX}org2" |
| 1014 | + Organization.objects.create(name=f"{OBJECT_PREFIX}org2_full", short_name=org_short_name_new) |
| 1015 | + user = User.objects.create_user( |
| 1016 | + username=f"org_user_{OBJECT_PREFIX}", email=f"org_user_{OBJECT_PREFIX}@example.com" |
| 1017 | + ) |
| 1018 | + CourseAccessRole.objects.create(user=user, org=org_short_name_new, course_id="", role="instructor") |
| 1019 | + |
| 1020 | + _, _ = migrate_legacy_course_roles_to_authz( |
| 1021 | + CourseAccessRole, course_id_list=None, org_id=org_short_name_new, delete_after_migration=True |
| 1022 | + ) |
| 1023 | + AuthzEnforcer.get_enforcer().load_policy() |
| 1024 | + |
| 1025 | + org_scope = OrgCourseOverviewGlobData.build_external_key(org_short_name_new) |
| 1026 | + assignments = get_user_role_assignments_in_scope( |
| 1027 | + user_external_key=user.username, scope_external_key=org_scope |
| 1028 | + ) |
| 1029 | + self.assertEqual(len(assignments), 1) |
| 1030 | + self.assertEqual(assignments[0].roles[0], COURSE_ADMIN) |
| 1031 | + |
| 1032 | + @patch("openedx_authz.api.data.CourseOverview", CourseOverview) |
| 1033 | + def test_rollback_org_level_scope_creates_org_only_course_access_role(self): |
| 1034 | + """Rollback of an OrgCourseOverviewGlobData assignment recreates a CourseAccessRole with org only. |
| 1035 | +
|
| 1036 | + Expected result: |
| 1037 | + The recreated entry has org set and course_id is None (org-wide, not course-specific). |
| 1038 | + """ |
| 1039 | + org_short_name_new = f"{OBJECT_PREFIX}org2" |
| 1040 | + Organization.objects.create(name=f"{OBJECT_PREFIX}org2_full", short_name=org_short_name_new) |
| 1041 | + user = User.objects.create_user( |
| 1042 | + username=f"org_user_{OBJECT_PREFIX}", email=f"org_user_{OBJECT_PREFIX}@example.com" |
| 1043 | + ) |
| 1044 | + CourseAccessRole.objects.create(user=user, org=org_short_name_new, course_id="", role="instructor") |
| 1045 | + |
| 1046 | + migrate_legacy_course_roles_to_authz( |
| 1047 | + CourseAccessRole, course_id_list=None, org_id=org_short_name_new, delete_after_migration=True |
| 1048 | + ) |
| 1049 | + AuthzEnforcer.get_enforcer().load_policy() |
| 1050 | + |
| 1051 | + errors, successes = migrate_authz_to_legacy_course_roles( |
| 1052 | + CourseAccessRole, UserSubject, course_id_list=None, org_id=org_short_name_new, delete_after_migration=True |
| 1053 | + ) |
| 1054 | + |
| 1055 | + self.assertEqual(len(errors), 0) |
| 1056 | + self.assertEqual(len(successes), 1) |
| 1057 | + |
| 1058 | + recreated = CourseAccessRole.objects.filter(user=user, org=org_short_name_new).first() |
| 1059 | + self.assertIsNotNone(recreated) |
| 1060 | + self.assertEqual(recreated.org, org_short_name_new) |
| 1061 | + self.assertIsNone(recreated.course_id) |
0 commit comments