Skip to content

Commit d41f678

Browse files
test: include test cases for org-level migrations
1 parent 749754c commit d41f678

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

openedx_authz/engine/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ def migrate_authz_to_legacy_course_roles(
338338
for role_assignment in role_assignments:
339339

340340
# Per valid role assignment, create corresponding CourseAccessRole entry
341+
# depending on whether the scope is course-level or org-level glob
341342
try:
342343
user_external_key = role_assignment.subject.external_key
343344
role_external_key = role_assignment.roles[0].external_key
@@ -355,12 +356,13 @@ def migrate_authz_to_legacy_course_roles(
355356
course_access_role_kwargs["org"] = role_assignment.scope.org
356357
else:
357358
logger.error(
358-
f"Unexpected scope type: {type(role_assignment.scope)} for RoleAssignment with scope: {scope_external_key}"
359+
f"Unexpected scope type: {type(role_assignment.scope)} for RoleAssignment with "
360+
f"scope: {scope_external_key}, user: {user_external_key} and role: {role_external_key}, skipping."
359361
)
360362
roles_with_errors.append(role_assignment)
361363
continue
362364

363-
course_access_role_model.objects.create(**course_access_role_kwargs)
365+
course_access_role_model.objects.get_or_create(**course_access_role_kwargs)
364366
roles_with_no_errors.append(role_assignment)
365367

366368
logger.info(

openedx_authz/tests/test_migrations.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.core.management import CommandError, call_command
88
from django.test import TestCase
99

10+
from openedx_authz.api.data import OrgCourseOverviewGlobData
1011
from openedx_authz.api.users import batch_unassign_role_from_users, get_user_role_assignments_in_scope
1112
from openedx_authz.constants.roles import (
1213
COURSE_ADMIN,
@@ -1001,3 +1002,60 @@ def test_migrate_authz_to_legacy_course_roles_with_library_env(self):
10011002

10021003
self.assertEqual(len(errors), 0)
10031004
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

Comments
 (0)