#31 API Frontend token generating
* adds frontend settings for users to create API tokens on their user settings
This commit is contained in:
@@ -6,8 +6,12 @@ Created on: 08.07.21
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.urls import reverse
|
||||
from django.db import IntegrityError
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from api.models import APIUserToken
|
||||
from intervention.inputs import GenerateInput
|
||||
from user.models import User
|
||||
|
||||
from konova.forms import BaseForm, BaseModalForm
|
||||
@@ -113,3 +117,45 @@ class UserContactForm(BaseModalForm):
|
||||
self.initialize_form_field("mail", self.instance.email)
|
||||
|
||||
|
||||
class UserAPITokenForm(BaseForm):
|
||||
token = forms.CharField(
|
||||
label=_("Token"),
|
||||
label_suffix="",
|
||||
max_length=255,
|
||||
required=True,
|
||||
help_text=_("Generated automatically"),
|
||||
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"]
|
||||
user.api_token.delete()
|
||||
new_token = APIUserToken.objects.create(
|
||||
token=new_token
|
||||
)
|
||||
user.api_token = new_token
|
||||
user.save()
|
||||
return new_token
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.contrib.auth.models import AbstractUser
|
||||
|
||||
from django.db import models
|
||||
|
||||
from api.models import APIUserToken
|
||||
from konova.settings import ZB_GROUP, DEFAULT_GROUP, ETS_GROUP
|
||||
from konova.utils.mailer import Mailer
|
||||
from user.enums import UserNotificationEnum
|
||||
@@ -142,3 +143,19 @@ class User(AbstractUser):
|
||||
if notification_set:
|
||||
mailer = Mailer()
|
||||
mailer.send_mail_shared_data_checked(obj_identifier, self)
|
||||
|
||||
def get_API_token(self):
|
||||
""" Getter for an API token
|
||||
|
||||
Creates a new one if none exists, yet.
|
||||
|
||||
Returns:
|
||||
token (APIUserToken)
|
||||
"""
|
||||
if self.api_token is None:
|
||||
token = APIUserToken.objects.create()
|
||||
self.api_token = token
|
||||
self.save()
|
||||
else:
|
||||
token = self.api_token
|
||||
return token
|
||||
|
||||
@@ -54,6 +54,14 @@
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<a href="{% url 'user:api-token' %}" title="{% trans 'See or edit your API token' %}">
|
||||
<button class="btn btn-default">
|
||||
{% fa5_icon 'code' %}
|
||||
<span>{% trans 'API' %}</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
31
user/templates/user/token.html
Normal file
31
user/templates/user/token.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n fontawesome_5 %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container">
|
||||
<h3>{% trans 'API settings' %}</h3>
|
||||
<div class="table-container">
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Current token' %}</th>
|
||||
<td>{{ user.api_token.token }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Authenticated by admins' %}</th>
|
||||
{% if user.api_token.is_active %}
|
||||
<td class="text-success" title="{% trans 'Token has been verified and can be used' %}">{% fa5_icon 'check-circle' %}</td>
|
||||
{% else %}
|
||||
<td class="text-primary" title="{% trans 'Token waiting for verification' %}">{% fa5_icon 'hourglass-half' %}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans 'Valid until' %}</th>
|
||||
<td>{{ user.api_token.valid_until|default_if_none:"-" }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{% include 'form/table/generic_table_form.html' %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -13,6 +13,7 @@ app_name = "user"
|
||||
urlpatterns = [
|
||||
path("", index_view, name="index"),
|
||||
path("notifications/", notifications_view, name="notifications"),
|
||||
path("token/api", api_token_view, name="api-token"),
|
||||
path("contact/<id>", contact_view, name="contact"),
|
||||
|
||||
]
|
||||
@@ -2,14 +2,15 @@ from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import FORM_INVALID
|
||||
from user.models import User
|
||||
from django.http import HttpRequest
|
||||
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
|
||||
from user.forms import UserNotificationForm, UserContactForm
|
||||
from konova.decorators import any_group_check, default_group_required
|
||||
from user.forms import UserNotificationForm, UserContactForm, UserAPITokenForm
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -70,6 +71,37 @@ 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"
|
||||
form = UserAPITokenForm(request.POST or None, instance=request.user)
|
||||
if request.method == "POST":
|
||||
if form.is_valid():
|
||||
token = form.save()
|
||||
messages.info(request, _("New token generated. Administrators need to validate."))
|
||||
return redirect("user:api-token")
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger")
|
||||
elif request.method != "GET":
|
||||
raise NotImplementedError
|
||||
context = {
|
||||
"user": request.user,
|
||||
"form": form,
|
||||
TAB_TITLE_IDENTIFIER: _("User API token"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
def contact_view(request: HttpRequest, id: str):
|
||||
""" Renders contact modal view of a users contact data
|
||||
|
||||
Reference in New Issue
Block a user