Implements admin token deletion

This commit is contained in:
Éloi Rivard 2023-02-04 18:41:49 +01:00
parent 3ac7a8013f
commit 3359b51d9b
4 changed files with 126 additions and 39 deletions

View file

@ -1,9 +1,15 @@
import datetime
from canaille.flaskutils import permissions_needed from canaille.flaskutils import permissions_needed
from canaille.models import User from canaille.models import User
from canaille.oidc.models import Client from canaille.oidc.models import Client
from canaille.oidc.models import Token from canaille.oidc.models import Token
from flask import abort from flask import abort
from flask import Blueprint from flask import Blueprint
from flask import flash
from flask import redirect
from flask import url_for
from flask_babel import gettext as _
from flask_themer import render_template from flask_themer import render_template
@ -40,3 +46,18 @@ def view(user, token_id):
token_audience=token_audience, token_audience=token_audience,
menuitem="admin", menuitem="admin",
) )
@bp.route("/<token_id>/revoke", methods=["GET", "POST"])
@permissions_needed("manage_oidc")
def revoke(user, token_id):
token = Token.get(token_id=token_id)
if not token:
abort(404)
token.revokation_date = datetime.datetime.now()
token.save()
flash(_("The token has successfully been revoked."), "success")
return redirect(url_for("oidc.tokens.view", token_id=token_id))

View file

