|
8 | 8 | from django.test import TestCase |
9 | 9 |
|
10 | 10 | from openedx_authz.api.data import OrgCourseOverviewGlobData |
11 | | -from openedx_authz.api.users import batch_unassign_role_from_users, get_user_role_assignments_in_scope |
| 11 | +from openedx_authz.api.users import ( |
| 12 | + assign_role_to_user_in_scope, |
| 13 | + batch_unassign_role_from_users, |
| 14 | + get_user_role_assignments_in_scope, |
| 15 | +) |
12 | 16 | from openedx_authz.constants.roles import ( |
13 | 17 | COURSE_ADMIN, |
14 | 18 | COURSE_DATA_RESEARCHER, |
@@ -1333,3 +1337,68 @@ def test_rollback_org_level_scope_creates_org_only_course_access_role(self): |
1333 | 1337 | self.assertIsNotNone(recreated) |
1334 | 1338 | self.assertEqual(recreated.org, org_short_name_new) |
1335 | 1339 | self.assertIsNone(recreated.course_id) |
| 1340 | + |
| 1341 | + @patch("openedx_authz.api.data.CourseOverview", CourseOverview) |
| 1342 | + def test_org_id_filter_includes_glob_and_excludes_other_orgs(self): |
| 1343 | + """Rolling back with org_id includes org-level glob scopes and excludes assignments from other orgs. |
| 1344 | +
|
| 1345 | + Expected result: |
| 1346 | + The user with a glob scope in self.org is in successes; the user with a course-level |
| 1347 | + assignment in a different org is not. |
| 1348 | + """ |
| 1349 | + glob_scope = f"course-v1:{self.org}+*" |
| 1350 | + other_org_course_scope = f"course-v1:{OBJECT_PREFIX}filter_org2+FilterCourse+2024" |
| 1351 | + |
| 1352 | + user_glob = User.objects.create_user( |
| 1353 | + username=f"{OBJECT_PREFIX}filter_glob_user", email=f"{OBJECT_PREFIX}[email protected]" |
| 1354 | + ) |
| 1355 | + user_other_org = User.objects.create_user( |
| 1356 | + username=f"{OBJECT_PREFIX}filter_org2_user", email=f"{OBJECT_PREFIX}[email protected]" |
| 1357 | + ) |
| 1358 | + assign_role_to_user_in_scope(user_glob.username, COURSE_STAFF.external_key, glob_scope) |
| 1359 | + assign_role_to_user_in_scope(user_other_org.username, COURSE_STAFF.external_key, other_org_course_scope) |
| 1360 | + AuthzEnforcer.get_enforcer().load_policy() |
| 1361 | + |
| 1362 | + errors, successes = migrate_authz_to_legacy_course_roles( |
| 1363 | + CourseAccessRole, UserSubject, course_id_list=None, org_id=self.org, delete_after_migration=False |
| 1364 | + ) |
| 1365 | + |
| 1366 | + migrated_users = {assignment.subject.external_key for assignment in successes} |
| 1367 | + # glob assignment for self.org is included |
| 1368 | + self.assertIn(user_glob.username, migrated_users) |
| 1369 | + # assignment from the other org is excluded |
| 1370 | + self.assertNotIn(user_other_org.username, migrated_users) |
| 1371 | + self.assertEqual(len(errors), 0) |
| 1372 | + |
| 1373 | + @patch("openedx_authz.api.data.CourseOverview", CourseOverview) |
| 1374 | + def test_course_id_list_filter_excludes_glob_and_other_courses(self): |
| 1375 | + """Rolling back with course_id_list excludes org-level glob scopes and assignments from other courses. |
| 1376 | +
|
| 1377 | + Expected result: |
| 1378 | + The user with a glob scope and the user with a course-level assignment not in the list |
| 1379 | + are both absent from successes. |
| 1380 | + """ |
| 1381 | + glob_scope = f"course-v1:{self.org}+*" |
| 1382 | + other_course_scope = f"course-v1:{self.org}+FilterOtherCourse+2024" |
| 1383 | + |
| 1384 | + user_glob = User.objects.create_user( |
| 1385 | + username=f"{OBJECT_PREFIX}filter_glob_user", email=f"{OBJECT_PREFIX}[email protected]" |
| 1386 | + ) |
| 1387 | + user_other_course = User.objects.create_user( |
| 1388 | + username=f"{OBJECT_PREFIX}filter_other_course_user", email=f"{OBJECT_PREFIX}[email protected]" |
| 1389 | + ) |
| 1390 | + assign_role_to_user_in_scope(user_glob.username, COURSE_STAFF.external_key, glob_scope) |
| 1391 | + assign_role_to_user_in_scope(user_other_course.username, COURSE_STAFF.external_key, other_course_scope) |
| 1392 | + AuthzEnforcer.get_enforcer().load_policy() |
| 1393 | + |
| 1394 | + errors, successes = migrate_authz_to_legacy_course_roles( |
| 1395 | + CourseAccessRole, UserSubject, |
| 1396 | + course_id_list=[self.course_id], org_id=None, delete_after_migration=False |
| 1397 | + ) |
| 1398 | + |
| 1399 | + migrated_users = {assignment.subject.external_key for assignment in successes} |
| 1400 | + # org-level glob is excluded even though it belongs to the same org |
| 1401 | + self.assertNotIn(user_glob.username, migrated_users) |
| 1402 | + # course not in the list is excluded |
| 1403 | + self.assertNotIn(user_other_course.username, migrated_users) |
| 1404 | + self.assertEqual(len(errors), 0) |
0 commit comments