Skip to content

Commit df9f70f

Browse files
test: include test case for instance wide cases
1 parent e4f4eee commit df9f70f

2 files changed

Lines changed: 43 additions & 6 deletions

File tree

openedx_authz/engine/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from casbin import Enforcer
1111
from django.db.models import Q
12+
from opaque_keys.edx.django.models import CourseKeyField
1213

1314
from openedx_authz.api.data import CourseOverviewData, OrgCourseOverviewGlobData
1415
from openedx_authz.api.roles import get_all_role_assignments_per_scope_type
@@ -230,7 +231,7 @@ def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_lis
230231

231232
legacy_permissions = (
232233
course_access_role_model.objects.filter(**course_access_role_filter)
233-
.filter(Q(course_id="") | Q(course_id__startswith=CourseOverviewData.NAMESPACE))
234+
.filter(Q(course_id=CourseKeyField.Empty) | Q(course_id__startswith=CourseOverviewData.NAMESPACE))
234235
.select_related("user")
235236
.all()
236237
)
@@ -255,7 +256,7 @@ def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_lis
255256
elif permission.org:
256257
scope_external_key = OrgCourseOverviewGlobData.build_external_key(permission.org)
257258
else:
258-
# This should not happen as either course_id or org should be defined for each permission, log and skip
259+
# Instance-wide roles (no course_id, no org) are not supported by this migration, log and skip.
259260
logger.error(
260261
f"Permission for User: {permission.user.username} has neither course_id nor org defined, skipping."
261262
)

openedx_authz/tests/test_migrations.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Unit Tests for openedx_authz migrations."""
22

3-
from unittest.mock import patch
3+
from unittest.mock import MagicMock, patch
44

55
from django.contrib.auth import get_user_model
66
from django.contrib.auth.models import Group
@@ -278,11 +278,12 @@ def setUp(self):
278278
class MockPermission:
279279
"""Mock class to simulate CourseAccessRole entries for testing the rollback migration."""
280280

281-
def __init__(self, user, role, course_id, id_in):
281+
def __init__(self, user, role, course_id, id_in, *, org=""):
282282
self.user = user
283283
self.role = role
284284
self.course_id = course_id
285285
self.id = id_in
286+
self.org = org
286287

287288
class MockUser:
288289
"""Mock class to simulate User objects for testing the rollback migration."""
@@ -296,7 +297,7 @@ class MockQuerySet:
296297
def __init__(self, permissions):
297298
self.permissions = permissions
298299

299-
def filter(self, **kwargs):
300+
def filter(self, *args, **kwargs):
300301
return self
301302

302303
def select_related(self, *args, **kwargs):
@@ -1169,6 +1170,41 @@ def test_migrate_legacy_course_roles_to_authz_user_not_added(
11691170
self.assertEqual(len(successes), 0)
11701171
self.assertEqual(errors[0].user.username, "testuser")
11711172

1173+
@patch("openedx_authz.engine.utils.LEGACY_COURSE_ROLE_EQUIVALENCES", {"instructor": "instructor-role"})
1174+
def test_migrate_legacy_course_roles_to_authz_instance_wide_role_is_error(self):
1175+
"""Instance-wide roles (no course_id and no org) are logged as errors and skipped.
1176+
1177+
Expected result:
1178+
A CourseAccessRole with both course_id and org blank is logged as an error and
1179+
returned in permissions_with_errors, but not migrated.
1180+
"""
1181+
instance_wide_permission = MagicMock()
1182+
instance_wide_permission.user.username = "instance_user"
1183+
instance_wide_permission.role = "instructor"
1184+
instance_wide_permission.course_id = ""
1185+
instance_wide_permission.org = ""
1186+
1187+
mock_qs = MagicMock()
1188+
mock_qs.filter.return_value = mock_qs
1189+
mock_qs.select_related.return_value = mock_qs
1190+
mock_qs.all.return_value = [instance_wide_permission]
1191+
1192+
mock_model = MagicMock()
1193+
mock_model.objects.filter.return_value = mock_qs
1194+
1195+
with self.assertLogs("openedx_authz.engine.utils", level="ERROR") as log:
1196+
errors, successes = migrate_legacy_course_roles_to_authz(
1197+
mock_model,
1198+
course_id_list=["course-v1:test"],
1199+
org_id=None,
1200+
delete_after_migration=False,
1201+
)
1202+
1203+
self.assertEqual(len(errors), 1)
1204+
self.assertEqual(len(successes), 0)
1205+
self.assertEqual(errors[0].user.username, "instance_user")
1206+
self.assertTrue(any("instance_user" in msg for msg in log.output))
1207+
11721208
@patch("openedx_authz.api.data.CourseOverview", CourseOverview)
11731209
def test_migrate_authz_to_legacy_course_roles_user_not_added(self):
11741210
permissions_with_errors, permissions_with_no_errors = migrate_legacy_course_roles_to_authz(
@@ -1279,7 +1315,7 @@ def test_rollback_org_level_scope_creates_org_only_course_access_role(self):
12791315
user = User.objects.create_user(
12801316
username=f"org_user_{OBJECT_PREFIX}", email=f"org_user_{OBJECT_PREFIX}@example.com"
12811317
)
1282-
CourseAccessRole.objects.create(user=user, org=org_short_name_new, course_id="", role="instructor")
1318+
CourseAccessRole.objects.create(user=user, org=org_short_name_new, role="instructor")
12831319

12841320
migrate_legacy_course_roles_to_authz(
12851321
CourseAccessRole, course_id_list=None, org_id=org_short_name_new, delete_after_migration=True

0 commit comments

Comments
 (0)