Skip to content

Commit af13f30

Browse files
committed
fixup! feat: add course authoring migration and rollback scripts
1 parent bd4f1a3 commit af13f30

3 files changed

Lines changed: 26 additions & 10 deletions

File tree

openedx_authz/engine/utils.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def migrate_legacy_permissions(ContentLibraryPermission):
168168
return permissions_with_errors
169169

170170

171-
def migrate_legacy_course_roles_to_authz(CourseAccessRole, course_id_list, org_id, delete_after_migration):
171+
def migrate_legacy_course_roles_to_authz(course_access_role_model, course_id_list, org_id, delete_after_migration):
172172
"""
173173
Migrate legacy course role data to the new Casbin-based authorization model.
174174
This function reads legacy permissions from the CourseAccessRole model
@@ -187,7 +187,11 @@ def migrate_legacy_course_roles_to_authz(CourseAccessRole, course_id_list, org_i
187187
- user: subject
188188
- role: role
189189
190-
param CourseAccessRole: The CourseAccessRole model to use.
190+
param course_access_role_model: The CourseAccessRole model to use. This is passed in because the function
191+
is intended to run within a Django migration context, where direct model imports can cause issues.
192+
param course_id_list: Optional list of course IDs to filter the migration.
193+
param org_id: Optional organization ID to filter the migration.
194+
param delete_after_migration: Whether to delete successfully migrated legacy permissions after migration.
191195
"""
192196
if not course_id_list and not org_id:
193197
raise ValueError(
@@ -205,7 +209,9 @@ def migrate_legacy_course_roles_to_authz(CourseAccessRole, course_id_list, org_i
205209
# otherwise we will filter by org_id which is more efficient
206210
course_access_role_filter["course_id__in"] = course_id_list
207211

208-
legacy_permissions = CourseAccessRole.objects.filter(**course_access_role_filter).select_related("user").all()
212+
legacy_permissions = (
213+
course_access_role_model.objects.filter(**course_access_role_filter).select_related("user").all()
214+
)
209215

210216
# List to keep track of any permissions that could not be migrated
211217
permissions_with_errors = []
@@ -246,19 +252,29 @@ def migrate_legacy_course_roles_to_authz(CourseAccessRole, course_id_list, org_i
246252

247253
if delete_after_migration:
248254
# Only delete permissions that were successfully migrated to avoid data loss.
249-
CourseAccessRole.objects.filter(id__in=[p.id for p in permissions_with_no_errors]).delete()
255+
course_access_role_model.objects.filter(id__in=[p.id for p in permissions_with_no_errors]).delete()
250256

251257
return permissions_with_errors, permissions_with_no_errors
252258

253259

254-
def migrate_authz_to_legacy_course_roles(CourseAccessRole, UserSubject, course_id_list, org_id, delete_after_migration):
260+
def migrate_authz_to_legacy_course_roles(
261+
course_access_role_model, user_subject_model, course_id_list, org_id, delete_after_migration
262+
):
255263
"""
256264
Migrate permissions from the new Casbin-based authorization model back to the legacy CourseAccessRole model.
257265
This function reads permissions from the Casbin enforcer and creates equivalent entries in the
258266
CourseAccessRole model.
259267
260268
This is essentially the reverse of migrate_legacy_course_roles_to_authz and is intended
261269
for rollback purposes in case of migration issues.
270+
271+
param course_access_role_model: The CourseAccessRole model to use. This is passed in because the function
272+
is intended to run within a Django migration context, where direct model imports can cause issues.
273+
param user_subject_model: The UserSubject model to query for users with course-related permissions.
274+
param course_id_list: Optional list of course IDs to filter the migration.
275+
param org_id: Optional organization ID to filter the migration.
276+
param delete_after_migration: Whether to unassign successfully migrated permissions
277+
from the new model after migration.
262278
"""
263279
if not course_id_list and not org_id:
264280
raise ValueError(
@@ -279,7 +295,7 @@ def migrate_authz_to_legacy_course_roles(CourseAccessRole, UserSubject, course_i
279295
# otherwise we will filter by org_id which is more efficient
280296
course_subject_filter["casbin_rules__scope__coursescope__course_overview__id__in"] = course_id_list
281297

282-
course_subjects = UserSubject.objects.filter(**course_subject_filter).select_related("user").distinct()
298+
course_subjects = user_subject_model.objects.filter(**course_subject_filter).select_related("user").distinct()
283299

284300
roles_with_errors = []
285301
roles_with_no_errors = []
@@ -309,7 +325,7 @@ def migrate_authz_to_legacy_course_roles(CourseAccessRole, UserSubject, course_i
309325

310326
try:
311327
# Create legacy CourseAccessRole entry
312-
CourseAccessRole.objects.get_or_create(
328+
course_access_role_model.objects.get_or_create(
313329
user=user,
314330
org=course_overview.org,
315331
course_id=scope,

openedx_authz/management/commands/authz_migrate_course_authoring.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def handle(self, *args, **options):
6464
return
6565
with transaction.atomic():
6666
errors, success = migrate_legacy_course_roles_to_authz(
67-
CourseAccessRole=CourseAccessRole,
67+
course_access_role_model=CourseAccessRole,
6868
course_id_list=course_id_list,
6969
org_id=org_id,
7070
delete_after_migration=delete_after_migration,

openedx_authz/management/commands/authz_rollback_course_authoring.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ def handle(self, *args, **options):
6767
return
6868
with transaction.atomic():
6969
errors, success = migrate_authz_to_legacy_course_roles(
70-
CourseAccessRole=CourseAccessRole,
71-
UserSubject=UserSubject,
70+
course_access_role_model=CourseAccessRole,
71+
user_subject_model=UserSubject,
7272
course_id_list=course_id_list,
7373
org_id=org_id,
7474
delete_after_migration=delete_after_migration, # control deletion here

0 commit comments

Comments
 (0)