@ -2,13 +2,30 @@
{% import 'fomanticui.html' as sui %} {% import 'fomanticui.html' as sui %}
{% block script %} {% block script %}
<script src="/static/js/confirm.js"></script>
<script src="/static/js/copy.js"></script> <script src="/static/js/copy.js"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="modal-delete" class="ui basic modal">
<div class="ui icon header">
<i class="trash icon"></i>
{% trans %}Token deletion{% endtrans %}
</div>
<div class="content">
<p>
{{ _("Are you sure you want to revoke this token? This action is unrevokable.") }}
</p>
</div>
<div class="actions">
<div class="ui inverted cancel button">{% trans %}Cancel{% endtrans %}</div>
<div class="ui inverted red approve button">{% trans %}Delete{% endtrans %}</div>
</div>
</div>
<div class="loginform"> <div class="loginform">
<h3 class="ui top attached header"> <h3 class="ui top attached header">
{% trans %}View a token{% endtrans %} {% trans %}Token details{% endtrans %}
</h3> </h3>
<div class="ui attached clearing segment"> <div class="ui attached clearing segment">
@ -59,7 +76,18 @@
</tr> </tr>
<tr> <tr>
<td>{{ _("Revokation date") }}</td> <td>{{ _("Revokation date") }}</td>
<td>{% if token.revokation_date %}{{ token.revokation_date }}{% endif %}</td> <td>
{% if token.revokation_date %}
{{ token.revokation_date }}
{% else %}
<a href="{{ url_for("oidc.tokens.revoke", token_id=token.token_id) }}" class="ui negative right floated button confirm" name="action" value="delete" id="delete">
{% trans %}Revoke token{% endtrans %}
</a>
<p>
{% trans %}This token has not been revoked{% endtrans %}
</p>
{% endif %}
</td>
</tr> </tr>
<tr> <tr>
<td>{{ _("Lifetime") }}</td> <td>{{ _("Lifetime") }}</td>

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-01-22 13:42+0100\n" "POT-Creation-Date: 2023-02-04 18:36+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,7 +18,7 @@ msgstr ""
"Generated-By: Babel 2.11.0\n" "Generated-By: Babel 2.11.0\n"
#: canaille/account.py:103 canaille/account.py:128 #: canaille/account.py:103 canaille/account.py:128
#: canaille/oidc/endpoints.py:81 #: canaille/oidc/endpoints.py:82
msgid "Login failed, please check your information" msgid "Login failed, please check your information"
msgstr "" msgstr ""
@ -42,7 +42,7 @@ msgid ""
"should receive it within a few minutes." "should receive it within a few minutes."
msgstr "" msgstr ""
#: canaille/account.py:176 canaille/account.py:426 #: canaille/account.py:176 canaille/account.py:423
msgid "Could not send the password initialization email" msgid "Could not send the password initialization email"
msgstr "" msgstr ""
@ -76,65 +76,65 @@ msgstr ""
msgid "You account has been created successfuly." msgid "You account has been created successfuly."
msgstr "" msgstr ""
#: canaille/account.py:393 #: canaille/account.py:390
msgid "User account creation succeed." msgid "User account creation succeed."
msgstr "" msgstr ""
#: canaille/account.py:420 #: canaille/account.py:417
msgid "" msgid ""
"A password initialization link has been sent at the user email address. " "A password initialization link has been sent at the user email address. "
"It should be received within a few minutes." "It should be received within a few minutes."
msgstr "" msgstr ""
#: canaille/account.py:437 #: canaille/account.py:434
msgid "" msgid ""
"A password reset link has been sent at the user email address. It should " "A password reset link has been sent at the user email address. It should "
"be received within a few minutes." "be received within a few minutes."
msgstr "" msgstr ""
#: canaille/account.py:443 #: canaille/account.py:440
msgid "Could not send the password reset email" msgid "Could not send the password reset email"
msgstr "" msgstr ""
#: canaille/account.py:477 #: canaille/account.py:474
msgid "Profile edition failed." msgid "Profile edition failed."
msgstr "" msgstr ""
#: canaille/account.py:513 #: canaille/account.py:508
msgid "Profile updated successfuly." msgid "Profile updated successfuly."
msgstr "" msgstr ""
#: canaille/account.py:536 #: canaille/account.py:531
#, python-format #, python-format
msgid "The user %(user)s has been sucessfuly deleted" msgid "The user %(user)s has been sucessfuly deleted"
msgstr "" msgstr ""
#: canaille/account.py:566 #: canaille/account.py:561
msgid "Could not send the password reset link." msgid "Could not send the password reset link."
msgstr "" msgstr ""
#: canaille/account.py:570 #: canaille/account.py:565
msgid "" msgid ""
"A password reset link has been sent at your email address. You should " "A password reset link has been sent at your email address. You should "
"receive it within a few minutes." "receive it within a few minutes."
msgstr "" msgstr ""
#: canaille/account.py:581 #: canaille/account.py:576
#, python-format #, python-format
msgid "" msgid ""
"The user '%(user)s' does not have permissions to update their password. " "The user '%(user)s' does not have permissions to update their password. "
"We cannot send a password reset email." "We cannot send a password reset email."
msgstr "" msgstr ""
#: canaille/account.py:596 #: canaille/account.py:591
msgid "We encountered an issue while we sent the password recovery email." msgid "We encountered an issue while we sent the password recovery email."
msgstr "" msgstr ""
#: canaille/account.py:615 #: canaille/account.py:610
msgid "The password reset link that brought you here was invalid." msgid "The password reset link that brought you here was invalid."
msgstr "" msgstr ""
#: canaille/account.py:624 #: canaille/account.py:619
msgid "Your password has been updated successfuly" msgid "Your password has been updated successfuly"
msgstr "" msgstr ""
@ -396,19 +396,19 @@ msgstr ""
msgid "The access has been revoked" msgid "The access has been revoked"
msgstr "" msgstr ""
#: canaille/oidc/endpoints.py:129 #: canaille/oidc/endpoints.py:130
msgid "You have been successfully logged out." msgid "You have been successfully logged out."
msgstr "" msgstr ""
#: canaille/oidc/endpoints.py:327 #: canaille/oidc/endpoints.py:329
msgid "You have been disconnected" msgid "You have been disconnected"
msgstr "" msgstr ""
#: canaille/oidc/endpoints.py:335 #: canaille/oidc/endpoints.py:337
msgid "An error happened during the logout" msgid "An error happened during the logout"
msgstr "" msgstr ""
#: canaille/oidc/endpoints.py:347 #: canaille/oidc/endpoints.py:349
msgid "You have not been disconnected" msgid "You have not been disconnected"
msgstr "" msgstr ""
@ -432,7 +432,7 @@ msgstr ""
msgid "Grant types" msgid "Grant types"
msgstr "" msgstr ""
#: canaille/oidc/forms.py:54 canaille/templates/oidc/admin/token_view.html:33 #: canaille/oidc/forms.py:54 canaille/templates/oidc/admin/token_view.html:54
msgid "Scope" msgid "Scope"
msgstr "" msgstr ""
@ -480,12 +480,16 @@ msgstr ""
msgid "Pre-consent" msgid "Pre-consent"
msgstr "" msgstr ""
#: canaille/oidc/tokens.py:61
msgid "The token has successfully been revoked."
msgstr ""
#: canaille/oidc/utils.py:6 #: canaille/oidc/utils.py:6
msgid "Personnal information about yourself, such as your name or your gender." msgid "Info about yourself, such as your name."
msgstr "" msgstr ""
#: canaille/oidc/utils.py:8 #: canaille/oidc/utils.py:8
msgid "Your email address." msgid "Your e-mail address."
msgstr "" msgstr ""
#: canaille/oidc/utils.py:9 #: canaille/oidc/utils.py:9
@ -497,11 +501,11 @@ msgid "Your phone number."
msgstr "" msgstr ""
#: canaille/oidc/utils.py:11 #: canaille/oidc/utils.py:11
msgid "Groups you are belonging to" msgid "Groups you belong to."
msgstr "" msgstr ""
#: canaille/templates/about.html:12 canaille/themes/default/base.html:106 #: canaille/templates/about.html:12 canaille/themes/default/base.html:106
msgid "About canaille" msgid "About Canaille"
msgstr "" msgstr ""
#: canaille/templates/about.html:14 #: canaille/templates/about.html:14
@ -623,12 +627,14 @@ msgstr ""
#: canaille/templates/group.html:30 #: canaille/templates/group.html:30
#: canaille/templates/oidc/admin/client_edit.html:18 #: canaille/templates/oidc/admin/client_edit.html:18
#: canaille/templates/oidc/admin/token_view.html:21
#: canaille/templates/profile.html:41 #: canaille/templates/profile.html:41
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: canaille/templates/group.html:31 #: canaille/templates/group.html:31
#: canaille/templates/oidc/admin/client_edit.html:19 #: canaille/templates/oidc/admin/client_edit.html:19
#: canaille/templates/oidc/admin/token_view.html:22
#: canaille/templates/profile.html:42 #: canaille/templates/profile.html:42
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
@ -723,6 +729,8 @@ msgid ""
msgstr "" msgstr ""
#: canaille/templates/invite.html:58 #: canaille/templates/invite.html:58
#: canaille/templates/oidc/admin/token_view.html:104
#: canaille/templates/oidc/admin/token_view.html:114
msgid "Copy" msgid "Copy"
msgstr "" msgstr ""
@ -1039,13 +1047,13 @@ msgstr ""
#: canaille/templates/oidc/admin/authorization_list.html:19 #: canaille/templates/oidc/admin/authorization_list.html:19
#: canaille/templates/oidc/admin/token_list.html:19 #: canaille/templates/oidc/admin/token_list.html:19
#: canaille/templates/oidc/admin/token_view.html:17 #: canaille/templates/oidc/admin/token_view.html:38
msgid "Client" msgid "Client"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/authorization_list.html:20 #: canaille/templates/oidc/admin/authorization_list.html:20
#: canaille/templates/oidc/admin/token_list.html:20 #: canaille/templates/oidc/admin/token_list.html:20
#: canaille/templates/oidc/admin/token_view.html:25 #: canaille/templates/oidc/admin/token_view.html:46
msgid "Subject" msgid "Subject"
msgstr "" msgstr ""
@ -1113,35 +1121,51 @@ msgstr ""
msgid "Token" msgid "Token"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:7 #: canaille/templates/oidc/admin/token_view.html:13
msgid "View a token" msgid "Token deletion"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:13 #: canaille/templates/oidc/admin/token_view.html:17
msgid "Are you sure you want to revoke this token? This action is unrevokable."
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:28
msgid "Token details"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:34
msgid "Issue date" msgid "Issue date"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:43 #: canaille/templates/oidc/admin/token_view.html:64
msgid "Audience" msgid "Audience"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:57 #: canaille/templates/oidc/admin/token_view.html:78
msgid "Revokation date" msgid "Revokation date"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:61 #: canaille/templates/oidc/admin/token_view.html:84
msgid "Revoke token"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:86
msgid "This token has not been revoked"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:91
msgid "Lifetime" msgid "Lifetime"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:65 #: canaille/templates/oidc/admin/token_view.html:95
msgid "Token type" msgid "Token type"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:69 #: canaille/templates/oidc/admin/token_view.html:99
msgid "Access token" msgid "Access token"
msgstr "" msgstr ""
#: canaille/templates/oidc/admin/token_view.html:74 #: canaille/templates/oidc/admin/token_view.html:109
msgid "Refresh token" msgid "Refresh token"
msgstr "" msgstr ""
@ -1152,7 +1176,7 @@ msgstr ""
#: canaille/templates/oidc/user/authorize.html:32 #: canaille/templates/oidc/user/authorize.html:32
#, python-format #, python-format
msgid "You are logged id as: %(name)s" msgid "You are logged in as %(name)s"
msgstr "" msgstr ""
#: canaille/templates/oidc/user/authorize.html:39 #: canaille/templates/oidc/user/authorize.html:39

View file

@ -18,3 +18,17 @@ def test_token_view(testclient, token, logged_admin):
def test_token_not_found(testclient, logged_admin): def test_token_not_found(testclient, logged_admin):
res = testclient.get("/admin/token/" + "yolo", status=404) res = testclient.get("/admin/token/" + "yolo", status=404)
def test_revoke_token(testclient, token, logged_admin):
assert not token.revoked
res = testclient.get(f"/admin/token/{token.token_id}/revoke")
assert ("success", "The token has successfully been revoked.") in res.flashes
token.reload()
assert token.revoked
def test_revoke_invalid_token(testclient, logged_admin):
testclient.get(f"/admin/token/invalid/revoke", status=404)