Projet

Général

Profil

0001-profile_views-include-ous-in-oidc-authz-management-p.patch

Paul Marillonnet, 05 août 2020 10:16

Télécharger (10,4 ko)

Voir les différences:

Subject: [PATCH] profile_views: include ous in oidc-authz management page
 (#45651)

 .../templates/authentic2/accounts.html        |  2 +-
 .../accounts_authorized_oauth_services.html   | 52 +++++++++++++++++++
 src/authentic2/views.py                       | 29 ++++++++---
 tests/test_idp_oidc.py                        | 34 ++++++++++--
 4 files changed, 103 insertions(+), 14 deletions(-)
src/authentic2/templates/authentic2/accounts.html
38 38
        <p><a href="{% url 'profile_edit' %}">{% trans "Edit account data" %}</a></p>
39 39
      {% endif %}
40 40
      {% if allow_authorization_management %}
41
        <p><a href="{% url 'authorized-oauth-services' %}">{% trans "Manage service authorizations" %}</a></p>
41
        <p><a href="{% url 'authorized-oauth-services' %}">{% trans "Manage OUs and services authorizations" %}</a></p>
42 42
      {% endif %}
43 43
      {% if allow_account_deletion %}
44 44
        <p><a href="{% url 'delete_account' %}">{% trans "Delete account" %}</a></p>
src/authentic2/templates/authentic2/accounts_authorized_oauth_services.html
12 12
{% endblock %}
13 13

  
14 14
{% block content %}
15
{% block oidc-authorized-oauth-ous-pre %}{% endblock %}
16
<div class="authorized-oauth-ous">
17
  {% block oidc-authorized-oauth-ous-top %}
18
  <p class="authorized-oauth-ous--top">
19
    {% if authorized_oauth_ous|length_is:0 %}
20
    {% trans "You have not granted organizational unit access to your account profile data." %}
21
    {% else %}
22
    {% blocktrans count counter=authorized_oauth_ous|length %}
23
    You have granted one organizational unit access to your account profile data.
24
    {% plural %}
25
    You have granted {{ counter }} organizational units access to your account profile data.
26
    {% endblocktrans %}
27
    {% endif %}
28
  </p>
29
  {% endblock %}
30
  <ul class="authorized-oauth-ous--list">
31
    {% for auth in authorized_oauth_ous %}
32
    <li class="authorized-oauth-ous--item">
33
      <form method="post" class="authorized-oauth-ous--form">
34
        {% csrf_token %}
35
        {% block oidc-authorized-oauth-ou %}
36
        <div class="authorized-oauth-ous--infos">
37
          {% block oidc-authorized-oauth-ou-top %}{% endblock %}
38
          <span class="authorized-oauth-ous--client">
39
            {{ auth.client }}
40
          </span>
41
          <span class="authorized-oauth-ous--dates">
42
            <span class="authorized-oauth-ous-dates--since">
43
              <span class="label">{% trans "Allowed since:" %}</span>
44
              <span class="time">{{ auth.created }}</span>
45
            </span>
46
            <span class="authorized-oauth-ous--separator">/</span>
47
            <span class="authorized-oauth-ous--expired">
48
              <span class="label">{% trans "Expire on:" %}</span>
49
              <span class="time">{{ auth.expired }}</span>
50
            </span>
51
          </span>
52
        </div>
53
        <div class="authorized-oauth-ous--actions">
54
          <input type="hidden" id="auth-id" name="auth_id" value="{{ auth.id }}">
55
          <button class="authorized-oauth-ous--revoke-button">{% trans 'Revoke' %}</button>
56
        </div>
57
        {% block oidc-authorized-oauth-ou-bottom %}{% endblock %}
58
        {% endblock %}
59
      </form>
60
    </li>
61
    {% endfor %}
62
  </ul>
63
</table>
64
{% block oidc-authorized-oauth-ous-bottom %}{% endblock %}
65
</div>
66
{% block oidc-authorized-oauth-ous-post %}{% endblock %}
15 67
{% block oidc-authorized-oauth-services-pre %}{% endblock %}
16 68
<div class="authorized-oauth-services">
17 69
  {% block oidc-authorized-oauth-services-top %}
src/authentic2/views.py
23 23
from ratelimit.utils import is_ratelimited
24 24

  
25 25
from django.conf import settings
26
from django.contrib.contenttypes.models import ContentType
26 27
from django.shortcuts import render, get_object_or_404
27 28
from django.template.loader import render_to_string
28 29
from django.views.generic.edit import UpdateView, FormView
......
512 513
            'federation_management': federation_management,
513 514
        })
514 515

  
515
        if ('authentic2_idp_oidc' in settings.INSTALLED_APPS and
516
                app_settings.A2_PROFILE_CAN_MANAGE_SERVICE_AUTHORIZATIONS):
517
            from authentic2_idp_oidc.models import OIDCClient
518
            context['allow_authorization_management'] = OIDCClient.objects.filter(
519
                    authorization_mode=OIDCClient.AUTHORIZATION_MODE_BY_SERVICE).exists()
520

  
516
        if 'authentic2_idp_oidc' in settings.INSTALLED_APPS:
517
            if app_settings.A2_PROFILE_CAN_MANAGE_SERVICE_AUTHORIZATIONS:
518
                from authentic2_idp_oidc.models import OIDCClient
