auth_saml: add views to configure related objects (#67025)
This commit is contained in:
parent
18ea92a76b
commit
742e955dcc
|
@ -75,6 +75,7 @@ class BaseAuthenticator(models.Model):
|
|||
|
||||
type = ''
|
||||
manager_form_class = None
|
||||
manager_view_template_name = 'authentic2/authenticators/authenticator_detail.html'
|
||||
unique = False
|
||||
protected = False
|
||||
description_fields = ['show_condition']
|
||||
|
|
|
@ -31,9 +31,25 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class='placeholder'>
|
||||
{% for line in object.get_full_description %}
|
||||
<p>{{ line }}</p>
|
||||
{% endfor %}
|
||||
<div class='section authenticator-detail'>
|
||||
<div class='pk-tabs'>
|
||||
<div class="pk-tabs--tab-list" role="tablist">
|
||||
<button aria-controls="panel-description" aria-selected="true" id="tab-description" role="tab" tabindex="0">{% trans "Description" %}</button>
|
||||
{% block extra-tab-buttons %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="pk-tabs--container">
|
||||
<div aria-labelledby="tab-description" id="panel-description" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
{% for line in object.get_full_description %}
|
||||
<li>{{ line }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% block extra-tab-list %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -64,7 +64,8 @@ add = AuthenticatorAddView.as_view()
|
|||
|
||||
|
||||
class AuthenticatorDetailView(AuthenticatorsMixin, DetailView):
|
||||
template_name = 'authentic2/authenticators/authenticator_detail.html'
|
||||
def get_template_names(self):
|
||||
return self.object.manager_view_template_name
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
from django import forms
|
||||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
from authentic2.manager.utils import label_from_role
|
||||
|
||||
from .models import SAMLAuthenticator
|
||||
|
||||
|
||||
|
@ -23,3 +26,12 @@ class SAMLAuthenticatorForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = SAMLAuthenticator
|
||||
exclude = ('ou',)
|
||||
|
||||
|
||||
class RoleChoiceField(forms.ModelChoiceField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.queryset = Role.objects.exclude(slug__startswith='_')
|
||||
|
||||
def label_from_instance(self, obj):
|
||||
return label_from_role(obj)
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2022 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from authentic2.apps.journal.models import EventTypeDefinition
|
||||
from authentic2.apps.journal.utils import form_to_old_new
|
||||
|
||||
from .models import SAMLAuthenticator
|
||||
|
||||
|
||||
class SAMLAuthenticatorEvents(EventTypeDefinition):
|
||||
@classmethod
|
||||
def record(cls, *, user, session, related_object, data=None):
|
||||
data = data or {}
|
||||
data.update({'related_object': repr(related_object)})
|
||||
super().record(user=user, session=session, references=[related_object.authenticator], data=data)
|
||||
|
||||
|
||||
class SAMLAuthenticatorRelatedObjectCreation(SAMLAuthenticatorEvents):
|
||||
name = 'authenticator.saml.related_object.creation'
|
||||
label = _('SAML authenticator related object creation')
|
||||
|
||||
@classmethod
|
||||
def get_message(cls, event, context):
|
||||
(authenticator,) = event.get_typed_references(SAMLAuthenticator)
|
||||
related_object = event.get_data('related_object')
|
||||
if context != authenticator:
|
||||
return _('creation of {related_object} in authenticator "{authenticator}"').format(
|
||||
related_object=related_object, authenticator=authenticator
|
||||
)
|
||||
else:
|
||||
return _('creation of %s') % related_object
|
||||
|
||||
|
||||
class SAMLAuthenticatorRelatedObjectEdit(SAMLAuthenticatorEvents):
|
||||
name = 'authenticator.saml.related_object.edit'
|
||||
label = _('SAML authenticator related object edit')
|
||||
|
||||
@classmethod
|
||||
def record(cls, *, user, session, form):
|
||||
super().record(
|
||||
user=user,
|
||||
session=session,
|
||||
related_object=form.instance,
|
||||
data=form_to_old_new(form),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_message(cls, event, context):
|
||||
(authenticator,) = event.get_typed_references(SAMLAuthenticator)
|
||||
related_object = event.get_data('related_object')
|
||||
new = event.get_data('new') or {}
|
||||
edited_attributes = ', '.join(new) or ''
|
||||
if context != authenticator:
|
||||
return _('edit {related_object} in authenticator "{authenticator}" ({change})').format(
|
||||
related_object=related_object,
|
||||
authenticator=authenticator,
|
||||
change=edited_attributes,
|
||||
)
|
||||
else:
|
||||
return _('edit {related_object} ({change})').format(
|
||||
related_object=related_object, change=edited_attributes
|
||||
)
|
||||
|
||||
|
||||
class SAMLAuthenticatorRelatedObjectDeletion(SAMLAuthenticatorEvents):
|
||||
name = 'authenticator.saml.related_object.deletion'
|
||||
label = _('SAML authenticator related object deletion')
|
||||
|
||||
@classmethod
|
||||
def get_message(cls, event, context):
|
||||
(authenticator,) = event.get_typed_references(SAMLAuthenticator)
|
||||
related_object = event.get_data('related_object')
|
||||
if context != authenticator:
|
||||
return _('deletion of {related_object} in authenticator "{authenticator}"').format(
|
||||
related_object=related_object, authenticator=authenticator
|
||||
)
|
||||
else:
|
||||
return _('deletion of %s') % related_object
|
|
@ -21,10 +21,9 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from authentic2.a2_rbac.models import Role
|
||||
from authentic2.apps.authenticators.models import BaseAuthenticator
|
||||
from authentic2.manager.utils import label_from_role
|
||||
from authentic2.utils.misc import redirect_to_login
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
class SAMLAuthenticator(BaseAuthenticator):
|
||||
metadata_url = models.URLField(_('Metadata URL'), max_length=300, blank=True)
|
||||
|
@ -144,6 +143,7 @@ class SAMLAuthenticator(BaseAuthenticator):
|
|||
|
||||
type = 'saml'
|
||||
how = ['saml']
|
||||
manager_view_template_name = 'authentic2_auth_saml/authenticator_detail.html'
|
||||
description_fields = [
|
||||
'show_condition',
|
||||
'metadata_url',
|
||||
|
@ -191,9 +191,13 @@ class SAMLAuthenticator(BaseAuthenticator):
|
|||
)
|
||||
|
||||
def login(self, request, *args, **kwargs):
|
||||
from . import views
|
||||
|
||||
return views.login(request, self, *args, **kwargs)
|
||||
|
||||
def profile(self, request, *args, **kwargs):
|
||||
from . import views
|
||||
|
||||
return views.profile(request, *args, **kwargs)
|
||||
|
||||
|
||||
|
@ -215,6 +219,9 @@ class RenameAttributeAction(SAMLRelatedObjectBase):
|
|||
default_related_name = 'rename_attribute_actions'
|
||||
verbose_name = _('Rename an attribute')
|
||||
|
||||
def __str__(self):
|
||||
return '%s → %s' % (self.from_name, self.to_name)
|
||||
|
||||
|
||||
class SAMLAttributeLookup(SAMLRelatedObjectBase):
|
||||
user_field = models.CharField(_('User field'), max_length=256)
|
||||
|
@ -225,6 +232,15 @@ class SAMLAttributeLookup(SAMLRelatedObjectBase):
|
|||
default_related_name = 'attribute_lookups'
|
||||
verbose_name = _('Attribute lookup')
|
||||
|
||||
def __str__(self):
|
||||
label = _('"%(saml_attribute)s" (from "%(user_field)s")') % {
|
||||
'saml_attribute': self.saml_attribute,
|
||||
'user_field': self.user_field,
|
||||
}
|
||||
if self.ignore_case:
|
||||
label = '%s, %s' % (label, _('case insensitive'))
|
||||
return label
|
||||
|
||||
def as_dict(self):
|
||||
return {
|
||||
'user_field': self.user_field,
|
||||
|
@ -242,6 +258,15 @@ class SetAttributeAction(SAMLRelatedObjectBase):
|
|||
default_related_name = 'set_attribute_actions'
|
||||
verbose_name = _('Set an attribute')
|
||||
|
||||
def __str__(self):
|
||||
label = _('"%(attribute)s" from "%(saml_attribute)s"') % {
|
||||
'attribute': self.attribute,
|
||||
'saml_attribute': self.saml_attribute,
|
||||
}
|
||||
if self.mandatory:
|
||||
label = '%s (%s)' % (label, _('mandatory'))
|
||||
return label
|
||||
|
||||
|
||||
class AddRoleAction(SAMLRelatedObjectBase):
|
||||
role = models.ForeignKey(Role, verbose_name=_('Role'), on_delete=models.CASCADE)
|
||||
|
@ -251,3 +276,6 @@ class AddRoleAction(SAMLRelatedObjectBase):
|
|||
class Meta:
|
||||
default_related_name = 'add_role_actions'
|
||||
verbose_name = _('Add a role')
|
||||
|
||||
def __str__(self):
|
||||
return label_from_role(self.role)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
{% extends 'authentic2/authenticators/authenticator_detail.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block extra-tab-buttons %}
|
||||
<button aria-controls="panel-samlattributelookup" aria-selected="false" id="tab-samlattributelookup" role="tab" tabindex="-1">{% trans "Lookup by attributes" %}</button>
|
||||
<button aria-controls="panel-renameattributeaction" aria-selected="false" id="tab-renameattributeaction" role="tab" tabindex="-1">{% trans "Rename attributes" %}</button>
|
||||
<button aria-controls="panel-setattributeaction" aria-selected="false" id="tab-setattributeaction" role="tab" tabindex="-1">{% trans "Set attributes" %}</button>
|
||||
<button aria-controls="panel-addroleaction" aria-selected="false" id="tab-addroleaction" role="tab" tabindex="-1">{% trans "Add roles" %}</button>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra-tab-list %}
|
||||
<div aria-labelledby="tab-samlattributelookup" hidden="" id="panel-samlattributelookup" role="tabpanel" tabindex="0">
|
||||
{% include 'authentic2_auth_saml/related_object_list.html' with object_list=object.attribute_lookups.all model_name='samlattributelookup' %}
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-renameattributeaction" hidden="" id="panel-renameattributeaction" role="tabpanel" tabindex="0">
|
||||
{% include 'authentic2_auth_saml/related_object_list.html' with object_list=object.rename_attribute_actions.all model_name='renameattributeaction' %}
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-setattributeaction" hidden="" id="panel-setattributeaction" role="tabpanel" tabindex="0">
|
||||
{% include 'authentic2_auth_saml/related_object_list.html' with object_list=object.set_attribute_actions.all model_name='setattributeaction' %}
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-addroleaction" hidden="" id="panel-addroleaction" role="tabpanel" tabindex="0">
|
||||
{% include 'authentic2_auth_saml/related_object_list.html' with object_list=object.add_role_actions.all model_name='addroleaction' %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
{% load i18n %}
|
||||
|
||||
<ul class="objects-list single-links">
|
||||
{% for related_object in object_list %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'a2-manager-saml-edit-related-object' authenticator_pk=object.pk model_name=model_name pk=related_object.pk %}">{{ related_object }}</a>
|
||||
<a rel="popup" class="delete" href="{% url 'a2-manager-saml-delete-related-object' authenticator_pk=object.pk model_name=model_name pk=related_object.pk %}">{% trans "Remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li><a class="add" rel="popup" href="{% url 'a2-manager-saml-add-related-object' authenticator_pk=object.pk model_name=model_name %}">{% trans 'Add' %}</a></li>
|
||||
</ul>
|
|
@ -15,7 +15,34 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import include, url
|
||||
from django.urls import path
|
||||
|
||||
from authentic2.apps.authenticators.manager_urls import superuser_login_required
|
||||
from authentic2.decorators import required
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^accounts/saml/', include('mellon.urls'), kwargs={'template_base': 'authentic2/base.html'})
|
||||
]
|
||||
|
||||
urlpatterns += required(
|
||||
superuser_login_required,
|
||||
[
|
||||
path(
|
||||
'authenticators/<int:authenticator_pk>/<slug:model_name>/add/',
|
||||
views.add_related_object,
|
||||
name='a2-manager-saml-add-related-object',
|
||||
),
|
||||
path(
|
||||
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/edit/',
|
||||
views.edit_related_object,
|
||||
name='a2-manager-saml-edit-related-object',
|
||||
),
|
||||
path(
|
||||
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/delete/',
|
||||
views.delete_related_object,
|
||||
name='a2-manager-saml-delete-related-object',
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
from django.shortcuts import render
|
||||
from django.apps import apps
|
||||
from django.forms.models import modelform_factory
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.views.generic import CreateView, DeleteView, UpdateView
|
||||
from mellon.utils import get_idp
|
||||
|
||||
from authentic2.manager.views import MediaMixin, TitleMixin
|
||||
from authentic2.utils.misc import redirect_to_login
|
||||
|
||||
from .forms import RoleChoiceField
|
||||
from .models import (
|
||||
AddRoleAction,
|
||||
RenameAttributeAction,
|
||||
SAMLAttributeLookup,
|
||||
SAMLAuthenticator,
|
||||
SetAttributeAction,
|
||||
)
|
||||
|
||||
|
||||
def login(request, authenticator, *args, **kwargs):
|
||||
context = kwargs.pop('context', {}).copy()
|
||||
|
@ -34,3 +49,79 @@ def profile(request, *args, **kwargs):
|
|||
user_saml_identifier.idp = get_idp(user_saml_identifier.issuer.entity_id)
|
||||
context['user_saml_identifiers'] = user_saml_identifiers
|
||||
return render_to_string('authentic2_auth_saml/profile.html', context, request=request)
|
||||
|
||||
|
||||
class SAMLAuthenticatorMixin(MediaMixin, TitleMixin):
|
||||
allowed_models = (SAMLAttributeLookup, RenameAttributeAction, SetAttributeAction, AddRoleAction)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.authenticator = get_object_or_404(SAMLAuthenticator, pk=kwargs.get('authenticator_pk'))
|
||||
|
||||
model_name = kwargs.get('model_name')
|
||||
if model_name not in (x._meta.model_name for x in self.allowed_models):
|
||||
raise Http404()
|
||||
self.model = apps.get_model('authentic2_auth_saml', model_name)
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_class(self):
|
||||
return modelform_factory(
|
||||
self.model, exclude=('authenticator',), field_classes={'role': RoleChoiceField}
|
||||
)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
if not kwargs.get('instance'):
|
||||
kwargs['instance'] = self.model()
|
||||
kwargs['instance'].authenticator = self.authenticator
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return (
|
||||
reverse('a2-manager-authenticator-detail', kwargs={'pk': self.authenticator.pk})
|
||||
+ '#open:%s' % self.model._meta.model_name
|
||||
)
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self.model._meta.verbose_name
|
||||
|
||||
|
||||
class RelatedObjectAddView(SAMLAuthenticatorMixin, CreateView):
|
||||
template_name = 'authentic2/manager/form.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
resp = super().form_valid(form)
|
||||
self.request.journal.record(
|
||||
'authenticator.saml.related_object.creation', related_object=form.instance
|
||||
)
|
||||
return resp
|
||||
|
||||
|
||||
add_related_object = RelatedObjectAddView.as_view()
|
||||
|
||||
|
||||
class RelatedObjectEditView(SAMLAuthenticatorMixin, UpdateView):
|
||||
template_name = 'authentic2/manager/form.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
resp = super().form_valid(form)
|
||||
self.request.journal.record('authenticator.saml.related_object.edit', form=form)
|
||||
return resp
|
||||
|
||||
|
||||
edit_related_object = RelatedObjectEditView.as_view()
|
||||
|
||||
|
||||
class RelatedObjectDeleteView(SAMLAuthenticatorMixin, DeleteView):
|
||||
template_name = 'authentic2/authenticators/authenticator_delete_form.html'
|
||||
title = ''
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
self.request.journal.record(
|
||||
'authenticator.saml.related_object.deletion', related_object=self.get_object()
|
||||
)
|
||||
return super().delete(*args, **kwargs)
|
||||
|
||||
|
||||
delete_related_object = RelatedObjectDeleteView.as_view()
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import pytest
|
||||
from django import VERSION as DJ_VERSION
|
||||
from django.utils.html import escape
|
||||
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.authenticators.models import BaseAuthenticator, LoginPasswordAuthenticator
|
||||
|
@ -279,6 +280,77 @@ def test_authenticators_saml(app, superuser, ou1, ou2):
|
|||
assert 'Authenticator has been enabled.' in resp.text
|
||||
|
||||
|
||||
def test_authenticators_saml_attribute_lookup(app, superuser):
|
||||
authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
|
||||
resp = login(app, superuser, path=authenticator.get_absolute_url())
|
||||
|
||||
resp = resp.click('Add', href='samlattributelookup')
|
||||
resp.form['user_field'] = 'email'
|
||||
resp.form['saml_attribute'] = 'mail'
|
||||
resp = resp.form.submit()
|
||||
assert_event('authenticator.saml.related_object.creation', user=superuser, session=app.session)
|
||||
assert '#open:samlattributelookup' in resp.location
|
||||
|
||||
resp = resp.follow()
|
||||
assert escape('"mail" (from "email")') in resp.text
|
||||
|
||||
resp = resp.click('mail')
|
||||
resp.form['ignore_case'] = True
|
||||
resp = resp.form.submit().follow()
|
||||
assert escape('"mail" (from "email"), case insensitive') in resp.text
|
||||
assert_event('authenticator.saml.related_object.edit', user=superuser, session=app.session)
|
||||
|
||||
resp = resp.click('Remove', href='samlattributelookup')
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'mail' not in resp.text
|
||||
assert_event('authenticator.saml.related_object.deletion', user=superuser, session=app.session)
|
||||
|
||||
|
||||
def test_authenticators_saml_rename_attribute(app, superuser):
|
||||
authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
|
||||
resp = login(app, superuser, path=authenticator.get_absolute_url())
|
||||
|
||||
resp = resp.click('Add', href='renameattributeaction')
|
||||
resp.form['from_name'] = 'a'
|
||||
resp.form['to_name'] = 'b'
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'a → b' in resp.text
|
||||
|
||||
|
||||
def test_authenticators_saml_set_attribute(app, superuser):
|
||||
authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
|
||||
resp = login(app, superuser, path=authenticator.get_absolute_url())
|
||||
|
||||
resp = resp.click('Add', href='setattributeaction')
|
||||
resp.form['attribute'] = 'email'
|
||||
resp.form['saml_attribute'] = 'mail'
|
||||
resp = resp.form.submit().follow()
|
||||
assert escape('"email" from "mail"') in resp.text
|
||||
|
||||
resp = resp.click('mail')
|
||||
resp.form['mandatory'] = True
|
||||
resp = resp.form.submit().follow()
|
||||
assert escape('"email" from "mail" (mandatory)') in resp.text
|
||||
|
||||
|
||||
def test_authenticators_saml_add_role(app, superuser, role_ou1, role_ou2):
|
||||
authenticator = SAMLAuthenticator.objects.create(metadata='meta1.xml', slug='idp1')
|
||||
resp = login(app, superuser, path=authenticator.get_absolute_url())
|
||||
|
||||
resp = resp.click('Add', href='addroleaction')
|
||||
assert [x[2] for x in resp.form['role'].options] == ['---------', 'OU1 - role_ou1', 'OU2 - role_ou2']
|
||||
|
||||
resp.form['role'] = role_ou1.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'role_ou1' in resp.text
|
||||
|
||||
resp = resp.click('role_ou1')
|
||||
resp.form['role'] = role_ou2.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'role_ou1' not in resp.text
|
||||
assert 'role_ou2' in resp.text
|
||||
|
||||
|
||||
def test_authenticators_order(app, superuser):
|
||||
resp = login(app, superuser, path='/manage/authenticators/')
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ from authentic2.apps.journal.models import Event, _registry
|
|||
from authentic2.custom_user.models import Profile, ProfileType, User
|
||||
from authentic2.journal import journal
|
||||
from authentic2.models import Service
|
||||
from authentic2_auth_saml.models import RenameAttributeAction, SAMLAuthenticator
|
||||
|
||||
from .utils import login, logout, text_content
|
||||
|
||||
|
@ -58,6 +59,8 @@ def events(db, freezer):
|
|||
role_agent = Role.objects.create(name="role2", ou=ou)
|
||||
service = Service.objects.create(name="service")
|
||||
authenticator = LoginPasswordAuthenticator.objects.create(slug='test')
|
||||
saml_authenticator = SAMLAuthenticator.objects.create(slug='saml')
|
||||
rename_attribute_action = RenameAttributeAction.objects.create(authenticator=saml_authenticator)
|
||||
|
||||
class EventFactory:
|
||||
date = make_aware(datetime.datetime(2020, 1, 1))
|
||||
|
@ -301,6 +304,24 @@ def events(db, freezer):
|
|||
make('authenticator.enable', user=agent, session=session2, authenticator=authenticator)
|
||||
make('authenticator.disable', user=agent, session=session2, authenticator=authenticator)
|
||||
make('authenticator.deletion', user=agent, session=session2, authenticator=authenticator)
|
||||
make(
|
||||
'authenticator.saml.related_object.creation',
|
||||
user=agent,
|
||||
session=session2,
|
||||
related_object=rename_attribute_action,
|
||||
)
|
||||
action_edit_form = mock.Mock(spec=['instance', 'initial', 'changed_data', 'cleaned_data'])
|
||||
action_edit_form.instance = rename_attribute_action
|
||||
action_edit_form.initial = {'from_name': 'old'}
|
||||
action_edit_form.changed_data = ['from_name']
|
||||
action_edit_form.cleaned_data = {'from_name': 'new'}
|
||||
make('authenticator.saml.related_object.edit', user=agent, session=session2, form=action_edit_form)
|
||||
make(
|
||||
'authenticator.saml.related_object.deletion',
|
||||
user=agent,
|
||||
session=session2,
|
||||
related_object=rename_attribute_action,
|
||||
)
|
||||
|
||||
# verify we created at least one event for each type
|
||||
assert set(Event.objects.values_list("type__name", flat=True)) == set(_registry)
|
||||
|
@ -337,6 +358,7 @@ def extract_journal(response):
|
|||
|
||||
def test_global_journal(app, superuser, events):
|
||||
response = login(app, user=superuser, path="/manage/")
|
||||
rename_attribute_action = RenameAttributeAction.objects.get()
|
||||
|
||||
# remove event about admin login
|
||||
Event.objects.filter(user=superuser).delete()
|
||||
|
@ -692,6 +714,27 @@ def test_global_journal(app, superuser, events):
|
|||
'type': 'authenticator.deletion',
|
||||
'user': 'agent',
|
||||
},
|
||||
{
|
||||
'message': 'creation of RenameAttributeAction (%s) in authenticator "SAML"'
|
||||
% rename_attribute_action.pk,
|
||||
'timestamp': 'Jan. 3, 2020, 8 a.m.',
|
||||
'type': 'authenticator.saml.related_object.creation',
|
||||
'user': 'agent',
|
||||
},
|
||||
{
|
||||
'message': 'edit RenameAttributeAction (%s) in authenticator "SAML" (from_name)'
|
||||
% rename_attribute_action.pk,
|
||||
'timestamp': 'Jan. 3, 2020, 9 a.m.',
|
||||
'type': 'authenticator.saml.related_object.edit',
|
||||
'user': 'agent',
|
||||
},
|
||||
{
|
||||
'message': 'deletion of RenameAttributeAction (%s) in authenticator "SAML"'
|
||||
% rename_attribute_action.pk,
|
||||
'timestamp': 'Jan. 3, 2020, 10 a.m.',
|
||||
'type': 'authenticator.saml.related_object.deletion',
|
||||
'user': 'agent',
|
||||
},
|
||||
]
|
||||
|
||||
agent_page = response.click('agent', index=1)
|
||||
|
|
Loading…
Reference in New Issue