Merge branch 'admin-token-deletion' into 'main'

Implements admin token deletion

See merge request yaal/canaille!100
This commit is contained in:
Éloi Rivard 2023-02-04 17:53:20 +00:00
commit 6bb989c21e
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.models import User
from canaille.oidc.models import Client
from canaille.oidc.models import Token
from flask import abort
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
@ -40,3 +46,18 @@ def view(user, token_id):
token_audience=token_audience,
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 %}
{% block script %}
<script src="/static/js/confirm.js"></script>
<script src="/static/js/copy.js"></script>
{% endblock %}
{% 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">
<h3 class="ui top attached header">
{% trans %}View a token{% endtrans %}
{% trans %}Token details{% endtrans %}
</h3>
<div class="ui attached clearing segment">
@ -59,7 +76,18 @@
</tr>
<tr>
<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>
<td>{{ _("Lifetime") }}</td>

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\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"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,7 +18,7 @@ msgstr ""
"Generated-By: Babel 2.11.0\n"
#: 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"
msgstr ""
@ -42,7 +42,7 @@ msgid ""
"should receive it within a few minutes."
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"
msgstr ""
@ -76,65 +76,65 @@ msgstr ""
msgid "You account has been created successfuly."
msgstr ""
#: canaille/account.py:393
#: canaille/account.py:390
msgid "User account creation succeed."
msgstr ""
#: canaille/account.py:420
#: canaille/account.py:417
msgid ""
"A password initialization link has been sent at the user email address. "
"It should be received within a few minutes."
msgstr ""
#: canaille/account.py:437
#: canaille/account.py:434
msgid ""
"A password reset link has been sent at the user email address. It should "
"be received within a few minutes."
msgstr ""
#: canaille/account.py:443
#: canaille/account.py:440
msgid "Could not send the password reset email"
msgstr ""
#: canaille/account.py:477
#: canaille/account.py:474
msgid "Profile edition failed."
msgstr ""
#: canaille/account.py:513
#: canaille/account.py:508
msgid "Profile updated successfuly."
msgstr ""
#: canaille/account.py:536
#: canaille/account.py:531
#, python-format
msgid "The user %(user)s has been sucessfuly deleted"
msgstr ""
#: canaille/account.py:566
#: canaille/account.py:561
msgid "Could not send the password reset link."
msgstr ""
#: canaille/account.py:570
#: canaille/account.py:565
msgid ""
"A password reset link has been sent at your email address. You should "
"receive it within a few minutes."
msgstr ""
#: canaille/account.py:581
#: canaille/account.py:576
#, python-format
msgid ""
"The user '%(user)s' does not have permissions to update their password. "
"We cannot send a password reset email."
msgstr ""
#: canaille/account.py:596
#: canaille/account.py:591
msgid "We encountered an issue while we sent the password recovery email."
msgstr ""
#: canaille/account.py:615
#: canaille/account.py:610
msgid "The password reset link that brought you here was invalid."
msgstr ""
#: canaille/account.py:624
#: canaille/account.py:619
msgid "Your password has been updated successfuly"
msgstr ""
@ -396,19 +396,19 @@ msgstr ""
msgid "The access has been revoked"
msgstr ""
#: canaille/oidc/endpoints.py:129
#: canaille/oidc/endpoints.py:130
msgid "You have been successfully logged out."
msgstr ""
#: canaille/oidc/endpoints.py:327
#: canaille/oidc/endpoints.py:329
msgid "You have been disconnected"
msgstr ""
#: canaille/oidc/endpoints.py:335
#: canaille/oidc/endpoints.py:337
msgid "An error happened during the logout"
msgstr ""
#: canaille/oidc/endpoints.py:347
#: canaille/oidc/endpoints.py:349
msgid "You have not been disconnected"
msgstr ""
@ -432,7 +432,7 @@ msgstr ""
msgid "Grant types"
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"
msgstr ""
@ -480,12 +480,16 @@ msgstr ""
msgid "Pre-consent"
msgstr ""
#: canaille/oidc/tokens.py:61
msgid "The token has successfully been revoked."
msgstr ""
#: 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 ""
#: canaille/oidc/utils.py:8
msgid "Your email address."
msgid "Your e-mail address."
msgstr ""
#: canaille/oidc/utils.py:9
@ -497,11 +501,11 @@ msgid "Your phone number."
msgstr ""
#: canaille/oidc/utils.py:11
msgid "Groups you are belonging to"
msgid "Groups you belong to."
msgstr ""
#: canaille/templates/about.html:12 canaille/themes/default/base.html:106
msgid "About canaille"
msgid "About Canaille"
msgstr ""
#: canaille/templates/about.html:14
@ -623,12 +627,14 @@ msgstr ""
#: canaille/templates/group.html:30
#: canaille/templates/oidc/admin/client_edit.html:18
#: canaille/templates/oidc/admin/token_view.html:21
#: canaille/templates/profile.html:41
msgid "Cancel"
msgstr ""
#: canaille/templates/group.html:31
#: canaille/templates/oidc/admin/client_edit.html:19
#: canaille/templates/oidc/admin/token_view.html:22
#: canaille/templates/profile.html:42
msgid "Delete"
msgstr ""
@ -723,6 +729,8 @@ msgid ""
msgstr ""
#: canaille/templates/invite.html:58
#: canaille/templates/oidc/admin/token_view.html:104
#: canaille/templates/oidc/admin/token_view.html:114
msgid "Copy"
msgstr ""
@ -1039,13 +1047,13 @@ msgstr ""
#: canaille/templates/oidc/admin/authorization_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"
msgstr ""
#: canaille/templates/oidc/admin/authorization_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"
msgstr ""
@ -1113,35 +1121,51 @@ msgstr ""
msgid "Token"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:7
msgid "View a token"
#: canaille/templates/oidc/admin/token_view.html:13
msgid "Token deletion"
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"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:43
#: canaille/templates/oidc/admin/token_view.html:64
msgid "Audience"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:57
#: canaille/templates/oidc/admin/token_view.html:78
msgid "Revokation date"
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"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:65
#: canaille/templates/oidc/admin/token_view.html:95
msgid "Token type"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:69
#: canaille/templates/oidc/admin/token_view.html:99
msgid "Access token"
msgstr ""
#: canaille/templates/oidc/admin/token_view.html:74
#: canaille/templates/oidc/admin/token_view.html:109
msgid "Refresh token"
msgstr ""
@ -1152,7 +1176,7 @@ msgstr ""
#: canaille/templates/oidc/user/authorize.html:32
#, python-format
msgid "You are logged id as: %(name)s"
msgid "You are logged in as %(name)s"
msgstr ""
#: 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):
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)