a2_rbac: allow management of subclasses by manager roles (#77366) #54
|
@ -19,7 +19,7 @@ from django.utils.text import slugify
|
|||
from django.utils.translation import gettext
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit, Role
|
||||
from authentic2.a2_rbac.models import ADMIN_OP, OrganizationalUnit, Permission, Role
|
||||
from authentic2.utils.misc import get_fk_model
|
||||
|
||||
from . import app_settings, utils
|
||||
|
@ -94,6 +94,10 @@ MANAGED_CT = {
|
|||
('authenticators', 'baseauthenticator'): {
|
||||
'name': _('Manager of authenticators'),
|
||||
'scoped_name': _('Authenticators - {ou}'),
|
||||
'submanagement_cts': (
|
||||
('authenticators', 'addroleaction'),
|
||||
('authentic2_auth_oidc', 'oidcclaimmapping'),
|
||||
),
|
||||
},
|
||||
('authentic2', 'apiclient'): {
|
||||
'name': _('Manager of API clients'),
|
||||
|
@ -140,5 +144,15 @@ def update_content_types_roles():
|
|||
ct_admin_role.permissions.add(view_user_perm)
|
||||
if MANAGED_CT[ct_tuple].get('must_manage_authorizations_user'):
|
||||
ct_admin_role.permissions.add(manage_authorizations_user_perm)
|
||||
for subclass in MANAGED_CT[ct_tuple].get('submanagement_cts', ()):
|
||||
subct = ContentType.objects.get_by_natural_key(subclass[0], subclass[1])
|
||||
perm, dummy = Permission.objects.get_or_create(
|
||||
operation=utils.get_operation(ADMIN_OP),
|
||||
target_ct=ContentType.objects.get_for_model(ContentType),
|
||||
target_id=subct.pk,
|
||||
ou__isnull=True,
|
||||
ou=None,
|
||||
)
|
||||
ct_admin_role.permissions.add(perm)
|
||||
ct_admin_role.permissions.add(search_ou_perm)
|
||||
ct_admin_role.add_child(admin_role)
|
||||
|
|
|
@ -98,6 +98,10 @@ class BaseAuthenticator(models.Model):
|
|||
return '%s - %s' % (self._meta.verbose_name, self.name or self.slug)
|
||||
return str(self._meta.verbose_name)
|
||||
|
||||
@property
|
||||
def related_model_permissions(self):
|
||||
return {}
|
||||
|
||||
@property
|
||||
def manager_form_classes(self):
|
||||
return [(_('General'), self.manager_form_class)]
|
||||
|
|
|
@ -270,8 +270,6 @@ order = AuthenticatorsOrderView.as_view()
|
|||
|
||||
|
||||
class AuthenticatorRelatedObjectMixin(MediaMixin, TitleMixin, PermissionMixin):
|
||||
permissions = ['authenticators.search_baseauthenticator']
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.authenticator = get_object_or_404(
|
||||
BaseAuthenticator.authenticators.all(), pk=kwargs.get('authenticator_pk')
|
||||
|
@ -285,6 +283,10 @@ class AuthenticatorRelatedObjectMixin(MediaMixin, TitleMixin, PermissionMixin):
|
|||
except LookupError:
|
||||
self.model = apps.get_model('authenticators', model_name)
|
||||
|
||||
self.permissions = self.authenticator.related_model_permissions.get(self.model) or [
|
||||
'authenticators.search_baseauthenticator'
|
||||
]
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_class(self):
|
||||
|
|
|
@ -179,6 +179,13 @@ class OIDCProvider(BaseAuthenticator):
|
|||
AddRoleAction: self.add_role_actions.all(),
|
||||
}
|
||||
|
||||
@property
|
||||
def related_model_permissions(self):
|
||||
return {
|
||||
OIDCClaimMapping: ['authentic2_auth_oidc.admin_oidcclaimmapping'],
|
||||
AddRoleAction: ['authenticators.admin_addroleaction'],
|
||||
}
|
||||
|
||||
@property
|
||||
def jwkset(self):
|
||||
if self.jwkset_json:
|
||||
|
|
|
@ -221,6 +221,12 @@ class SAMLAuthenticator(BaseAuthenticator):
|
|||
AddRoleAction: self.add_role_actions.all(),
|
||||
}
|
||||
|
||||
@property
|
||||
def related_model_permissions(self):
|
||||
return {
|
||||
AddRoleAction: ['authenticators.admin_addroleaction'],
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
if not (self.metadata or self.metadata_url):
|
||||
raise ValidationError(_('One of the metadata fields must be filled.'))
|
||||
|
|
|
@ -37,7 +37,7 @@ def test_update_rbac(db):
|
|||
# and 1 user view permission (for the role administrator)
|
||||
# and 1 user manage authorizations permission (for the role administrator)
|
||||
# and 1 ou view permission (for the user and role administrators)
|
||||
assert Permission.objects.count() == 10
|
||||
assert Permission.objects.count() == 12
|
||||
|
||||
|
||||
def test_delete_role(db):
|
||||
|
|
|
@ -393,6 +393,29 @@ def test_authenticators_oidc_import_errors(app, superuser, simple_role):
|
|||
assert escape("Role not found: {'slug': 'xxx'}.") in resp.text
|
||||
|
||||
|
||||
def test_authenticators_oidc_related_objects_permissions(app, simple_user, simple_role):
|
||||
authenticator = OIDCProvider.objects.create(slug='idp1', order=42, ou=get_default_ou(), enabled=True)
|
||||
authenticator.save()
|
||||
mapping = OIDCClaimMapping.objects.create(authenticator=authenticator, claim='test', attribute='hop')
|
||||
action = AddRoleAction.objects.create(authenticator=authenticator, role=simple_role)
|
||||
simple_user.roles.add(simple_role.get_admin_role()) # grant user access to /manage/
|
||||
|
||||
role = Role.objects.get(name='Manager of authenticators')
|
||||
|
||||
login(app, simple_user, path='/')
|
||||
app.get(authenticator.get_absolute_url(), status=403)
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/oidcclaimmapping/{mapping.pk}/edit/', status=403)
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/addroleaction/{action.pk}/delete/', status=403)
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/addroleaction/add/', status=403)
|
||||
|
||||
simple_user.roles.add(role)
|
||||
|
||||
app.get(authenticator.get_absolute_url())
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/oidcclaimmapping/{mapping.pk}/edit/')
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/addroleaction/{action.pk}/delete/')
|
||||
app.get(f'/manage/authenticators/{authenticator.pk}/addroleaction/add/')
|
||||
|
||||
|
||||
def test_authenticators_fc(app, superuser):
|
||||
resp = login(app, superuser, path='/manage/authenticators/')
|
||||
|
||||
|
|
Loading…
Reference in New Issue