0001-profile_views-include-ous-in-oidc-authz-management-p.patch
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 |
- |