0001-manager-add-OpenID-service-handling-20696.patch
src/authentic2/manager/service_views.py | ||
---|---|---|
39 | 39 |
listing = ServicesView.as_view() |
40 | 40 | |
41 | 41 | |
42 |
class ServiceMixin: |
|
43 |
def get_object(self, queryset=None): |
|
44 |
service = super().get_object(queryset) |
|
45 |
if hasattr(service, 'oidcclient'): |
|
46 |
return service.oidcclient |
|
47 |
return service |
|
48 | ||
49 | ||
42 | 50 |
class ServiceView( |
51 |
ServiceMixin, |
|
43 | 52 |
views.SimpleSubTableView, |
44 | 53 |
role_views.RoleViewMixin, |
45 | 54 |
views.MediaMixin, |
... | ... | |
86 | 95 |
kwargs['form'] = self.get_form() |
87 | 96 |
ctx = super().get_context_data(**kwargs) |
88 | 97 |
ctx['roles_table'] = tables.RoleTable(self.object.roles.all()) |
98 |
ctx.update(self.object.get_manager_context_data()) |
|
89 | 99 |
return ctx |
90 | 100 | |
91 | 101 | |
92 |
roles = ServiceView.as_view()
|
|
102 |
service_detail = ServiceView.as_view()
|
|
93 | 103 | |
94 | 104 | |
95 |
class ServiceEditView(views.BaseEditView): |
|
105 |
class ServiceEditView(ServiceMixin, views.BaseEditView):
|
|
96 | 106 |
model = Service |
97 | 107 |
pk_url_kwarg = 'service_pk' |
98 | 108 |
template_name = 'authentic2/manager/form.html' |
... | ... | |
101 | 111 |
fields = ['name', 'slug', 'ou', 'unauthorized_url'] |
102 | 112 |
success_url = '..' |
103 | 113 | |
114 |
def get_form_class(self): |
|
115 |
if self.object.manager_form_class: |
|
116 |
return self.object.manager_form_class |
|
117 |
return super().get_form_class() |
|
118 | ||
119 | ||
120 |
edit_service = ServiceEditView.as_view() |
|
121 | ||
122 | ||
123 |
class ServiceDeleteView(views.BaseDeleteView): |
|
124 |
model = Service |
|
125 |
pk_url_kwarg = 'service_pk' |
|
126 |
permissions = ['authentic2.delete_service'] |
|
127 |
title = _('Delete OpenID Service') |
|
128 | ||
104 | 129 | |
105 |
edit = ServiceEditView.as_view() |
|
130 |
delete_service = ServiceDeleteView.as_view() |
src/authentic2/manager/static/authentic2/manager/css/style.scss | ||
---|---|---|
287 | 287 |
max-width: 100%; |
288 | 288 |
overflow-y: auto; |
289 | 289 |
} |
290 | ||
291 |
table.claims-table td.actions { |
|
292 |
position: relative; |
|
293 |
width: 80px; |
|
294 |
a { |
|
295 |
display: inline-block; |
|
296 |
border: none; |
|
297 |
overflow: hidden; |
|
298 |
width: 30px; |
|
299 |
height: 30px; |
|
300 |
line-height: 30px; |
|
301 |
&::before { |
|
302 |
font-family: FontAwesome; |
|
303 |
padding-right: 3em; |
|
304 |
} |
|
305 |
&.delete::before { |
|
306 |
content: "\f057"; /* remove-sign */ |
|
307 |
} |
|
308 |
&.edit::before { |
|
309 |
content: "\f044"; /* edit-sign */ |
|
310 |
} |
|
311 |
} |
|
312 |
} |
src/authentic2/manager/templates/authentic2/manager/service.html | ||
---|---|---|
1 |
{% extends "authentic2/manager/services.html" %}
|
|
1 |
{% extends "authentic2/manager/base.html" %}
|
|
2 | 2 |
{% load i18n static django_tables2 %} |
3 | 3 | |
4 | 4 |
{% block page-title %}{% firstof manager_site_title site_title "Authentic2" %} - {{ object }}{% endblock %} |
5 | 5 | |
6 | 6 |
{% block breadcrumb %} |
7 |
{{ block.super }} |
|
7 |
{{ block.super }} |
|
8 |
<a href="{% url 'a2-manager-services' %}">{% trans 'Services' %}</a> |
|
8 | 9 |
<a href="{% url 'a2-manager-service' service_pk=view.kwargs.service_pk %}">{{ view.service.name }}</a> |
9 | 10 |
{% endblock %} |
10 | 11 | |
12 |
{% block buttons %} |
|
13 |
{% endblock %} |
|
14 | ||
11 | 15 |
{% block appbar %} |
12 | 16 |
{{ block.super }} |
13 | 17 |
<span class="actions"> |
18 |
{% if view.can_delete %} |
|
19 |
<a rel="popup" href="{% url "a2-manager-service-delete" service_pk=view.kwargs.service_pk %}">{% trans "Delete" %}</a> |
|
20 |
{% endif %} |
|
14 | 21 |
{% if view.can_change %} |
15 | 22 |
<a rel="popup" href="{% url "a2-manager-service-edit" service_pk=view.kwargs.service_pk %}">{% trans "Edit" %}</a> |
16 | 23 |
{% endif %} |
... | ... | |
34 | 41 |
{% endblock %} |
35 | 42 | |
36 | 43 |
{% block main %} |
44 | ||
45 |
{% if extra_details_template %} |
|
46 |
{% include extra_details_template %} |
|
47 |
{% endif %} |
|
48 | ||
37 | 49 |
<div class="section"> |
38 | 50 |
<h3>{% trans "Roles of users allowed on this service" %}</h3> |
39 | 51 |
<div id="authorized-roles"> |
src/authentic2/manager/templates/authentic2/manager/services.html | ||
---|---|---|
8 | 8 |
<a href="{% url 'a2-manager-services' %}">{% trans 'Services' %}</a> |
9 | 9 |
{% endblock %} |
10 | 10 | |
11 |
{% block appbar %} |
|
12 |
{{ block.super }} |
|
13 |
<span class="actions"> |
|
14 |
{% if view.can_add %} |
|
15 |
<a href="{% url "a2-manager-add-oidc-service" %}">{% trans "Add OIDC service" %}</a> |
|
16 |
{% endif %} |
|
17 |
</span> |
|
18 |
{% endblock %} |
|
19 | ||
11 | 20 |
{% block sidebar %} |
12 | 21 |
<aside id="sidebar"> |
13 | 22 |
{% include "authentic2/manager/search_form.html" %} |
src/authentic2/manager/urls.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
from functools import wraps |
|
18 | ||
19 | 17 |
from django.conf.urls import url |
20 |
from django.utils.functional import lazy |
|
21 | 18 |
from django.views.i18n import JavaScriptCatalog |
22 | 19 | |
23 | 20 |
from authentic2.apps.authenticators.manager_urls import urlpatterns as authenticator_urlpatterns |
24 |
from authentic2.utils import misc as utils_misc
|
|
21 |
from authentic2_idp_oidc.manager.urls import urlpatterns as oidc_manager_urlpatterns
|
|
25 | 22 | |
26 | 23 |
from ..decorators import required |
27 |
from . import journal_views, ou_views, role_views, service_views, user_views, views |
|
28 | ||
29 | ||
30 |
def manager_login_required(func): |
|
31 |
@wraps(func) |
|
32 |
def _wrapped_view(request, *args, **kwargs): |
|
33 |
if request.user.is_authenticated: |
|
34 |
return func(request, *args, **kwargs) |
|
35 |
return utils_misc.login_require( |
|
36 |
request, login_url=lazy(utils_misc.get_manager_login_url, str)(), login_hint=['backoffice'] |
|
37 |
) |
|
38 | ||
39 |
return _wrapped_view |
|
40 | ||
24 |
from . import journal_views, ou_views, role_views, service_views, user_views, utils, views |
|
41 | 25 | |
42 | 26 |
urlpatterns = required( |
43 |
manager_login_required, |
|
27 |
utils.manager_login_required,
|
|
44 | 28 |
[ |
45 | 29 |
# homepage |
46 | 30 |
url(r'^$', views.homepage, name='a2-manager-homepage'), |
... | ... | |
182 | 166 |
url(r'^organizational-units/import/$', ou_views.ous_import, name='a2-manager-ous-import'), |
183 | 167 |
# Services |
184 | 168 |
url(r'^services/$', service_views.listing, name='a2-manager-services'), |
185 |
url(r'^services/(?P<service_pk>\d+)/$', service_views.roles, name='a2-manager-service'), |
|
186 |
url(r'^services/(?P<service_pk>\d+)/edit/$', service_views.edit, name='a2-manager-service-edit'), |
|
187 |
# Journal |
|
169 |
url(r'^services/(?P<service_pk>\d+)/$', service_views.service_detail, name='a2-manager-service'), |
|
170 |
url( |
|
171 |
r'^services/(?P<service_pk>\d+)/edit/$', |
|
172 |
service_views.edit_service, |
|
173 |
name='a2-manager-service-edit', |
|
174 |
), |
|
175 |
url( |
|
176 |
r'^services/(?P<service_pk>\d+)/delete/$', |
|
177 |
service_views.delete_service, |
|
178 |
name='a2-manager-service-delete', |
|
179 |
), # Journal |
|
188 | 180 |
url(r'^journal/$', journal_views.journal, name='a2-manager-journal'), |
189 | 181 |
url( |
190 | 182 |
r'^journal/event-types/$', |
... | ... | |
202 | 194 |
) |
203 | 195 | |
204 | 196 |
urlpatterns += authenticator_urlpatterns |
197 |
urlpatterns += oidc_manager_urlpatterns |
|
205 | 198 | |
206 | 199 |
urlpatterns += [ |
207 | 200 |
url( |
src/authentic2/manager/utils.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
from functools import wraps |
|
18 | ||
19 |
from django.utils.functional import lazy |
|
20 | ||
17 | 21 |
from authentic2.a2_rbac.models import OrganizationalUnit |
22 |
from authentic2.utils import misc as utils_misc |
|
18 | 23 |
from authentic2.utils.cache import GlobalCache |
19 | 24 | |
20 | 25 | |
... | ... | |
44 | 49 |
@GlobalCache(timeout=10) |
45 | 50 |
def has_show_username(): |
46 | 51 |
return not OrganizationalUnit.objects.filter(show_username=False).exists() |
52 | ||
53 | ||
54 |
def manager_login_required(func): |
|
55 |
@wraps(func) |
|
56 |
def _wrapped_view(request, *args, **kwargs): |
|
57 |
if request.user.is_authenticated: |
|
58 |
return func(request, *args, **kwargs) |
|
59 |
return utils_misc.login_require( |
|
60 |
request, login_url=lazy(utils_misc.get_manager_login_url, str)(), login_hint=['backoffice'] |
|
61 |
) |
|
62 | ||
63 |
return _wrapped_view |
src/authentic2/models.py | ||
---|---|---|
416 | 416 | |
417 | 417 |
objects = managers.ServiceManager() |
418 | 418 | |
419 |
manager_form_class = None |
|
420 | ||
419 | 421 |
def clean(self): |
420 | 422 |
errors = {} |
421 | 423 | |
... | ... | |
499 | 501 | |
500 | 502 |
return super().delete(*args, **kwargs) |
501 | 503 | |
504 |
def get_manager_context_data(self): |
|
505 |
return {} |
|
506 | ||
502 | 507 | |
503 | 508 |
Service._meta.natural_key = [['slug', 'ou']] |
504 | 509 |
src/authentic2_idp_oidc/app_settings.py | ||
---|---|---|
83 | 83 |
def PROFILE_OVERRIDE_MAPPING(self): |
84 | 84 |
return self._setting('PROFILE_OVERRIDE_MAPPING', {'email': 'email'}) |
85 | 85 | |
86 |
@property |
|
87 |
def MANAGER_FIELDS(self): |
|
88 |
return self._setting( |
|
89 |
'MANAGER_FIELDS', |
|
90 |
[ |
|
91 |
'name', |
|
92 |
'redirect_uris', |
|
93 |
'post_logout_redirect_uris', |
|
94 |
'sector_identifier_uri', |
|
95 |
'frontchannel_logout_uri', |
|
96 |
'ou', |
|
97 |
'identifier_policy', |
|
98 |
'idtoken_algo', |
|
99 |
'unauthorized_url', |
|
100 |
'authorization_mode', |
|
101 |
'authorization_flow', |
|
102 |
'home_url', |
|
103 |
'colour', |
|
104 |
'logo', |
|
105 |
], |
|
106 |
) |
|
107 | ||
86 | 108 | |
87 | 109 |
app_settings = AppSettings('A2_IDP_OIDC_') |
88 | 110 |
app_settings.__name__ = __name__ |
src/authentic2_idp_oidc/manager/forms.py | ||
---|---|---|
1 |
# authentic2 - versatile identity manager |
|
2 |
# Copyright (C) 2022 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from django import forms |
|
18 | ||
19 |
from authentic2.attributes_ng.engine import get_service_attributes |
|
20 |
from authentic2.forms.mixins import SlugMixin |
|
21 |
from authentic2.forms.widgets import DatalistTextInput |
|
22 |
from authentic2_idp_oidc.models import OIDCClaim, OIDCClient |
|
23 | ||
24 |
from .. import app_settings |
|
25 | ||
26 | ||
27 |
class OIDCClientForm(SlugMixin, forms.ModelForm): |
|
28 |
class Meta: |
|
29 |
model = OIDCClient |
|
30 |
fields = app_settings.MANAGER_FIELDS |
|
31 | ||
32 |
def __init__(self, *args, **kwargs): |
|
33 |
super().__init__(*args, **kwargs) |
|
34 |
self.fields['colour'].widget = forms.TextInput(attrs={'type': 'color'}) |
|
35 | ||
36 | ||
37 |
class OIDCClaimForm(forms.ModelForm): |
|
38 |
class Meta: |
|
39 |
model = OIDCClaim |
|
40 |
fields = ('name', 'value', 'scopes') |
|
41 |
widgets = { |
|
42 |
'value': DatalistTextInput, |
|
43 |
} |
|
44 | ||
45 |
def __init__(self, *args, **kwargs): |
|
46 |
super().__init__(*args, **kwargs) |
|
47 |
data = dict(get_service_attributes(getattr(self.instance, 'client', None))).keys() |
|
48 |
widget = self.fields['value'].widget |
|
49 |
widget.data = data |
|
50 |
widget.name = 'list__oidcclaim-inline' |
|
51 |
widget.attrs.update({'list': 'list__oidcclaim-inline'}) |
src/authentic2_idp_oidc/manager/urls.py | ||
---|---|---|
1 |
# authentic2 - versatile identity manager |
|
2 |
# Copyright (C) 2022p Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 | ||
18 |
from django.conf.urls import url |
|
19 | ||
20 |
from authentic2.decorators import required |
|
21 |
from authentic2.manager.utils import manager_login_required |
|
22 | ||
23 |
from . import views |
|
24 | ||
25 |
urlpatterns = required( |
|
26 |
manager_login_required, |
|
27 |
[ |
|
28 |
url(r'^services/add-oidc/$', views.add_oidc_service, name='a2-manager-add-oidc-service'), |
|
29 |
url( |
|
30 |
r'^services/(?P<service_pk>\d+)/claim/add/$', |
|
31 |
views.oidc_claim_add, |
|
32 |
name='a2-manager-oidc-claim-add', |
|
33 |
), |
|
34 |
url( |
|
35 |
r'^services/(?P<service_pk>\d+)/claim/(?P<claim_pk>\d+)/edit/$', |
|
36 |
views.oidc_claim_edit, |
|
37 |
name='a2-manager-oidc-claim-edit', |
|
38 |
), |
|
39 |
url( |
|
40 |
r'^services/(?P<service_pk>\d+)/claim/(?P<claim_pk>\d+)/delete/$', |
|
41 |
views.oidc_claim_delete, |
|
42 |
name='a2-manager-oidc-claim-delete', |
|
43 |
), |
|
44 |
], |
|
45 |
) |
src/authentic2_idp_oidc/manager/views.py | ||
---|---|---|
1 |
# authentic2 - versatile identity manager |
|
2 |
# Copyright (C) 2022 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from django.urls import reverse |
|
18 |
from django.utils.translation import ugettext_lazy as _ |
|
19 | ||
20 |
from authentic2.manager import views |
|
21 |
from authentic2_idp_oidc import app_settings |
|
22 |
from authentic2_idp_oidc.models import OIDCClaim, OIDCClient |
|
23 | ||
24 |
from . import forms |
|
25 | ||
26 | ||
27 |
class OIDCServiceAddView(views.ActionMixin, views.BaseAddView): |
|
28 |
form_class = forms.OIDCClientForm |
|
29 |
model = OIDCClient |
|
30 |
title = _('Add OIDC service') |
|
31 |
permissions = ['authentic2.add_service'] |
|
32 |
action = _('Add') |
|
33 | ||
34 |
def get_success_url(self): |
|
35 |
# add default claims mappings after creating service |
|
36 |
for mapping in app_settings.DEFAULT_MAPPINGS: |
|
37 |
OIDCClaim.objects.get_or_create(client=self.object, **mapping) |
|
38 |
return reverse('a2-manager-service', kwargs={'service_pk': self.object.pk}) |
|
39 | ||
40 | ||
41 |
add_oidc_service = OIDCServiceAddView.as_view() |
|
42 | ||
43 | ||
44 |
class OIDCClaimAddView(views.ActionMixin, views.BaseAddView): |
|
45 |
form_class = forms.OIDCClaimForm |
|
46 |
model = OIDCClaim |
|
47 |
title = _('Add OIDC Claim') |
|
48 |
action = _('Add') |
|
49 | ||
50 |
def form_valid(self, form): |
|
51 |
obj = form.save(commit=False) |
|
52 |
obj.client = OIDCClient.objects.get(pk=self.kwargs['service_pk']) |
|
53 |
obj.save() |
|
54 |
return super().form_valid(form) |
|
55 | ||
56 |
def get_success_url(self): |
|
57 |
return reverse('a2-manager-service', kwargs={'service_pk': self.object.client.pk}) |
|
58 | ||
59 | ||
60 |
oidc_claim_add = OIDCClaimAddView.as_view() |
|
61 | ||
62 | ||
63 |
class BaseClaimView: |
|
64 |
model = OIDCClaim |
|
65 |
pk_url_kwarg = 'claim_pk' |
|
66 | ||
67 |
def get_queryset(self): |
|
68 |
qs = super().get_queryset() |
|
69 |
return qs.filter(client__pk=self.kwargs['service_pk']) |
|
70 | ||
71 |
def get_success_url(self): |
|
72 |
return reverse('a2-manager-service', kwargs={'service_pk': self.object.client.pk}) |
|
73 | ||
74 | ||
75 |
class OIDCClaimEditView(BaseClaimView, views.BaseEditView): |
|
76 |
title = _('Edit OpenID Claim') |
|
77 |
form_class = forms.OIDCClaimForm |
|
78 | ||
79 | ||
80 |
oidc_claim_edit = OIDCClaimEditView.as_view() |
|
81 | ||
82 | ||
83 |
class OIDCClaimDeleteView(BaseClaimView, views.BaseDeleteView): |
|
84 |
title = _('Delete OpenID Claim') |
|
85 | ||
86 | ||
87 |
oidc_claim_delete = OIDCClaimDeleteView.as_view() |
src/authentic2_idp_oidc/models.py | ||
---|---|---|
238 | 238 |
self.get_identifier_policy_display(), |
239 | 239 |
) |
240 | 240 | |
241 |
@property |
|
242 |
def manager_form_class(self): |
|
243 |
from .manager.forms import OIDCClientForm |
|
244 | ||
245 |
return OIDCClientForm |
|
246 | ||
247 |
def get_manager_fields(self): |
|
248 |
# add client id and secret |
|
249 |
display_fields = ['client_id', 'client_secret'] + app_settings.MANAGER_FIELDS |
|
250 |
# but remove name because it's already displayed |
|
251 |
if 'name' in display_fields: |
|
252 |
display_fields.remove('name') |
|
253 |
for field in display_fields: |
|
254 |
field_value = getattr(self, field) |
|
255 |
if not field_value: |
|
256 |
continue |
|
257 |
if hasattr(self, 'get_%s_display' % field): |
|
258 |
field_value = getattr(self, 'get_%s_display' % field)() |
|
259 |
yield self._meta.get_field(field).verbose_name, field_value |
|
260 | ||
261 |
def get_manager_context_data(self): |
|
262 |
ctx = { |
|
263 |
'claims': self.oidcclaim_set.all(), |
|
264 |
'object_fields': self.get_manager_fields(), |
|
265 |
'extra_details_template': 'authentic2_idp_oidc/manager/object_detail.html', |
|
266 |
} |
|
267 |
return ctx |
|
268 | ||
241 | 269 | |
242 | 270 |
class OIDCAuthorization(models.Model): |
243 | 271 |
client_ct = models.ForeignKey( |
src/authentic2_idp_oidc/templates/authentic2_idp_oidc/manager/object_detail.html | ||
---|---|---|
1 |
{% load i18n %} |
|
2 |
{% for field, value in object_fields %} |
|
3 |
<p>{{ field|capfirst }}{% trans ":" %} {% if value == True %}{% trans "yes" %} |
|
4 |
{% elif value == False %}{% trans "no" %} |
|
5 |
{% else %}{{value}} |
|
6 |
{% endif %}</p> |
|
7 |
{% endfor %} |
|
8 | ||
9 |
<div class="section"> |
|
10 |
<h3>{% trans "OIDC Claims" %}<a href="{% url "a2-manager-oidc-claim-add" service_pk=object.pk %}" class="button" rel="popup">{% trans "Add claim" %}</a></h3> |
|
11 |
{% if claims %} |
|
12 |
<table class="main claims-table" id="oidc-claims"> |
|
13 |
<thead> |
|
14 |
<tr><th>{% trans "Name" %}</th><th>{% trans "Value" %}</th><th>{% trans "Scopes" %}</th><th></th></tr> |
|
15 |
</thead> |
|
16 |
<tbody> |
|
17 |
{% for claim in claims %} |
|
18 |
<tr> |
|
19 |
<td>{{ claim.name }}</td> |
|
20 |
<td>{{ claim.value }}</td> |
|
21 |
<td>{{ claim.scopes }}</td> |
|
22 |
<td class="actions"> |
|
23 |
<a class="edit" href="{% url "a2-manager-oidc-claim-edit" service_pk=object.pk claim_pk=claim.pk %}" rel="popup" title="{% trans "Edit" %}">{% trans "Edit" %}</a> |
|
24 |
<a class="delete" href="{% url "a2-manager-oidc-claim-delete" service_pk=object.pk claim_pk=claim.pk %}" rel="popup" title="{% trans "Delete" %}">{% trans "Delete" %}</a> |
|
25 |
</td> |
|
26 |
</tr> |
|
27 |
{% endfor %} |
|
28 |
</tbody> |
|
29 |
</table> |
|
30 |
{% endif %} |
|
31 |
</div> |
tests/test_manager.py | ||
---|---|---|
34 | 34 |
from authentic2.apps.journal.models import Event |
35 | 35 |
from authentic2.models import Service |
36 | 36 |
from authentic2.validators import EmailValidator |
37 |
from authentic2_idp_oidc import app_settings as oidc_app_settings |
|
38 |
from authentic2_idp_oidc.models import OIDCClaim, OIDCClient |
|
37 | 39 |
from django_rbac.models import VIEW_OP |
38 | 40 |
from django_rbac.utils import get_operation |
39 | 41 | |
... | ... | |
1220 | 1222 |
resp = resp.form.submit() |
1221 | 1223 |
assert 'Test Service' in resp.text |
1222 | 1224 |
assert 'Example Service' not in resp.text |
1225 | ||
1226 | ||
1227 |
def test_manager_add_oidc_service(app, superuser): |
|
1228 |
resp = login(app, superuser, 'a2-manager-services') |
|
1229 |
assert 'Add OIDC service' in resp.text |
|
1230 |
assert OIDCClient.objects.count() == 0 |
|
1231 |
assert OIDCClaim.objects.count() == 0 |
|
1232 | ||
1233 |
resp = resp.click('Add OIDC service') |
|
1234 |
form = resp.form |
|
1235 |
for field in oidc_app_settings.MANAGER_FIELDS: |
|
1236 |
assert field in form.fields |
|
1237 | ||
1238 |
form['name'] = 'Test' |
|
1239 |
form['redirect_uris'] = 'http://example.com' |
|
1240 |
resp = form.submit() |
|
1241 | ||
1242 |
assert OIDCClient.objects.count() == 1 |
|
1243 |
assert OIDCClaim.objects.count() == len(oidc_app_settings.DEFAULT_MAPPINGS) |
|
1244 |
assert resp.location == reverse('a2-manager-service', kwargs={'service_pk': OIDCClient.objects.get().pk}) |
|
1245 | ||
1246 |
resp = resp.follow() |
|
1247 |
assert "<h3>OIDC Claims" in resp.text |
|
1248 |
assert "Add claim" in resp.text |
|
1249 |
assert resp.pyquery.remove_namespaces()('#oidc-claims tbody tr').length == len( |
|
1250 |
oidc_app_settings.DEFAULT_MAPPINGS |
|
1251 |
) |
|
1252 | ||
1253 | ||
1254 |
def test_manager_edit_oidc_service(app, superuser): |
|
1255 |
OIDCClient.objects.create(name='Test', slug='test', redirect_uris='http://example.com') |
|
1256 |
resp = login(app, superuser, 'a2-manager-services') |
|
1257 |
resp = resp.click('Test') |
|
1258 |
resp = resp.click('Edit') |
|
1259 |
form = resp.form |
|
1260 |
form['name'] = 'New Test' |
|
1261 |
form['colour'] = '#ff00ff' |
|
1262 |
resp = form.submit() |
|
1263 |
assert resp.location == '..' |
|
1264 |
resp = resp.follow() |
|
1265 |
assert "New Test" in resp.text |
|
1266 |
assert "#ff00ff" in resp.text |
|
1267 | ||
1268 | ||
1269 |
def test_manager_delete_oidc_service(app, superuser): |
|
1270 |
OIDCClient.objects.create(name='Test', slug='test', redirect_uris='http://example.com') |
|
1271 |
resp = login(app, superuser, 'a2-manager-services') |
|
1272 |
resp = resp.click('Test') |
|
1273 |
resp = resp.click('Delete') |
|
1274 |
resp = resp.form.submit().follow() |
|
1275 |
assert OIDCClient.objects.count() == 0 |
|
1276 | ||
1277 | ||
1278 |
def test_manager_add_oidc_claim(app, superuser): |
|
1279 |
client = OIDCClient.objects.create(name='Test', slug='test', redirect_uris='http://example.com') |
|
1280 |
resp = login(app, superuser, reverse('a2-manager-service', kwargs={'service_pk': client.pk})) |
|
1281 |
resp = resp.click('Add claim') |
|
1282 |
form = resp.form |
|
1283 |
form['name'] = 'claim' |
|
1284 |
form['value'] = 'value' |
|
1285 |
form['scopes'] = 'profile' |
|
1286 |
resp = form.submit() |
|
1287 |
assert resp.location == reverse('a2-manager-service', kwargs={'service_pk': client.pk}) |
|
1288 |
assert OIDCClaim.objects.filter(client=client, name='claim', value='value', scopes='profile').exists() |
|
1289 | ||
1290 | ||
1291 |
def test_manager_edit_oidc_claim(app, superuser): |
|
1292 |
client = OIDCClient.objects.create(name='Test', slug='test', redirect_uris='http://example.com') |
|
1293 |
OIDCClaim.objects.create(client=client, name='claim', value='value', scopes='profile') |
|
1294 |
resp = login(app, superuser, reverse('a2-manager-service', kwargs={'service_pk': client.pk})) |
|
1295 |
assert "claim" in resp.text |
|
1296 |
resp = resp.click('Edit', index=1) |
|
1297 |
form = resp.form |
|
1298 |
form['value'] = 'new value' |
|
1299 |
resp = form.submit() |
|
1300 |
assert resp.location == reverse('a2-manager-service', kwargs={'service_pk': client.pk}) |
|
1301 |
assert not OIDCClaim.objects.filter(client=client, name='claim', value='value', scopes='profile').exists() |
|
1302 |
assert OIDCClaim.objects.filter(client=client, name='claim', value='new value', scopes='profile').exists() |
|
1303 | ||
1304 | ||
1305 |
def test_manager_delete_oidc_claim(app, superuser): |
|
1306 |
client = OIDCClient.objects.create(name='Test', slug='test', redirect_uris='http://example.com') |
|
1307 |
OIDCClaim.objects.create(client=client, name='claim', value='value', scopes='profile') |
|
1308 |
resp = login(app, superuser, reverse('a2-manager-service', kwargs={'service_pk': client.pk})) |
|
1309 |
assert "claim" in resp.text |
|
1310 |
resp = resp.click('Delete', index=1) |
|
1311 |
form = resp.form |
|
1312 |
resp = form.submit() |
|
1313 |
assert resp.location == reverse('a2-manager-service', kwargs={'service_pk': client.pk}) |
|
1314 |
assert not OIDCClaim.objects.filter(client=client, name='claim', value='value', scopes='profile').exists() |
|
1223 |
- |