Skip to content

Commit 0675eea

Browse files
feat: consider org-level - org scope match access when migrating to new model
1 parent ef8b1d1 commit 0675eea

2 files changed

Lines changed: 40 additions & 7 deletions

File tree

openedx_authz/api/data.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,24 @@ def validate_external_key(cls, external_key: str) -> bool:
710710

711711
return True
712712

713+
@classmethod
714+
def build_external_key(cls, org: str) -> str:
715+
"""Build the external key for all resources within the given organization.
716+
717+
Args:
718+
org (str): The organization identifier (e.g., ``DemoX``).
719+
720+
Returns:
721+
str: The external key for the org-level glob (e.g., ``course-v1:DemoX+*``).
722+
723+
Examples:
724+
>>> OrgCourseOverviewGlobData.build_external_key('DemoX')
725+
'course-v1:DemoX+*'
726+
>>> OrgContentLibraryGlobData.build_external_key('DemoX')
727+
'lib:DemoX:*'
728+
"""
729+
return f"{cls.NAMESPACE}{EXTERNAL_KEY_SEPARATOR}{org}{cls.ID_SEPARATOR}{GLOBAL_SCOPE_WILDCARD}"
730+
713731
@classmethod
714732
def get_org(cls, external_key: str) -> str | None:
715733
"""Extract the organization identifier from the glob pattern.

openedx_authz/engine/utils.py

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

1010
from casbin import Enforcer
1111

12-
from openedx_authz.api.data import CourseOverviewData
12+
from openedx_authz.api.data import CourseOverviewData, OrgCourseOverviewGlobData
1313
from openedx_authz.api.users import (
1414
assign_role_to_user_in_scope,
1515
batch_assign_role_to_users_in_scope,
@@ -188,6 +188,11 @@ def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_lis
188188
- user: subject
189189
- role: role
190190
191+
The scope assigned per row depends on which fields are set:
192+
- course_id set: course-level scope (e.g. "course-v1:OpenedX+CS101+2024").
193+
- course_id blank, org set: org-level glob scope (e.g. "course-v1:OpenedX+*").
194+
- both set: course_id takes precedence as the more specific scope.
195+
191196
param course_access_role_model: It should be the CourseAccessRole model. This is passed in because the function
192197
is intended to run within a Django migration context, where direct model imports can cause issues.
193198
param course_id_list: Optional list of course IDs to filter the migration.
@@ -198,9 +203,7 @@ def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_lis
198203
raise ValueError(
199204
"At least one of course_id_list or org_id must be provided to limit the scope of the migration."
200205
)
201-
course_access_role_filter = {
202-
"course_id__startswith": "course-v1:",
203-
}
206+
course_access_role_filter = {}
204207

205208
if org_id:
206209
course_access_role_filter["org"] = org_id
@@ -229,22 +232,34 @@ def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_lis
229232
permissions_with_errors.append(permission)
230233
continue
231234

235+
if permission.course_id:
236+
scope_external_key = str(permission.course_id)
237+
elif permission.org:
238+
scope_external_key = OrgCourseOverviewGlobData.build_external_key(permission.org)
239+
else:
240+
# This should not happen as either course_id or org should be defined for each permission, log and skip
241+
logger.error(
242+
f"Permission for User: {permission.user.username} has neither course_id nor org defined, skipping."
243+
)
244+
permissions_with_errors.append(permission)
245+
continue
246+
232247
# Permission applied to individual user
233248
logger.info(
234249
f"Migrating permission for User: {permission.user.username} "
235-
f"to Role: {role} in Scope: {permission.course_id}"
250+
f"to Role: {role} in Scope: {scope_external_key}"
236251
)
237252

238253
is_user_added = assign_role_to_user_in_scope(
239254
user_external_key=permission.user.username,
240255
role_external_key=role,
241-
scope_external_key=str(permission.course_id),
256+
scope_external_key=scope_external_key,
242257
)
243258

244259
if not is_user_added:
245260
logger.error(
246261
f"Failed to migrate permission for User: {permission.user.username} "
247-
f"to Role: {role} in Scope: {permission.course_id}"
262+
f"to Role: {role} in Scope: {scope_external_key}"
248263
)
249264
permissions_with_errors.append(permission)
250265
continue

0 commit comments

Comments
 (0)