Skip to content

Commit 4b08cf1

Browse files
refactor: address PR reviews
1 parent df9f70f commit 4b08cf1

2 files changed

Lines changed: 72 additions & 2 deletions

File tree

openedx_authz/engine/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,8 @@ def migrate_authz_to_legacy_course_roles(
340340
role_assignments = [
341341
role_assignment
342342
for role_assignment in role_assignments
343-
if role_assignment.scope.course_id in course_id_list
343+
if isinstance(role_assignment.scope, CourseOverviewData) and
344+
role_assignment.scope.course_id in course_id_list
344345
]
345346

346347
roles_with_errors = []

openedx_authz/tests/test_migrations.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
from django.test import TestCase
99

1010
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+
)
1216
from openedx_authz.constants.roles import (
1317
COURSE_ADMIN,
1418
COURSE_DATA_RESEARCHER,
@@ -1333,3 +1337,68 @@ def test_rollback_org_level_scope_creates_org_only_course_access_role(self):
13331337
self.assertIsNotNone(recreated)
13341338
self.assertEqual(recreated.org, org_short_name_new)
13351339
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

Comments
 (0)