Projet

Général

Profil

0004-to-be-fixed-up-use-a-decorator-to-indicate-views-whe.patch

Benjamin Dauvergne, 23 juillet 2021 11:59

Télécharger (9,77 ko)

Voir les différences:

Subject: [PATCH 4/4] to be fixed up: use a decorator to indicate views where
 view_restriction can be applied

 src/authentic2/idp/saml/saml2_endpoints.py | 12 -------
 src/authentic2/idp/saml/urls.py            |  9 ++---
 src/authentic2/middleware.py               |  6 ++--
 src/authentic2/urls.py                     |  5 +--
 src/authentic2/utils/view_decorators.py    | 40 ++++++++++++++++++++++
 src/authentic2/views.py                    |  3 --
 src/authentic2_idp_cas/urls.py             |  6 ++--
 src/authentic2_idp_oidc/urls.py            |  4 ++-
 8 files changed, 57 insertions(+), 28 deletions(-)
 create mode 100644 src/authentic2/utils/view_decorators.py
src/authentic2/idp/saml/saml2_endpoints.py
1126 1126
    return return_saml2_response(request, logout, title=_('You are being redirected to "%s"') % provider.name)
1127 1127

  
1128 1128

  
1129
finish_slo.no_view_restriction = True
1130

  
1131

  
1132 1129
def return_logout_error(request, logout, error):
1133 1130
    logout.buildResponseMsg()
1134 1131
    set_saml2_response_responder_status_code(logout.response, error)
......
1448 1445
    return a2_views.logout(request, next_url=next_url, do_local=False, check_referer=False)
1449 1446

  
1450 1447

  
1451
slo.no_view_restriction = True
1452

  
1453

  
1454 1448
def icon_url(name):
1455 1449
    return '%s/authentic2/images/%s.png' % (settings.STATIC_URL, name)
1456 1450

  
......
1535 1529
        return HttpResponseRedirect(logout.msgUrl)
1536 1530

  
1537 1531

  
1538
idp_slo.no_view_restriction = True
1539

  
1540

  
1541 1532
def process_logout_response(request, logout, soap_response, next):
1542 1533
    logger.debug('logout response is %r', soap_response)
1543 1534
    try:
......
1579 1570
    return process_logout_response(request, logout, get_saml2_query_request(request), next)
1580 1571

  
1581 1572

  
1582
slo_return.no_view_restriction = True
1583

  
1584

  
1585 1573
# Helpers
1586 1574

  
1587 1575
# Mapping to generate the metadata file, must be kept in sync with the url
src/authentic2/idp/saml/urls.py
28 28
    slo_soap,
29 29
    sso,
30 30
)
31
from authentic2.utils.view_decorators import view_restriction
31 32

  
32 33
from . import views
33 34

  
34 35
urlpatterns = [
35 36
    url(r'^metadata$', metadata, name='a2-idp-saml-metadata'),
36
    url(r'^sso$', sso, name='a2-idp-saml-sso'),
37
    url(r'^continue$', continue_sso, name='a2-idp-saml-continue'),
37
    url(r'^sso$', view_restriction(sso), name='a2-idp-saml-sso'),
38
    url(r'^continue$', view_restriction(continue_sso), name='a2-idp-saml-continue'),
38 39
    url(r'^slo$', slo, name='a2-idp-saml-slo'),
39 40
    url(r'^slo/soap$', slo_soap, name='a2-idp-saml-slo-soap'),
40 41
    url(r'^idp_slo/(.*)$', idp_slo, name='a2-idp-saml-slo-idp'),
......
42 43
    url(r'^finish_slo$', finish_slo, name='a2-idp-saml-finish-slo'),
43 44
    url(r'^artifact$', artifact, name='a2-idp-saml-artifact'),
44 45
    # legacy endpoint, now it's prefered to pass the entity_id in a parameter
45
    url(r'^idp_sso/(.+)$', idp_sso, name='a2-idp-saml-idp-sso-named'),
46
    url(r'^idp_sso/$', idp_sso, name='a2-idp-saml2-idp-sso'),
46
    url(r'^idp_sso/(.+)$', view_restriction(idp_sso), name='a2-idp-saml-idp-sso-named'),
47
    url(r'^idp_sso/$', view_restriction(idp_sso), name='a2-idp-saml2-idp-sso'),
47 48
    url(r'^federations/create/(?P<pk>\d+)/$', views.create_federation, name='a2-idp-saml2-federation-create'),
48 49
    url(r'^federations/(?P<pk>\d+)/delete/$', views.delete_federation, name='a2-idp-saml2-federation-delete'),
49 50
]
src/authentic2/middleware.py
166 166

  
167 167
    def process_view(self, request, view_func, view_args, view_kwargs):
168 168
        '''If current view is not the one where we should be, redirect'''
169
        if not getattr(view_func, 'view_restriction', False):
170
            return
169 171
        view = self.check_view_restrictions(request)
170 172
        if not view:
171 173
            return
......
174 176
        # do not block on the restricted view
175 177
        if url_name == view:
176 178
            return
177

  
178
        # prevent blocking some views, like logout views
179
        if getattr(request.resolver_match.func, 'no_view_restriction', False):
180
            return
181 179
        return utils_misc.redirect_and_come_back(request, view)
182 180

  
183 181

  
src/authentic2/urls.py
34 34
from authentic2.decorators import lasso_required, required, setting_enabled
35 35

  
36 36
from . import plugins, views
37
from .utils.view_decorators import view_restriction
37 38

  
38 39
admin.autodiscover()
39 40

  
......
67 68
        login_required(views.authorized_oauth_services),
68 69
        name='authorized-oauth-services',
69 70
    ),
70
    url(r'^$', views.profile, name='account_management'),
71
    url(r'^$', view_restriction(views.profile), name='account_management'),
71 72
    # Password change
72 73
    url(r'^password/change/$', views.password_change, name='password_change'),
73 74
    url(
......
99 100
]
100 101

  
101 102
urlpatterns = [
102
    url(r'^$', views.homepage, name='auth_homepage'),
103
    url(r'^$', view_restriction(views.homepage), name='auth_homepage'),
103 104
    url(r'^login/$', views.login, name='auth_login'),
104 105
    url(r'^logout/$', views.logout, name='auth_logout'),
105 106
    url(r'^su/(?P<uuid>[A-Za-z0-9_-]+)/$', views.su, name='su'),
src/authentic2/utils/view_decorators.py
1
# authentic2 - versatile identity manager
2
# Copyright (C) 2010-2021 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
import copy
18
import functools
19
import types
20

  
21

  
22
def copy_callable(f):
23
    """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
24
    assert hasattr(f, '__call__')
25

  
26
    if isinstance(f, types.FunctionType):
27
        g = types.FunctionType(
28
            f.__code__, f.__globals__, name=f.__name__, argdefs=f.__defaults__, closure=f.__closure__
29
        )
30
        g = functools.update_wrapper(g, f)
31
        g.__kwdefaults__ = f.__kwdefaults__
32
        return g
33
    else:
34
        return copy.copy(f)
35

  
36

  
37
def view_restriction(view):
38
    decorated_view = copy_callable(view)
39
    decorated_view.view_restriction = True
40
    return decorated_view
src/authentic2/views.py
630 630
    return response
631 631

  
632 632

  
633
logout.no_view_restriction = True
634

  
635

  
636 633
def login_password_profile(request, *args, **kwargs):
637 634
    context = kwargs.pop('context', {})
638 635
    can_change_password = utils_misc.user_can_change_password(request=request)
src/authentic2_idp_cas/urls.py
16 16

  
17 17
from django.conf.urls import url
18 18

  
19
from authentic2.utils.view_decorators import view_restriction
20

  
19 21
from . import views
20 22

  
21 23
urlpatterns = [
22
    url('^login/?$', views.login, name='a2-idp-cas-login'),
23
    url('^continue/$', views._continue, name='a2-idp-cas-continue'),
24
    url('^login/?$', view_restriction(views.login), name='a2-idp-cas-login'),
25
    url('^continue/$', view_restriction(views._continue), name='a2-idp-cas-continue'),
24 26
    url('^validate/?$', views.validate, name='a2-idp-cas-validate'),
25 27
    url('^serviceValidate/?$', views.service_validate, name='a2-idp-cas-service-validate'),
26 28
    url('^logout/?$', views.logout, name='a2-idp-cas-logout'),
src/authentic2_idp_oidc/urls.py
16 16

  
17 17
from django.conf.urls import url
18 18

  
19
from authentic2.utils.view_decorators import view_restriction
20

  
19 21
from . import views
20 22

  
21 23
urlpatterns = [
22 24
    url(r'^.well-known/openid-configuration$', views.openid_configuration, name='oidc-openid-configuration'),
23 25
    url(r'^idp/oidc/certs/?$', views.certs, name='oidc-certs'),
24
    url(r'^idp/oidc/authorize/?$', views.authorize, name='oidc-authorize'),
26
    url(r'^idp/oidc/authorize/?$', view_restriction(views.authorize), name='oidc-authorize'),
25 27
    url(r'^idp/oidc/token/?$', views.token, name='oidc-token'),
26 28
    url(r'^idp/oidc/user_info/?$', views.user_info, name='oidc-user-info'),
27 29
    url(r'^idp/oidc/logout/?$', views.logout, name='oidc-logout'),
28
-