519
                context['allow_authorization_management'] = OIDCClient.objects.filter(
520
                        authorization_mode__in=(
521
                            OIDCClient.AUTHORIZATION_MODE_BY_SERVICE,
522
                            OIDCClient.AUTHORIZATION_MODE_BY_OU)).exists()
521 523
        hooks.call_hooks('modify_context_data', self, context)
522 524
        return context
523 525

  
......
1285 1287

  
1286 1288
    def get_context_data(self, **kwargs):
1287 1289
        from authentic2_idp_oidc.models import OIDCAuthorization
1290
        from authentic2_idp_oidc.models import OIDCClient
1291
        from django_rbac.utils import get_ou_model
1288 1292

  
1289 1293
        context = super(AuthorizedOauthServicesView, self).get_context_data(**kwargs)
1294
        service_ct = ContentType.objects.get_for_model(OIDCClient)
1295
        ou_ct = ContentType.objects.get_for_model(get_ou_model())
1290 1296
        context['authorized_oauth_services'] = OIDCAuthorization.objects.filter(
1291
            user=self.request.user)
1297
            user=self.request.user, client_ct=service_ct)
1298
        context['authorized_oauth_ous'] = OIDCAuthorization.objects.filter(
1299
            user=self.request.user, client_ct=ou_ct)
1292 1300
        return context
1293 1301

  
1294 1302
    def post(self, request, *args, **kwargs):
1295 1303
        from authentic2_idp_oidc.models import OIDCAuthorization
1304
        from authentic2_idp_oidc.models import OIDCClient
1305
        from django_rbac.utils import get_ou_model
1296 1306

  
1297
        qs = OIDCAuthorization.objects.filter(user=request.user)
1307
        service_ct = ContentType.objects.get_for_model(OIDCClient)
1308
        ou_ct = ContentType.objects.get_for_model(get_ou_model())
1309
        qs = OIDCAuthorization.objects.filter(
1310
            user=request.user, client_ct__in=(service_ct, ou_ct))
1298 1311
        auth_id = request.POST.get('auth_id')
1299 1312
        if auth_id:
1300 1313
            qs = qs.filter(id=auth_id)
tests/test_idp_oidc.py
45 45
from authentic2.a2_rbac.utils import get_default_ou
46 46
from authentic2.utils import make_url
47 47
from authentic2_auth_oidc.utils import parse_timestamp
48
from django_rbac.utils import get_ou_model
48 49
from django_rbac.utils import get_role_model
49 50

  
50 51
User = get_user_model()
......
1615 1616

  
1616 1617

  
1617 1618
def test_oidc_authorized_oauth_services_view(app, oidc_client, simple_user):
1619
    from django.contrib.contenttypes.models import ContentType
1620

  
1618 1621
    url = make_url('authorized-oauth-services')
1619 1622
    response = app.get(url, status=302)
1620 1623
    assert '/login/' in response.location
......
1632 1635
    OIDCAuthorization.objects.create(
1633 1636
        client=oidc_client, user=simple_user, scopes='openid profile email',
1634 1637
        expired=now() + datetime.timedelta(days=2))
1638
    # create an ou-based authz that appears at the top of the page
1639
    OU = get_ou_model()
1640
    ou1 = OU.objects.create(name='Orgunit1', slug='orgunit1')
1641
    OIDCAuthorization.objects.create(
1642
        client=ou1, user=simple_user, scopes='openid profile email',
1643
        expired=now() + datetime.timedelta(days=2))
1635 1644

  
1636 1645
    response = app.get(url, status=200)
1637
    assert "You have granted 3 services access to your account profile data."
1646
    assert "You have granted one organizational unit access to your account profile data." in response.text
1647
    assert "You have granted 3 services access to your account profile data." in response.text
1648
    assert len(response.html.find_all(
1649
        'button', {'class': 'authorized-oauth-ous--revoke-button'})) == 1
1638 1650
    assert len(response.html.find_all(
1639 1651
        'button', {'class': 'authorized-oauth-services--revoke-button'})) == 3
1640 1652

  
1641
    # revoke two
1642
    response = response.forms[0].submit()
1653
    # revoke two service authz
1654
    response = response.forms[1].submit()
1643 1655
    response = response.follow()
1644 1656
    assert len(response.html.find_all(
1645 1657
        'button', {'class': 'authorized-oauth-services--revoke-button'})) == 2
1646
    response = response.forms[0].submit()
1658
    assert OIDCAuthorization.objects.filter(
1659
        client_ct=ContentType.objects.get_for_model(OIDCClient)).count() == 2
1660
    response = response.forms[1].submit()
1647 1661
    response = response.follow()
1662
    assert "You have granted one service access to your account profile data." in response.text
1648 1663
    assert len(response.html.find_all(
1649 1664
        'button', {'class': 'authorized-oauth-services--revoke-button'})) == 1
1650
    assert "You have granted one service access to your account profile data." in response.text
1665
    assert OIDCAuthorization.objects.filter(
1666
        client_ct=ContentType.objects.get_for_model(OIDCClient)).count() == 1
1667

  
1668
    # revoke the only OU authz
1669
    response = response.forms[0].submit()
1670
    response = response.follow()
1671
    assert len(response.html.find_all(
1672
        'button', {'class': 'authorized-oauth-ous--revoke-button'})) == 0
1673
    assert OIDCAuthorization.objects.filter(
1674
        client_ct=ContentType.objects.get_for_model(OU)).count() == 0
1651
-