# 456 Rework API key creation
* removes frontend input field holding generated API key * replaces with modal form * reworks tests on API token form
This commit is contained in:
parent
123a470006
commit
9b63307f01
@ -91,3 +91,6 @@ INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations"
|
||||
DATA_CHECKED_ON_TEMPLATE = _("Checked on {} by {}")
|
||||
DATA_CHECKED_PREVIOUSLY_TEMPLATE = _("Data has changed since last check on {} by {}")
|
||||
DATA_IS_UNCHECKED = _("Current data not checked yet")
|
||||
|
||||
# API TOKEN SETTINGS
|
||||
NEW_API_TOKEN_GENERATED = _("New token generated. Administrators need to validate.")
|
@ -5,7 +5,6 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.gis.geos import MultiPolygon
|
||||
from django.http import HttpResponse, HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
Binary file not shown.
@ -38,13 +38,14 @@
|
||||
#: konova/forms/modals/remove_form.py:23
|
||||
#: konova/forms/modals/resubmission_form.py:22
|
||||
#: konova/forms/modals/resubmission_form.py:38 konova/forms/remove_form.py:25
|
||||
#: konova/tests/unit/test_forms.py:59 user/forms/user.py:39
|
||||
#: konova/tests/unit/test_forms.py:59 user/forms/modals/api_token.py:17
|
||||
#: user/forms/user.py:39
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-19 10:32+0200\n"
|
||||
"POT-Creation-Date: 2025-01-08 15:26+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"
|
||||
@ -373,7 +374,6 @@ msgid "Identifier"
|
||||
msgstr "Kennung"
|
||||
|
||||
#: compensation/forms/compensation.py:33 intervention/forms/intervention.py:33
|
||||
#: user/forms/user.py:77
|
||||
msgid "Generated automatically - not editable"
|
||||
msgstr "Automatisch generiert - nicht bearbeitbar"
|
||||
|
||||
@ -1795,8 +1795,7 @@ msgstr "Bearbeitender Nutzer"
|
||||
msgid ""
|
||||
"Search for entries where this person has been participated according to log "
|
||||
"history"
|
||||
msgstr ""
|
||||
"Sucht nach Einträgen, an denen diese Person gearbeitet hat"
|
||||
msgstr "Sucht nach Einträgen, an denen diese Person gearbeitet hat"
|
||||
|
||||
#: konova/forms/base_form.py:23 templates/form/collapsable/form.html:62
|
||||
msgid "Save"
|
||||
@ -1858,6 +1857,7 @@ msgstr ""
|
||||
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
|
||||
|
||||
#: konova/forms/modals/remove_form.py:22 konova/forms/remove_form.py:24
|
||||
#: user/forms/modals/api_token.py:16
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätige"
|
||||
|
||||
@ -2283,6 +2283,10 @@ msgstr ""
|
||||
msgid "Current data not checked yet"
|
||||
msgstr "Momentane Daten noch nicht geprüft"
|
||||
|
||||
#: konova/utils/message_templates.py:96
|
||||
msgid "New token generated. Administrators need to validate."
|
||||
msgstr "Neuer Token generiert. Administratoren sind informiert."
|
||||
|
||||
#: konova/utils/messenger.py:70
|
||||
msgid "{} checked"
|
||||
msgstr "{} geprüft"
|
||||
@ -2321,7 +2325,7 @@ msgstr "Home"
|
||||
msgid "Log"
|
||||
msgstr "Log"
|
||||
|
||||
#: konova/views/map_proxy.py:70
|
||||
#: konova/views/map_proxy.py:84
|
||||
msgid ""
|
||||
"The external service is currently unavailable.<br>Please try again in a few "
|
||||
"moments..."
|
||||
@ -2831,10 +2835,8 @@ msgid "Reports"
|
||||
msgstr "Berichte"
|
||||
|
||||
#: templates/navbars/navbar.html:57
|
||||
#, fuzzy
|
||||
#| msgid "Admins"
|
||||
msgid "Admin"
|
||||
msgstr "Administratoren"
|
||||
msgstr ""
|
||||
|
||||
#: templates/navbars/navbar.html:59 user/templates/user/index.html:31
|
||||
msgid "Settings"
|
||||
@ -2873,6 +2875,21 @@ msgstr ""
|
||||
"Falls die Geometrie nicht leer ist, werden die Flurstücke aktuell berechnet. "
|
||||
"Bitte laden Sie diese Seite in ein paar Augenblicken erneut..."
|
||||
|
||||
#: user/forms/modals/api_token.py:25
|
||||
msgid "Generate API Token"
|
||||
msgstr "API Token generieren"
|
||||
|
||||
#: user/forms/modals/api_token.py:29
|
||||
msgid ""
|
||||
"You are about to create a new API token. The existing one will not be usable "
|
||||
"afterwards."
|
||||
msgstr ""
|
||||
"Wenn Sie fortfahren, generieren Sie einen neuen API Token. Ihren existierenden werden Sie dann nicht länger nutzen können."
|
||||
|
||||
#: user/forms/modals/api_token.py:31
|
||||
msgid "A new token needs to be validated by an administrator!"
|
||||
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
|
||||
|
||||
#: user/forms/modals/team.py:20 user/forms/modals/team.py:24
|
||||
#: user/forms/team.py:17 user/forms/team.py:22
|
||||
msgid "Team name"
|
||||
@ -2895,11 +2912,11 @@ msgstr ""
|
||||
"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, die noch nicht "
|
||||
"Mitglieder dieses Teams sind. Geben Sie den ganzen Nutzernamen an."
|
||||
|
||||
#: user/forms/modals/team.py:56 user/tests/unit/test_forms.py:31
|
||||
#: user/forms/modals/team.py:56 user/tests/unit/test_forms.py:29
|
||||
msgid "Create new team"
|
||||
msgstr "Neues Team anlegen"
|
||||
|
||||
#: user/forms/modals/team.py:57 user/tests/unit/test_forms.py:32
|
||||
#: user/forms/modals/team.py:57 user/tests/unit/test_forms.py:30
|
||||
msgid ""
|
||||
"You will become the administrator for this group by default. You do not need "
|
||||
"to add yourself to the list of members."
|
||||
@ -2928,11 +2945,11 @@ msgid "There must be at least one admin on this team."
|
||||
msgstr "Es muss mindestens einen Administrator für das Team geben."
|
||||
|
||||
#: user/forms/modals/team.py:160 user/templates/user/team/index.html:60
|
||||
#: user/tests/unit/test_forms.py:88
|
||||
#: user/tests/unit/test_forms.py:86
|
||||
msgid "Edit team"
|
||||
msgstr "Team bearbeiten"
|
||||
|
||||
#: user/forms/modals/team.py:187 user/tests/unit/test_forms.py:165
|
||||
#: user/forms/modals/team.py:187 user/tests/unit/test_forms.py:163
|
||||
msgid ""
|
||||
"ATTENTION!\n"
|
||||
"\n"
|
||||
@ -2949,7 +2966,7 @@ msgstr ""
|
||||
"Sind Sie sicher, dass Sie dieses Team löschen möchten?"
|
||||
|
||||
#: user/forms/modals/team.py:197 user/templates/user/team/index.html:56
|
||||
#: user/tests/unit/test_forms.py:198
|
||||
#: user/tests/unit/test_forms.py:196
|
||||
msgid "Leave team"
|
||||
msgstr "Team verlassen"
|
||||
|
||||
@ -2981,22 +2998,10 @@ msgstr "Benachrichtigungen"
|
||||
msgid "Select the situations when you want to receive a notification"
|
||||
msgstr "Wann wollen Sie per E-Mail benachrichtigt werden?"
|
||||
|
||||
#: user/forms/user.py:38 user/tests/unit/test_forms.py:234
|
||||
#: user/forms/user.py:38 user/tests/unit/test_forms.py:232
|
||||
msgid "Edit notifications"
|
||||
msgstr "Benachrichtigungen bearbeiten"
|
||||
|
||||
#: user/forms/user.py:73
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
|
||||
#: user/forms/user.py:88 user/tests/unit/test_forms.py:260
|
||||
msgid "Create new token"
|
||||
msgstr "Neuen Token generieren"
|
||||
|
||||
#: user/forms/user.py:89 user/tests/unit/test_forms.py:261
|
||||
msgid "A new token needs to be validated by an administrator!"
|
||||
msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
|
||||
|
||||
#: user/models/user_action.py:23
|
||||
msgid "Unrecorded"
|
||||
msgstr "Entzeichnet"
|
||||
@ -3051,7 +3056,7 @@ msgid "Manage teams"
|
||||
msgstr ""
|
||||
|
||||
#: user/templates/user/index.html:53 user/templates/user/team/index.html:19
|
||||
#: user/views/views.py:171
|
||||
#: user/views/views.py:135
|
||||
msgid "Teams"
|
||||
msgstr ""
|
||||
|
||||
@ -3087,270 +3092,58 @@ msgstr "API Einstellungen"
|
||||
msgid "Current token"
|
||||
msgstr "Aktueller Token"
|
||||
|
||||
#: user/templates/user/token.html:14
|
||||
#: user/templates/user/token.html:15
|
||||
msgid "Create new token"
|
||||
msgstr "Neuen Token generieren"
|
||||
|
||||
#: user/templates/user/token.html:23
|
||||
msgid "Authenticated by admins"
|
||||
msgstr "Von Admin freigeschaltet"
|
||||
|
||||
#: user/templates/user/token.html:18
|
||||
#: user/templates/user/token.html:27
|
||||
msgid "Token has been verified and can be used"
|
||||
msgstr "Token wurde freigeschaltet und kann verwendet werden"
|
||||
|
||||
#: user/templates/user/token.html:20
|
||||
#: user/templates/user/token.html:29
|
||||
msgid "Token waiting for verification"
|
||||
msgstr "Token noch nicht freigeschaltet"
|
||||
|
||||
#: user/templates/user/token.html:24
|
||||
#: user/templates/user/token.html:33
|
||||
msgid "Valid until"
|
||||
msgstr "Läuft ab am"
|
||||
|
||||
#: user/views/views.py:35
|
||||
msgid "User settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: user/views/views.py:61
|
||||
msgid "Notifications edited"
|
||||
msgstr "Benachrichtigungen bearbeitet"
|
||||
|
||||
#: user/views/views.py:73
|
||||
msgid "User notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
#: user/views/views.py:96
|
||||
msgid "New token generated. Administrators need to validate."
|
||||
msgstr "Neuer Token generiert. Administratoren sind informiert."
|
||||
|
||||
#: user/views/views.py:107
|
||||
#: user/views/api_token.py:33
|
||||
msgid "User API token"
|
||||
msgstr "API Nutzer Token"
|
||||
|
||||
#: user/views/views.py:183
|
||||
#: user/views/views.py:33
|
||||
msgid "User settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: user/views/views.py:59
|
||||
msgid "Notifications edited"
|
||||
msgstr "Benachrichtigungen bearbeitet"
|
||||
|
||||
#: user/views/views.py:71
|
||||
msgid "User notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
|
||||
#: user/views/views.py:147
|
||||
msgid "New team added"
|
||||
msgstr "Neues Team hinzugefügt"
|
||||
|
||||
#: user/views/views.py:198
|
||||
#: user/views/views.py:162
|
||||
msgid "Team edited"
|
||||
msgstr "Team bearbeitet"
|
||||
|
||||
#: user/views/views.py:213
|
||||
#: user/views/views.py:177
|
||||
msgid "Team removed"
|
||||
msgstr "Team gelöscht"
|
||||
|
||||
#: user/views/views.py:228
|
||||
#: user/views/views.py:192
|
||||
msgid "You are not a member of this team"
|
||||
msgstr "Sie sind kein Mitglied dieses Teams"
|
||||
|
||||
#: user/views/views.py:235
|
||||
#: user/views/views.py:199
|
||||
msgid "Left Team"
|
||||
msgstr "Team verlassen"
|
||||
|
||||
#~ msgid "close"
|
||||
#~ msgstr "Schließen"
|
||||
|
||||
#~ msgid "Options"
|
||||
#~ msgstr "Optionen"
|
||||
|
||||
#~ msgid "Commands"
|
||||
#~ msgstr "Befehle"
|
||||
|
||||
#~ msgid "Missing command."
|
||||
#~ msgstr "Befehl fehlt"
|
||||
|
||||
#~ msgid "Missing argument"
|
||||
#~ msgstr "Argument fehlt"
|
||||
|
||||
#~ msgid "Missing option"
|
||||
#~ msgstr "Option fehlt"
|
||||
|
||||
#~ msgid "Missing parameter"
|
||||
#~ msgstr "Parameter fehlt"
|
||||
|
||||
#~ msgid "Messages"
|
||||
#~ msgstr "Nachrichten"
|
||||
|
||||
#~ msgid "This field is required."
|
||||
#~ msgstr "Pflichtfeld"
|
||||
|
||||
#~ msgid "Monday"
|
||||
#~ msgstr "Montag"
|
||||
|
||||
#~ msgid "Tuesday"
|
||||
#~ msgstr "Dienstag"
|
||||
|
||||
#~ msgid "Wednesday"
|
||||
#~ msgstr "Mittwoch"
|
||||
|
||||
#~ msgid "Thursday"
|
||||
#~ msgstr "Donnerstag"
|
||||
|
||||
#~ msgid "Friday"
|
||||
#~ msgstr "Freitag"
|
||||
|
||||
#~ msgid "Saturday"
|
||||
#~ msgstr "Samstag"
|
||||
|
||||
#~ msgid "Sunday"
|
||||
#~ msgstr "Sonntag"
|
||||
|
||||
#~ msgid "Mon"
|
||||
#~ msgstr "Mo"
|
||||
|
||||
#~ msgid "Tue"
|
||||
#~ msgstr "Di"
|
||||
|
||||
#~ msgid "Wed"
|
||||
#~ msgstr "Mi"
|
||||
|
||||
#~ msgid "Thu"
|
||||
#~ msgstr "Do"
|
||||
|
||||
#~ msgid "Fri"
|
||||
#~ msgstr "Fr"
|
||||
|
||||
#~ msgid "Sat"
|
||||
#~ msgstr "Sa"
|
||||
|
||||
#~ msgid "Sun"
|
||||
#~ msgstr "So"
|
||||
|
||||
#~ msgid "January"
|
||||
#~ msgstr "Januar"
|
||||
|
||||
#~ msgid "February"
|
||||
#~ msgstr "Februar"
|
||||
|
||||
#~ msgid "March"
|
||||
#~ msgstr "März"
|
||||
|
||||
#~ msgid "May"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#~ msgid "June"
|
||||
#~ msgstr "Juni"
|
||||
|
||||
#~ msgid "July"
|
||||
#~ msgstr "Juli"
|
||||
|
||||
#~ msgid "October"
|
||||
#~ msgstr "Oktober"
|
||||
|
||||
#~ msgid "December"
|
||||
#~ msgstr "Dezember"
|
||||
|
||||
#~ msgid "mar"
|
||||
#~ msgstr "mär"
|
||||
|
||||
#~ msgid "may"
|
||||
#~ msgstr "mai"
|
||||
|
||||
#~ msgid "oct"
|
||||
#~ msgstr "okt"
|
||||
|
||||
#~ msgid "dec"
|
||||
#~ msgstr "dez"
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "March"
|
||||
#~ msgstr "Mär"
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "May"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "June"
|
||||
#~ msgstr "Juni"
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "July"
|
||||
#~ msgstr "Juli"
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "Oct."
|
||||
#~ msgstr "Okt."
|
||||
|
||||
#~ msgctxt "abbrev. month"
|
||||
#~ msgid "Dec."
|
||||
#~ msgstr "Dez."
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "January"
|
||||
#~ msgstr "Januar"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "February"
|
||||
#~ msgstr "Februar"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "March"
|
||||
#~ msgstr "März"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "May"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "June"
|
||||
#~ msgstr "Juni"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "July"
|
||||
#~ msgstr "Juli"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "October"
|
||||
#~ msgstr "Oktober"
|
||||
|
||||
#~ msgctxt "alt. month"
|
||||
#~ msgid "December"
|
||||
#~ msgstr "Dezember"
|
||||
|
||||
#~ msgid "or"
|
||||
#~ msgstr "oder"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Deductable surface can not be larger than existing surfaces in after "
|
||||
#~ "states"
|
||||
#~ msgstr ""
|
||||
#~ "Die abbuchbare Fläche darf die Gesamtfläche der Zielzustände nicht "
|
||||
#~ "überschreiten"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Deductable surface can not be smaller than the sum of already existing "
|
||||
#~ "deductions. Please contact the responsible users for the deductions!"
|
||||
#~ msgstr ""
|
||||
#~ "Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar "
|
||||
#~ "einstellen wollen. Kontaktieren Sie die für die Abbuchungen "
|
||||
#~ "verantwortlichen Nutzer!"
|
||||
|
||||
#~ msgid "Added deadline"
|
||||
#~ msgstr "Frist/Termin hinzugefügt"
|
||||
|
||||
#~ msgid "Change default configuration for your KSP map"
|
||||
#~ msgstr "Karteneinstellungen ändern"
|
||||
|
||||
#~ msgid "Map settings"
|
||||
#~ msgstr "Karte"
|
||||
|
||||
#~ msgid "There are errors on this intervention:"
|
||||
#~ msgstr "Es liegen Fehler in diesem Eingriff vor:"
|
||||
|
||||
#~ msgid "Before"
|
||||
#~ msgstr "Vor"
|
||||
|
||||
#~ msgid "Groups"
|
||||
#~ msgstr "Gruppen"
|
||||
|
||||
#~ msgid "Show more..."
|
||||
#~ msgstr "Mehr anzeigen..."
|
||||
|
||||
#~ msgid "Kreis"
|
||||
#~ msgstr "Kreis"
|
||||
|
||||
#~ msgid "Gemarkung"
|
||||
#~ msgstr "Gemarkung"
|
||||
|
||||
#~ msgid "Loading..."
|
||||
#~ msgstr "Lade..."
|
||||
|
||||
#~ msgid "Who handles the eco-account"
|
||||
#~ msgstr "Wer für die Herrichtung des Ökokontos verantwortlich ist"
|
||||
|
49
user/forms/modals/api_token.py
Normal file
49
user/forms/modals/api_token.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 08.01.25
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from api.models import APIUserToken
|
||||
from konova.forms.modals import BaseModalForm
|
||||
from konova.utils.mailer import Mailer
|
||||
|
||||
|
||||
class NewAPITokenModalForm(BaseModalForm):
|
||||
confirm = forms.BooleanField(
|
||||
label=_("Confirm"),
|
||||
label_suffix=_(""),
|
||||
widget=forms.CheckboxInput(),
|
||||
required=True,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.template = "modal/modal_form.html"
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Generate API Token")
|
||||
|
||||
self.form_caption = ""
|
||||
if self.__user_has_api_token():
|
||||
self.form_caption = _("You are about to create a new API token. The existing one will not be usable afterwards.")
|
||||
self.form_caption += "\n"
|
||||
self.form_caption += _("A new token needs to be validated by an administrator!")
|
||||
# Disable automatic w-100 setting for this type of modal form. Looks kinda strange
|
||||
self.fields["confirm"].widget.attrs["class"] = ""
|
||||
|
||||
def __user_has_api_token(self):
|
||||
return self.instance.api_token is not None
|
||||
|
||||
def save(self):
|
||||
user = self.instance
|
||||
if user.api_token is not None:
|
||||
user.api_token.delete()
|
||||
user.api_token = APIUserToken.objects.create()
|
||||
user.save()
|
||||
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_verify_api_token(user)
|
||||
|
||||
return user.api_token
|
||||
|
@ -66,48 +66,3 @@ class UserNotificationForm(BaseForm):
|
||||
id__in=selected_notification_ids,
|
||||
)
|
||||
self.user.notifications.set(notifications)
|
||||
|
||||
|
||||
class UserAPITokenForm(BaseForm):
|
||||
token = forms.CharField(
|
||||
label=_("Token"),
|
||||
label_suffix="",
|
||||
max_length=255,
|
||||
required=True,
|
||||
help_text=_("Generated automatically - not editable"),
|
||||
widget=GenerateInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"url": reverse_lazy("api:generate-new-token"),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Create new token")
|
||||
self.form_caption = _("A new token needs to be validated by an administrator!")
|
||||
|
||||
self.action_url = reverse("user:api-token")
|
||||
self.cancel_redirect = reverse("user:index")
|
||||
|
||||
# Make direct token editing by user impossible. Instead set the proper url for generating a new token
|
||||
self.initialize_form_field("token", None)
|
||||
self.fields["token"].widget.attrs["readonly"] = True
|
||||
|
||||
def save(self):
|
||||
""" Saves the form data
|
||||
|
||||
Returns:
|
||||
api_token (APIUserToken)
|
||||
"""
|
||||
user = self.instance
|
||||
new_token = self.cleaned_data["token"]
|
||||
if user.api_token is not None:
|
||||
user.api_token.delete()
|
||||
new_token = APIUserToken.objects.create(
|
||||
token=new_token
|
||||
)
|
||||
user.api_token = new_token
|
||||
user.save()
|
||||
return new_token
|
@ -8,7 +8,16 @@
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Current token' %}</th>
|
||||
<td>{{ user.api_token.token }}</td>
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-10">{{ user.api_token.token }}</div>
|
||||
<div class="col-2">
|
||||
<button class="btn btn-default btn-modal" data-form-url="{% url 'user:api-token-new' %}" title="{% trans 'Create new token' %}">
|
||||
{% fa5_icon 'dice' %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Authenticated by admins' %}</th>
|
||||
@ -27,7 +36,9 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{% include 'form/table/generic_table_form.html' %}
|
||||
|
||||
|
||||
{% with 'btn-modal' as btn_class %}
|
||||
{% include 'modal/modal_form_script.html' %}
|
||||
{% endwith %}
|
||||
|
||||
{% endblock %}
|
@ -5,15 +5,14 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 12.09.23
|
||||
|
||||
"""
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.test import RequestFactory
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from api.models import APIUserToken
|
||||
from konova.tests.test_views import BaseTestCase
|
||||
from user.forms.modals.api_token import NewAPITokenModalForm
|
||||
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
|
||||
from user.forms.user import UserNotificationForm, UserAPITokenForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import Team, UserAction, UserNotification
|
||||
|
||||
|
||||
@ -252,35 +251,28 @@ class UserNotificationFormTestCase(BaseTestCase):
|
||||
self.assertIn(selected_notification, self.user.notifications.all())
|
||||
|
||||
|
||||
class UserAPITokenFormTestCase(BaseTestCase):
|
||||
def test_init(self):
|
||||
form = UserAPITokenForm(
|
||||
instance=self.user
|
||||
)
|
||||
self.assertEqual(form.form_title, str(_("Create new token")))
|
||||
self.assertEqual(form.form_caption, str(_("A new token needs to be validated by an administrator!")))
|
||||
self.assertEqual(form.action_url, reverse("user:api-token"))
|
||||
self.assertEqual(form.cancel_redirect, reverse("user:index"))
|
||||
|
||||
self.assertIsNone(form.fields["token"].initial)
|
||||
self.assertTrue(form.fields["token"].widget.attrs["readonly"])
|
||||
|
||||
def test_save(self):
|
||||
data = {
|
||||
"token": APIUserToken().token
|
||||
class ApiTokenFormTestCase(BaseTestCase):
|
||||
def test_new_token_and_recreating_token(self):
|
||||
request = RequestFactory().request()
|
||||
request.user = self.user
|
||||
request.POST = {
|
||||
"confirm": True
|
||||
}
|
||||
form = UserAPITokenForm(
|
||||
data,
|
||||
instance=self.user
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
|
||||
self.assertIsNone(self.user.api_token)
|
||||
token = form.save()
|
||||
self.assertEqual(self.user.api_token, token)
|
||||
new_token = form.save()
|
||||
self.assertEqual(self.user.api_token, new_token)
|
||||
try:
|
||||
token.refresh_from_db()
|
||||
self.fail("Token should be deleted and not be fetchable anymore")
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
form = NewAPITokenModalForm(request.POST, instance=self.user)
|
||||
form.save()
|
||||
self.user.refresh_from_db()
|
||||
token = self.user.api_token
|
||||
self.assertFalse(token.is_active)
|
||||
self.assertIsNone(token.valid_until)
|
||||
self.assertIsNotNone(token.token)
|
||||
|
||||
old_token = token.token
|
||||
form.save()
|
||||
self.user.refresh_from_db()
|
||||
new_token = self.user.api_token
|
||||
self.assertNotEqual(new_token.token, old_token)
|
||||
self.assertFalse(new_token.is_active)
|
||||
self.assertIsNone(new_token.valid_until)
|
||||
|
||||
|
@ -9,6 +9,7 @@ from django.urls import path
|
||||
|
||||
from user.autocomplete.share import ShareUserAutocomplete, ShareTeamAutocomplete
|
||||
from user.autocomplete.team import TeamAdminAutocomplete
|
||||
from user.views.api_token import APITokenView, new_api_token_view
|
||||
from user.views.propagate import PropagateUserView
|
||||
from user.views.views import *
|
||||
|
||||
@ -17,7 +18,8 @@ urlpatterns = [
|
||||
path("", index_view, name="index"),
|
||||
path("propagate/", PropagateUserView.as_view(), name="propagate"),
|
||||
path("notifications/", notifications_view, name="notifications"),
|
||||
path("token/api", api_token_view, name="api-token"),
|
||||
path("token/api", APITokenView.as_view(), name="api-token"),
|
||||
path("token/api/new", new_api_token_view, name="api-token-new"),
|
||||
path("contact/<id>", contact_view, name="contact"),
|
||||
path("team/", index_team_view, name="team-index"),
|
||||
path("team/new", new_team_view, name="team-new"),
|
||||
@ -30,4 +32,4 @@ urlpatterns = [
|
||||
path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"),
|
||||
path("atcmplt/share/t", ShareTeamAutocomplete.as_view(), name="share-team-autocomplete"),
|
||||
path("atcmplt/team/admin", TeamAdminAutocomplete.as_view(), name="team-admin-autocomplete"),
|
||||
]
|
||||
]
|
||||
|
57
user/views/api_token.py
Normal file
57
user/views/api_token.py
Normal file
@ -0,0 +1,57 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 08.01.25
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import default_group_required
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import NEW_API_TOKEN_GENERATED
|
||||
from user.forms.modals.api_token import NewAPITokenModalForm
|
||||
|
||||
|
||||
class APITokenView(View):
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
template = "user/token.html"
|
||||
user = request.user
|
||||
|
||||
context = {
|
||||
"user": user,
|
||||
TAB_TITLE_IDENTIFIER: _("User API token"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
def new_api_token_view(request: HttpRequest):
|
||||
""" Function based view for processing ModalForm
|
||||
(Currently ModalForms only work properly with function based views)
|
||||
|
||||
Args:
|
||||
request ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
user = request.user
|
||||
|
||||
form = NewAPITokenModalForm(request.POST or None, instance=user, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=NEW_API_TOKEN_GENERATED,
|
||||
redirect_url=reverse("user:api-token"),
|
||||
)
|
@ -3,19 +3,17 @@ from django.contrib.auth.decorators import login_required
|
||||
from django.urls import reverse
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.mailer import Mailer
|
||||
from konova.utils.message_templates import FORM_INVALID
|
||||
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
|
||||
from user.forms.modals.user import UserContactForm
|
||||
from user.forms.team import TeamDataForm
|
||||
from user.forms.user import UserNotificationForm, UserAPITokenForm
|
||||
from user.forms.user import UserNotificationForm
|
||||
from user.models import User, Team
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import any_group_check, default_group_required, login_required_modal
|
||||
from konova.decorators import any_group_check, login_required_modal
|
||||
|
||||
|
||||
@login_required
|
||||
@ -76,40 +74,6 @@ def notifications_view(request: HttpRequest):
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
def api_token_view(request: HttpRequest):
|
||||
""" Handles the request for user api frontend settings
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "user/token.html"
|
||||
user = request.user
|
||||
form = UserAPITokenForm(request.POST or None, instance=user)
|
||||
if request.method == "POST":
|
||||
if form.is_valid():
|
||||
token = form.save()
|
||||
messages.info(request, _("New token generated. Administrators need to validate."))
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_verify_api_token(user)
|
||||
return redirect("user:api-token")
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger")
|
||||
elif request.method != "GET":
|
||||
raise NotImplementedError
|
||||
context = {
|
||||
"user": user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: _("User API token"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
def contact_view(request: HttpRequest, id: str):
|
||||
|
Loading…
Reference in New Issue
Block a user