Skip to content
Snippets Groups Projects
Verified Commit acf45391 authored by Frank Sauerburger's avatar Frank Sauerburger
Browse files

Use advanced token auth

parent a50e6c72
No related branches found
No related tags found
1 merge request!3Resolve "Augment user object and OIDC"
Showing
with 246 additions and 10 deletions
from django.contrib import admin
from .models import Token
admin.site.register(Token)
from rest_framework import exceptions
from rest_framework.authentication import TokenAuthentication
from django.utils.translation import gettext_lazy as _
from .models import Token
class ApiTokenAuthentication(TokenAuthentication):
model = Token
def authenticate_credentials(self, key):
"""Authenticate a token"""
user, token = super().authenticate_credentials(key)
if token.expired():
msg = _("API Token expired")
raise exceptions.AuthenticationFailed(msg)
return user, token
# Generated by Django 3.1.3 on 2020-11-15 22:38
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Token',
fields=[
('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='api_tokens', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'Token',
'verbose_name_plural': 'Tokens',
},
),
]
# Generated by Django 3.1.3 on 2020-11-16 22:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uhepp_api', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='token',
name='description',
field=models.CharField(default='', max_length=100, verbose_name='Description'),
preserve_default=False,
),
migrations.AddField(
model_name='token',
name='expries',
field=models.DateTimeField(blank=True, null=True, verbose_name='Expires'),
),
]
# Generated by Django 3.1.3 on 2020-11-16 22:40
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('uhepp_api', '0002_auto_20201116_2236'),
]
operations = [
migrations.RenameField(
model_name='token',
old_name='expries',
new_name='expires',
),
]
import binascii
import os
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now
class Token(models.Model):
"""
The default authorization token model.
"""
key = models.CharField(_("Key"), max_length=40, primary_key=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL, related_name='api_tokens',
on_delete=models.CASCADE, verbose_name=_("User")
)
created = models.DateTimeField(_("Created"), auto_now_add=True)
expires = models.DateTimeField(_("Expires"), null=True, blank=True)
description = models.CharField(_("Description"), max_length=100)
def expired(self):
return self.expires and self.expires < now()
class Meta:
verbose_name = _("Token")
verbose_name_plural = _("Tokens")
def save(self, *args, **kwargs):
if not self.key:
self.key = self.generate_key()
return super().save(*args, **kwargs)
@classmethod
def generate_key(cls):
return binascii.hexlify(os.urandom(20)).decode()
def __str__(self):
return self.key
......@@ -21,9 +21,16 @@ class CreateModelMixin:
return obj
def get_success_headers(self, obj):
rel_url = reverse('uhepp_api:plot-detail', args=[obj.uuid])
url = self.request.build_absolute_uri(rel_url)
return {'Location': url}
api_url = reverse('uhepp_api:plot-detail', args=[obj.uuid])
api_url = self.request.build_absolute_uri(api_url)
ui_url = reverse('uhepp_vault:plot-detail', args=[obj.uuid])
ui_url = self.request.build_absolute_uri(ui_url)
return {
'Location': api_url,
'Link': f'<{ui_url}>; rel="ui"',
'X-Resource-UUID': obj.uuid,
}
class PlotSet(CreateModelMixin,
viewsets.mixins.RetrieveModelMixin,
......
......@@ -64,7 +64,7 @@ AUTHENTICATION_BACKENDS = [
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'uhepp_api.auth.ApiTokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
......
from django import forms
class TokenForm(forms.Form):
description = forms.CharField(label='Description', max_length=100)
# Generated by Django 3.1.3 on 2020-11-15 20:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('authtoken', '0002_auto_20160226_1747'),
('uhepp_vault', '0002_auto_20201114_1222'),
]
operations = [
migrations.CreateModel(
name='TokenInfo',
fields=[
('token', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='authtoken.token')),
('description', models.TextField(max_length=100)),
],
),
]
# Generated by Django 3.1.3 on 2020-11-15 22:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uhepp_api', '__first__'),
('uhepp_vault', '0003_tokeninfo'),
]
operations = [
migrations.AlterField(
model_name='tokeninfo',
name='token',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='uhepp_api.token'),
),
]
# Generated by Django 3.1.3 on 2020-11-16 22:36
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('uhepp_vault', '0004_auto_20201115_2236'),
]
operations = [
migrations.DeleteModel(
name='TokenInfo',
),
]
from django.db import models
from uhepp_api.models import Token
import uuid
class Plot(models.Model):
......
......@@ -2,9 +2,22 @@
{% if tokens %}
<ul>
{% for token in tokens %}
<li>{{ token.created }}: {{ token.key }}</li>
<li>
Created: {{ token.created }}<br />
{% if token.expires %}
{% if token.expired %}
<b>Expired</b>: {{ token.expires }}<br />
{% else %}
Expires: {{ token.expires }}<br />
{% endif %}
{% endif %}
{{ token.key }} ({{ token.description }})</li>
{% endfor %}
</ul>
{% else %}
<p>You don't have any tokens.</p>
{% endif %}
<form method="post"> {% csrf_token %}
{{ token_form }}
</form>
......@@ -7,9 +7,9 @@ app_name = 'uhepp_vault'
urlpatterns = [
path('', views.home, name='home'),
path('p/', views.PlotIndex.as_view(), name='plot-index'),
path('tokens/', views.token_index, name='token-index'),
path('accounts/', views.account, name='account'),
path('accounts/login/', auth_views.LoginView.as_view()),
path('accounts/tokens/', views.token_index, name='token-index'),
path('p/<str:pk>/', views.PlotDetail.as_view(), name='plot-detail'),
path('p/<str:uuid>/json', views.plot_detail_json, name='plot-detail-json'),
]
from django.shortcuts import render
from django.views import generic
from django.http import JsonResponse
from django.http import JsonResponse, HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from uhepp_api.models import Token
from .models import Plot
from .forms import TokenForm
class PlotIndex(generic.ListView):
template_name = 'uhepp_vault/plots.html'
......@@ -31,18 +33,33 @@ def home(request):
@login_required
def token_index(request):
if request.method == "POST":
form = TokenForm(request.POST)
if form.is_valid():
form_data = form.clean()
new_token = Token.objects.create(user=request.user,
description=form_data["description"])
return HttpResponseRedirect(request.get_full_path())
else:
form = TokenForm()
token_list = Token.objects.filter(user=request.user)
context = {
'user': request.user,
'tokens': Token.objects.filter(user=request.user)
'tokens': token_list,
'token_form': form,
}
return render(request, "uhepp_vault/token.html", context=context)
@login_required
def account(request):
context = {
'user': request.user,
}
return render(request, "uhepp_vault/account.html", context=context)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment