authentik.core.migrations.0056_user_roles
1# Generated by Django 5.1.12 on 2025-09-30 12:29 2 3from django.db import migrations, models 4 5from django.apps.registry import Apps 6from django.db.backends.base.schema import BaseDatabaseSchemaEditor 7 8 9def migrate_object_permissions(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): 10 db_alias = schema_editor.connection.alias 11 12 User = apps.get_model("authentik_core", "User") 13 Group = apps.get_model("auth", "Group") 14 Role = apps.get_model("authentik_rbac", "Role") 15 UserObjectPermission = apps.get_model("guardian", "UserObjectPermission") 16 GroupObjectPermission = apps.get_model("guardian", "GroupObjectPermission") 17 RoleObjectPermission = apps.get_model("guardian", "RoleObjectPermission") 18 RoleModelPermission = apps.get_model("guardian", "RoleModelPermission") 19 20 def get_role_for_user_id(user_id: int) -> Role: 21 name = f"ak-migrated-role--user-{user_id}" 22 role, created = Role.objects.using(db_alias).get_or_create( 23 name=name, 24 ) 25 if created: 26 role.users.add(user_id) 27 return role 28 29 def get_role_for_group_id(group_id: int) -> Role: 30 role = Role.objects.using(db_alias).filter(group_id=group_id).first() 31 if not role: 32 # Every django group should already have a role, so this should never happen. 33 # But let's be nice. 34 name = f"ak-migrated-role--group-{group_id}" 35 role, created = Role.objects.using(db_alias).get_or_create( 36 group_id=group_id, 37 name=name, 38 ) 39 if created: 40 role.group_id = group_id 41 role.save() 42 return role 43 44 # Below are 4 very similar pieces of code, for (user, group) x (model, object). 45 # Since this is a one-off migration, I won't attempt DRYing them. 46 47 # User model permissions 48 user_ids_with_model_permissions = ( 49 User.user_permissions.through.objects.using(db_alias) 50 .values_list("user", flat=True) 51 .distinct() 52 ) 53 for user_id in user_ids_with_model_permissions: 54 role = get_role_for_user_id(user_id) 55 user_model_permissions = User.user_permissions.through.objects.using(db_alias).filter( 56 user_id=user_id 57 ) 58 59 role_model_permissions = [] 60 for user_model_permission in user_model_permissions: 61 role_model_permissions.append( 62 RoleModelPermission( 63 permission=user_model_permission.permission, 64 content_type=user_model_permission.permission.content_type, 65 role=role, 66 ) 67 ) 68 69 RoleModelPermission.objects.using(db_alias).bulk_create(role_model_permissions) 70 71 # Group model permissions 72 group_ids_with_model_permissions = ( 73 Group.permissions.through.objects.using(db_alias).values_list("group", flat=True).distinct() 74 ) 75 for group_id in group_ids_with_model_permissions: 76 role = get_role_for_group_id(group_id) 77 group_model_permissions = Group.permissions.through.objects.using(db_alias).filter( 78 group_id=group_id 79 ) 80 81 role_model_permissions = [] 82 for group_model_permission in group_model_permissions: 83 role_model_permissions.append( 84 RoleModelPermission( 85 permission=group_model_permission.permission, 86 content_type=group_model_permission.permission.content_type, 87 role=role, 88 ) 89 ) 90 91 RoleModelPermission.objects.using(db_alias).bulk_create(role_model_permissions) 92 93 # User object permissions 94 user_ids_with_object_permissions = ( 95 UserObjectPermission.objects.using(db_alias).values_list("user", flat=True).distinct() 96 ) 97 for user_id in user_ids_with_object_permissions: 98 role = get_role_for_user_id(user_id) 99 user_object_permissions = UserObjectPermission.objects.using(db_alias).filter(user=user_id) 100 101 role_object_permissions = [] 102 for user_object_permission in user_object_permissions: 103 role_object_permissions.append( 104 RoleObjectPermission( 105 permission=user_object_permission.permission, 106 content_type=user_object_permission.content_type, 107 object_pk=user_object_permission.object_pk, 108 role=role, 109 ) 110 ) 111 112 RoleObjectPermission.objects.using(db_alias).bulk_create(role_object_permissions) 113 114 # Group object permissions 115 group_ids_with_object_permissions = ( 116 GroupObjectPermission.objects.using(db_alias).values_list("group", flat=True).distinct() 117 ) 118 for group_id in group_ids_with_object_permissions: 119 role = get_role_for_group_id(group_id) 120 group_object_permissions = GroupObjectPermission.objects.using(db_alias).filter( 121 group=group_id 122 ) 123 124 role_object_permissions = [] 125 for group_object_permission in group_object_permissions: 126 role_object_permissions.append( 127 RoleObjectPermission( 128 permission=group_object_permission.permission, 129 content_type=group_object_permission.content_type, 130 object_pk=group_object_permission.object_pk, 131 role=role, 132 ) 133 ) 134 135 RoleObjectPermission.objects.using(db_alias).bulk_create(role_object_permissions) 136 137 138class Migration(migrations.Migration): 139 140 dependencies = [ 141 ("guardian", "0004_role_permissions"), 142 ("authentik_core", "0055_groupancestor_groupparentagenode_group_parents"), 143 ("authentik_rbac", "0008_alter_role_group"), 144 ] 145 146 operations = [ 147 migrations.AddField( 148 model_name="user", 149 name="roles", 150 field=models.ManyToManyField( 151 blank=True, related_name="users", to="authentik_rbac.role" 152 ), 153 ), 154 migrations.RunPython(migrate_object_permissions), 155 migrations.AlterUniqueTogether( 156 name="group", 157 unique_together=set(), 158 ), 159 migrations.AlterField( 160 model_name="group", 161 name="parents", 162 field=models.ManyToManyField( 163 blank=True, 164 related_name="children", 165 through="authentik_core.GroupParentageNode", 166 to="authentik_core.group", 167 ), 168 ), 169 migrations.RemoveField( 170 model_name="group", 171 name="parent", 172 ), 173 migrations.AlterField( 174 model_name="group", 175 name="name", 176 field=models.TextField(unique=True, verbose_name="name"), 177 ), 178 ]
def
migrate_object_permissions( apps: django.apps.registry.Apps, schema_editor: django.db.backends.base.schema.BaseDatabaseSchemaEditor):
10def migrate_object_permissions(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): 11 db_alias = schema_editor.connection.alias 12 13 User = apps.get_model("authentik_core", "User") 14 Group = apps.get_model("auth", "Group") 15 Role = apps.get_model("authentik_rbac", "Role") 16 UserObjectPermission = apps.get_model("guardian", "UserObjectPermission") 17 GroupObjectPermission = apps.get_model("guardian", "GroupObjectPermission") 18 RoleObjectPermission = apps.get_model("guardian", "RoleObjectPermission") 19 RoleModelPermission = apps.get_model("guardian", "RoleModelPermission") 20 21 def get_role_for_user_id(user_id: int) -> Role: 22 name = f"ak-migrated-role--user-{user_id}" 23 role, created = Role.objects.using(db_alias).get_or_create( 24 name=name, 25 ) 26 if created: 27 role.users.add(user_id) 28 return role 29 30 def get_role_for_group_id(group_id: int) -> Role: 31 role = Role.objects.using(db_alias).filter(group_id=group_id).first() 32 if not role: 33 # Every django group should already have a role, so this should never happen. 34 # But let's be nice. 35 name = f"ak-migrated-role--group-{group_id}" 36 role, created = Role.objects.using(db_alias).get_or_create( 37 group_id=group_id, 38 name=name, 39 ) 40 if created: 41 role.group_id = group_id 42 role.save() 43 return role 44 45 # Below are 4 very similar pieces of code, for (user, group) x (model, object). 46 # Since this is a one-off migration, I won't attempt DRYing them. 47 48 # User model permissions 49 user_ids_with_model_permissions = ( 50 User.user_permissions.through.objects.using(db_alias) 51 .values_list("user", flat=True) 52 .distinct() 53 ) 54 for user_id in user_ids_with_model_permissions: 55 role = get_role_for_user_id(user_id) 56 user_model_permissions = User.user_permissions.through.objects.using(db_alias).filter( 57 user_id=user_id 58 ) 59 60 role_model_permissions = [] 61 for user_model_permission in user_model_permissions: 62 role_model_permissions.append( 63 RoleModelPermission( 64 permission=user_model_permission.permission, 65 content_type=user_model_permission.permission.content_type, 66 role=role, 67 ) 68 ) 69 70 RoleModelPermission.objects.using(db_alias).bulk_create(role_model_permissions) 71 72 # Group model permissions 73 group_ids_with_model_permissions = ( 74 Group.permissions.through.objects.using(db_alias).values_list("group", flat=True).distinct() 75 ) 76 for group_id in group_ids_with_model_permissions: 77 role = get_role_for_group_id(group_id) 78 group_model_permissions = Group.permissions.through.objects.using(db_alias).filter( 79 group_id=group_id 80 ) 81 82 role_model_permissions = [] 83 for group_model_permission in group_model_permissions: 84 role_model_permissions.append( 85 RoleModelPermission( 86 permission=group_model_permission.permission, 87 content_type=group_model_permission.permission.content_type, 88 role=role, 89 ) 90 ) 91 92 RoleModelPermission.objects.using(db_alias).bulk_create(role_model_permissions) 93 94 # User object permissions 95 user_ids_with_object_permissions = ( 96 UserObjectPermission.objects.using(db_alias).values_list("user", flat=True).distinct() 97 ) 98 for user_id in user_ids_with_object_permissions: 99 role = get_role_for_user_id(user_id) 100 user_object_permissions = UserObjectPermission.objects.using(db_alias).filter(user=user_id) 101 102 role_object_permissions = [] 103 for user_object_permission in user_object_permissions: 104 role_object_permissions.append( 105 RoleObjectPermission( 106 permission=user_object_permission.permission, 107 content_type=user_object_permission.content_type, 108 object_pk=user_object_permission.object_pk, 109 role=role, 110 ) 111 ) 112 113 RoleObjectPermission.objects.using(db_alias).bulk_create(role_object_permissions) 114 115 # Group object permissions 116 group_ids_with_object_permissions = ( 117 GroupObjectPermission.objects.using(db_alias).values_list("group", flat=True).distinct() 118 ) 119 for group_id in group_ids_with_object_permissions: 120 role = get_role_for_group_id(group_id) 121 group_object_permissions = GroupObjectPermission.objects.using(db_alias).filter( 122 group=group_id 123 ) 124 125 role_object_permissions = [] 126 for group_object_permission in group_object_permissions: 127 role_object_permissions.append( 128 RoleObjectPermission( 129 permission=group_object_permission.permission, 130 content_type=group_object_permission.content_type, 131 object_pk=group_object_permission.object_pk, 132 role=role, 133 ) 134 ) 135 136 RoleObjectPermission.objects.using(db_alias).bulk_create(role_object_permissions)
class
Migration(django.db.migrations.migration.Migration):
139class Migration(migrations.Migration): 140 141 dependencies = [ 142 ("guardian", "0004_role_permissions"), 143 ("authentik_core", "0055_groupancestor_groupparentagenode_group_parents"), 144 ("authentik_rbac", "0008_alter_role_group"), 145 ] 146 147 operations = [ 148 migrations.AddField( 149 model_name="user", 150 name="roles", 151 field=models.ManyToManyField( 152 blank=True, related_name="users", to="authentik_rbac.role" 153 ), 154 ), 155 migrations.RunPython(migrate_object_permissions), 156 migrations.AlterUniqueTogether( 157 name="group", 158 unique_together=set(), 159 ), 160 migrations.AlterField( 161 model_name="group", 162 name="parents", 163 field=models.ManyToManyField( 164 blank=True, 165 related_name="children", 166 through="authentik_core.GroupParentageNode", 167 to="authentik_core.group", 168 ), 169 ), 170 migrations.RemoveField( 171 model_name="group", 172 name="parent", 173 ), 174 migrations.AlterField( 175 model_name="group", 176 name="name", 177 field=models.TextField(unique=True, verbose_name="name"), 178 ), 179 ]
The base class for all migrations.
Migration files will import this from django.db.migrations.Migration and subclass it as a class called Migration. It will have one or more of the following attributes:
- operations: A list of Operation instances, probably from django.db.migrations.operations
- dependencies: A list of tuples of (app_path, migration_name)
- run_before: A list of tuples of (app_path, migration_name)
- replaces: A list of migration_names
Note that all migrations come out of migrations and into the Loader or Graph as instances, having been initialized with their app label and name.
dependencies =
[('guardian', '0004_role_permissions'), ('authentik_core', '0055_groupancestor_groupparentagenode_group_parents'), ('authentik_rbac', '0008_alter_role_group')]
operations =
[<AddField model_name='user', name='roles', field=<django.db.models.fields.related.ManyToManyField>>, <RunPython <function migrate_object_permissions>>, <AlterUniqueTogether name='group', unique_together=set()>, <AlterField model_name='group', name='parents', field=<django.db.models.fields.related.ManyToManyField>>, <RemoveField model_name='group', name='parent'>, <AlterField model_name='group', name='name', field=<django.db.models.fields.TextField>>]