create and show access qr code

This commit is contained in:
Laura Klünder 2017-12-10 03:49:21 +01:00
parent cca01e584a
commit 2a175aa43d
6 changed files with 98 additions and 4 deletions

View file

@ -0,0 +1,9 @@
{% extends 'control/base.html' %}
{% load i18n %}
{% block heading %}{% trans 'Access Permissions' %}{% endblock %}
{% block subcontent %}
{% trans 'Generate QR Code' as button_label %}
{% include 'control/fragment_access_permissions_form.html' with button_label=button_label %}
{% endblock %}

View file

@ -0,0 +1,25 @@
{% extends 'control/base.html' %}
{% load i18n %}
{% block heading %}{% trans 'Access Permission QR Code' %}{% endblock %}
{% block addattributes %} style="text-align: center;"{% endblock %}
{% block menu %}{% endblock %}
{% block subcontent %}
<p>
{% trans 'Scan this QR code to get access permissions:' %}
</p>
<p>
<img src="/qr/access/{{ token }}">
</p>
<p>
{{ absolute_url }}
</p>
<p>
<a href="{% url 'control.access' %}">« {% trans 'back' %}</a>
</p>
<script type="text/javascript">
window.setTimeout(function() { window.location.reload(); }, 3000);
</script>
{% endblock %}

View file

@ -6,15 +6,18 @@
{% block header_title_url %}{% url 'control.index' %}{% endblock %} {% block header_title_url %}{% url 'control.index' %}{% endblock %}
{% block content %} {% block content %}
<main class="control"> <main class="control"{% block addattributes %}{% endblock %}>
{% include 'site/fragment_messages.html' %} {% include 'site/fragment_messages.html' %}
<h2>{% block heading %}{% endblock %}</h2> <h2>{% block heading %}{% endblock %}</h2>
{% block menu %}
<nav> <nav>
<p> <p>
<a href="{% url 'control.index' %}">{% trans 'Overview' %}</a> &middot; <a href="{% url 'control.index' %}">{% trans 'Overview' %}</a> &middot;
<a href="{% url 'control.users' %}">{% trans 'Users' %}</a> <a href="{% url 'control.users' %}">{% trans 'Users' %}</a> &middot;
<a href="{% url 'control.access' %}">{% trans 'Access' %}</a>
</p> </p>
</nav> </nav>
{% endblock %}
{% block subcontent %} {% block subcontent %}
{% endblock %} {% endblock %}
</main> </main>

View file

@ -1,9 +1,11 @@
from django.conf.urls import url from django.conf.urls import url
from c3nav.control.views import main_index, user_detail, user_list from c3nav.control.views import grant_access, grant_access_qr, main_index, user_detail, user_list
urlpatterns = [ urlpatterns = [
url(r'^users/$', user_list, name='control.users'), url(r'^users/$', user_list, name='control.users'),
url(r'^users/(?P<user>\d+)/$', user_detail, name='control.users.detail'), url(r'^users/(?P<user>\d+)/$', user_detail, name='control.users.detail'),
url(r'^access/$', grant_access, name='control.access'),
url(r'^access/qr/(?P<token>[^/]+)', grant_access_qr, name='control.access.qr'),
url(r'^$', main_index, name='control.index'), url(r'^$', main_index, name='control.index'),
] ]

View file

@ -5,13 +5,15 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.db import transaction
from django.db.models import Prefetch from django.db.models import Prefetch
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from c3nav.control.forms import AccessPermissionForm, UserPermissionsForm from c3nav.control.forms import AccessPermissionForm, UserPermissionsForm
from c3nav.control.models import UserPermissions from c3nav.control.models import UserPermissions
from c3nav.mapdata.models.access import AccessPermission from c3nav.mapdata.models.access import AccessPermission, AccessPermissionToken
def control_panel_view(func): def control_panel_view(func):
@ -112,3 +114,53 @@ def user_detail(request, user):
}) })
return render(request, 'control/user.html', ctx) return render(request, 'control/user.html', ctx)
@login_required
@control_panel_view
def grant_access(request):
if request.method == 'POST' and request.POST.get('submit_access_permissions'):
form = AccessPermissionForm(request=request, data=request.POST)
if form.is_valid():
token = form.get_token()
token.save()
return redirect(reverse('control.access.qr', kwargs={'token': token.id}))
else:
form = AccessPermissionForm(request=request)
ctx = {
'access_permission_form': form
}
return render(request, 'control/access.html', ctx)
@login_required
@control_panel_view
def grant_access_qr(request, token):
with transaction.atomic():
token = AccessPermissionToken.objects.select_for_update().get(id=token, author=request.user)
if token.redeemed:
messages.success(_('Access successfully granted!'))
token = None
elif not token.unlimited:
try:
latest = AccessPermissionToken.objects.filter(author=request.user).latest('valid_until')
except AccessPermissionToken.DoesNotExist:
token = None
else:
if latest.id != token.id:
token = None
if token is None:
messages.error(_('You can only display your most recently created token.'))
if token is None:
redirect('control.access')
token.bump()
token.save()
return render(request, 'control/access_qr.html', {
'token': token.id,
'absolute_url': request.build_absolute_uri('/access/qr/%s' % token.id)
})

View file

@ -78,6 +78,9 @@ class AccessPermissionToken(models.Model):
if self.pk: if self.pk:
self.save() self.save()
def bump(self):
self.valid_until = default_valid_until()
class AccessPermission(models.Model): class AccessPermission(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)