a2_rbac: set existing role-admin roles' adequate permissions (#75205)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Paul Marillonnet 2024-02-20 14:52:26 +01:00
parent 87b0e1dd26
commit 34ad5a3cb7
2 changed files with 150 additions and 0 deletions

View File

@ -0,0 +1,64 @@
from django.db import migrations
def update_admin_roles_permissions(apps, schema_editor):
ContentType = apps.get_model('contenttypes', 'ContentType')
OrganizationalUnit = apps.get_model('a2_rbac', 'OrganizationalUnit')
Operation = apps.get_model('a2_rbac', 'Operation')
Role = apps.get_model('a2_rbac', 'Role')
Permission = apps.get_model('a2_rbac', 'Permission')
User = apps.get_model('custom_user', 'User')
view_operation, _ = Operation.objects.get_or_create(slug='view')
search_operation, _ = Operation.objects.get_or_create(slug='search')
target_ct = ContentType.objects.get_for_model(Role)
def all_ous_iterator():
yield from OrganizationalUnit.objects.all()
yield None # global administration not restrained to any OU
for ou in all_ous_iterator():
try:
view_user_perm = Permission.objects.get(
operation=view_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=ou is None,
ou=ou,
)
except Permission.DoesNotExist:
# The permission does not exist, implying that role administration roles have
# not been created in this OU yet, no migration needed.
continue
search_user_perm, _ = Permission.objects.get_or_create(
operation=search_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=ou is None,
ou=ou,
)
view_user_perm_roles = [role.id for role in view_user_perm.roles.all()]
search_user_perm_roles = [role.id for role in search_user_perm.roles.all()]
roles_qs = (
Role.objects.prefetch_related('permissions')
.filter(admin_scope_ct=target_ct, admin_scope_id__isnull=False, id__in=view_user_perm_roles)
.exclude(id__in=search_user_perm_roles)
)
for role in roles_qs:
role.permissions.remove(view_user_perm)
role.permissions.add(search_user_perm)
role.save()
class Migration(migrations.Migration):
dependencies = [
('a2_rbac', '0039_set_user_view_permissions_by_ou'),
]
operations = [
migrations.RunPython(update_admin_roles_permissions, reverse_code=migrations.RunPython.noop)
]

View File

@ -822,3 +822,89 @@ def test_a2_rbac_role_attribute_migration(migration, settings):
assert role.emails == []
assert role.emails_to_members is True
assert role.is_superuser is False
def test_a2_rbac_0040_migration_update_admin_roles_permission(migration, settings):
migrate_from = [('a2_rbac', '0039_set_user_view_permissions_by_ou')]
migrate_to = [('a2_rbac', '0040_update_role_administration_permissions')]
old_apps = migration.before(migrate_from)
ContentType = old_apps.get_model('contenttypes', 'ContentType')
Operation = old_apps.get_model('a2_rbac', 'Operation')
OrganizationalUnit = old_apps.get_model('a2_rbac', 'OrganizationalUnit')
Permission = old_apps.get_model('a2_rbac', 'Permission')
Role = old_apps.get_model('a2_rbac', 'Role')
User = old_apps.get_model('custom_user', 'User')
watched_roles = []
view_operation, _ = Operation.objects.get_or_create(slug='view')
role = Role.objects.create(slug='main-role', ou=None)
view_user_perm, _ = Permission.objects.get_or_create(
operation=view_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=True,
ou=None,
)
admin_role = Role.objects.create(
admin_scope_ct=ContentType.objects.get_for_model(Role),
admin_scope_id=role.id,
ou=None,
slug=f'admin-role-{role.slug}',
)
admin_role.permissions.add(view_user_perm)
admin_role.save()
watched_roles.append(admin_role.id)
for i in range(4):
ou = OrganizationalUnit.objects.create(slug=f'ou-{i}', name=f'OU {i}')
role = Role.objects.create(slug=f'role-{i}', name=f'Role {i}', ou=ou)
view_user_perm, _ = Permission.objects.get_or_create(
operation=view_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=ou is None,
ou=ou,
)
admin_role = Role.objects.create(
admin_scope_ct=ContentType.objects.get_for_model(Role),
admin_scope_id=role.id,
ou=role.ou,
slug=f'admin-role-{role.slug}',
)
admin_role.permissions.add(view_user_perm)
admin_role.save()
watched_roles.append(admin_role.id)
new_apps = migration.apply(migrate_to)
ContentType = new_apps.get_model('contenttypes', 'ContentType')
Operation = new_apps.get_model('a2_rbac', 'Operation')
Permission = new_apps.get_model('a2_rbac', 'Permission')
Role = new_apps.get_model('a2_rbac', 'Role')
User = new_apps.get_model('custom_user', 'User')
view_operation, _ = Operation.objects.get_or_create(slug='view')
search_operation, _ = Operation.objects.get_or_create(slug='search')
for role in Role.objects.filter(id__in=watched_roles):
view_user_perm, _ = Permission.objects.get_or_create(
operation=view_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=role.ou is None,
ou=role.ou,
)
search_user_perm, _ = Permission.objects.get_or_create(
operation=search_operation,
target_ct=ContentType.objects.get_for_model(ContentType),
target_id=ContentType.objects.get_for_model(User).pk,
ou__isnull=role.ou is None,
ou=role.ou,
)
assert role not in view_user_perm.roles.all()
assert role in search_user_perm.roles.all()