@@ -901,6 +901,39 @@ def test_migrate_legacy_course_roles_to_authz_using_org_id(self):
901901 # After rollback, we should have 0 UserSubjects related to the course permissions
902902 self .assertEqual (len (state_after_migration_user_subjects ), 0 )
903903
904+ @patch ("openedx_authz.api.data.CourseOverview" , CourseOverview )
905+ def test_migrate_legacy_course_roles_to_authz_skips_excluded_course_ids (self ):
906+ """Org-scoped migration skips course-level rows whose course_id is in excluded_course_ids."""
907+ errors , successes = migrate_legacy_course_roles_to_authz (
908+ CourseAccessRole ,
909+ course_id_list = None ,
910+ org_id = self .org ,
911+ delete_after_migration = False ,
912+ excluded_course_ids = frozenset ({self .course_id }),
913+ )
914+
915+ self .assertEqual (len (successes ), 0 )
916+ self .assertEqual (len (errors ), 13 )
917+
918+ skipped = [entry for entry in errors if entry .reason == MigrationErrorReason .SKIPPED_FOR_FLAG_OVERRIDE ]
919+ self .assertEqual (len (skipped ), 12 )
920+ for entry in skipped :
921+ self .assertEqual (entry .scope , self .course_id )
922+ self .assertEqual (
923+ entry .details ,
924+ "Course-level authoring flag override opposes this organization-level transition" ,
925+ )
926+
927+ unknown_role = [entry for entry in errors if entry .reason == MigrationErrorReason .UNKNOWN_ROLE ]
928+ self .assertEqual (len (unknown_role ), 1 )
929+ self .assertEqual (unknown_role [0 ].subject , self .error_user .username )
930+
931+ for user in self .admin_users :
932+ assignments = get_user_role_assignments_in_scope (
933+ user_external_key = user .username , scope_external_key = self .course_id
934+ )
935+ self .assertEqual (len (assignments ), 0 )
936+
904937 @patch ("openedx_authz.api.data.CourseOverview" , CourseOverview )
905938 def test_migrate_authz_to_legacy_course_roles_with_no_org_and_courses (self ):
906939 # Migrate from legacy CourseAccessRole to new Casbin-based model
@@ -1249,6 +1282,35 @@ def test_migrate_authz_to_legacy_course_roles_user_not_added(self):
12491282 self .assertEqual (len (errors ), 12 )
12501283 self .assertEqual (len (successes ), 0 )
12511284
1285+ @patch ("openedx_authz.api.data.CourseOverview" , CourseOverview )
1286+ def test_migrate_authz_to_legacy_course_roles_skips_excluded_course_ids (self ):
1287+ """Course-level assignments whose scope is listed in excluded_course_ids are skipped."""
1288+ migrate_legacy_course_roles_to_authz (
1289+ CourseAccessRole ,
1290+ course_id_list = [self .course_id ],
1291+ org_id = None ,
1292+ delete_after_migration = False ,
1293+ )
1294+
1295+ errors , successes = migrate_authz_to_legacy_course_roles (
1296+ CourseAccessRole ,
1297+ UserSubject ,
1298+ course_id_list = [self .course_id ],
1299+ org_id = None ,
1300+ delete_after_migration = False ,
1301+ excluded_course_ids = frozenset ({self .course_id }),
1302+ )
1303+
1304+ self .assertEqual (len (successes ), 0 )
1305+ self .assertEqual (len (errors ), 12 )
1306+ for entry in errors :
1307+ self .assertEqual (entry .reason , MigrationErrorReason .SKIPPED_FOR_FLAG_OVERRIDE )
1308+ self .assertEqual (
1309+ entry .details ,
1310+ "Course-level authoring flag override opposes this organization-level transition" ,
1311+ )
1312+ self .assertEqual (entry .scope , self .course_id )
1313+
12521314 def create_library_env (self ):
12531315 """
12541316 Helper method to create a ContentLibrary environment for testing.
0 commit comments