a2_rbac: set admin role view permissions to role's OU users (#84706)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Serghei Mihai 2023-12-19 14:19:38 +01:00
parent dc5b825cd8
commit 4ba169c4c1
4 changed files with 70 additions and 19 deletions

View File

@ -20,7 +20,6 @@ import sys
class AppSettings:
__DEFAULTS = dict(
MANAGED_CONTENT_TYPES=None,
ROLE_ADMIN_RESTRICT_TO_OU_USERS=False,
)
def __init__(self, prefix):

View File

@ -0,0 +1,44 @@
# Generated by Django 3.2.18 on 2024-01-25 10:51
from django.db import migrations
def update_admin_roles_permissions(apps, schema_editor):
Operation = apps.get_model('a2_rbac', 'Operation')
try:
view_operation = Operation.objects.get(slug='view')
except Operation.DoesNotExist:
return
OrganizationalUnit = apps.get_model('a2_rbac', 'OrganizationalUnit')
Permission = apps.get_model('a2_rbac', 'Permission')
User = apps.get_model('custom_user', 'User')
ContentType = apps.get_model('contenttypes', 'ContentType')
target_ct = ContentType.objects.get_for_model(ContentType)
target_id = ContentType.objects.get_for_model(User).pk
user_view_permission_qs = Permission.objects.filter(
operation=view_operation, target_ct=target_ct, target_id=target_id
)
global_user_view_permission = user_view_permission_qs.get(ou__isnull=True)
for ou in OrganizationalUnit.objects.exclude(default=True):
try:
ou_user_view_permission = user_view_permission_qs.get(ou=ou)
except Permission.DoesNotExist:
continue
# admin roles start with _
for r in ou.role_set.filter(slug__startswith='_'):
if ou_user_view_permission not in r.permissions.all():
continue
r.permissions.remove(global_user_view_permission)
r.permissions.add(ou_user_view_permission)
class Migration(migrations.Migration):
dependencies = [
('a2_rbac', '0038_organizationalunit_phone_is_unique'),
]
operations = [
migrations.RunPython(update_admin_roles_permissions, reverse_code=migrations.RunPython.noop)
]

View File

@ -39,7 +39,7 @@ from authentic2.decorators import errorcollector
from authentic2.utils.cache import GlobalCache
from authentic2.validators import HexaColourValidator
from . import app_settings, fields, managers, utils
from . import fields, managers, utils
class AbstractBase(models.Model):
@ -448,11 +448,7 @@ class Role(AbstractBase):
def get_admin_role(self, create=True):
from . import utils
if app_settings.ROLE_ADMIN_RESTRICT_TO_OU_USERS:
view_user_perm = utils.get_view_user_perm(ou=self.ou)
else:
view_user_perm = utils.get_view_user_perm()
view_user_perm = utils.get_view_user_perm(ou=self.ou)
admin_role = self.__class__.objects.get_admin_role(
self,
name=_('Managers of role "{role}"').format(role=str(self)),

View File

@ -109,6 +109,22 @@ def test_admin_roles_update_slug(db):
assert admin_role3.slug == slug2
def test_role_view_user_perm_on_ou_update(db):
role = Role.objects.create(name='Admin')
admin_role = role.get_admin_role()
assert admin_role.permissions.get(operation__slug='view').ou is None
default_ou = get_default_ou()
role.ou = default_ou
role.save()
assert admin_role.permissions.get(operation__slug='view').ou == default_ou
new_ou = OU.objects.create(name='New OU')
role.ou = new_ou
role.save()
assert admin_role.permissions.get(operation__slug='view').ou == new_ou
def test_role_clean(db):
coin = Role(name='Coin')
coin.clean()
@ -392,24 +408,20 @@ def test_role_rename(db):
def test_admin_role_user_view(db, settings, app, admin, simple_user, ou1, user_ou1, role_ou1):
role_ou1.get_admin_role().members.add(simple_user)
# Default: all users are visible
# Default: only OU users are visible
response = login(app, simple_user, '/manage/roles/')
response = response.click('role_ou1')
select2_json = request_select2(app, response)
assert select2_json['more'] is False
user_ids = {int(x['id'].split('-')[1]) for x in select2_json['results'] if x['id'].startswith('user')}
assert user_ids == {simple_user.id, user_ou1.id, admin.id}
# with A2_RBAC_ROLE_ADMIN_RESTRICT_TO_OU_USERS after a reload of the admin
# page, we should only see user from the same OU as the role
settings.A2_RBAC_ROLE_ADMIN_RESTRICT_TO_OU_USERS = True
role_ou1.get_admin_role()
response = app.get('/manage/roles/')
response = response.click('role_ou1')
select2_json = request_select2(app, response)
assert select2_json['more'] is False
user_ids = {int(x['id'].split('-')[1]) for x in select2_json['results'] if x['id'].startswith('user')}
assert user_ids == {user_ou1.id}
# add user to OU
admin.ou = ou1
admin.save()
select2_json = request_select2(app, response)
user_ids = {int(x['id'].split('-')[1]) for x in select2_json['results'] if x['id'].startswith('user')}
# it must be visible
assert user_ids == {user_ou1.id, admin.id}
def test_no_managed_ct(transactional_db, settings):