From d5bbbd4ee45b607a3cd31d2ab2f273c29c05ae50 Mon Sep 17 00:00:00 2001 From: Paul Konstantin Gerke Date: Wed, 24 Aug 2022 22:20:08 +0200 Subject: [PATCH] Add login QR-code to settings-page --- Pipfile | 1 + babybuddy/models.py | 20 +++++++++++++++++++ .../babybuddy/user_settings_form.html | 8 +++++++- babybuddy/views.py | 14 ++++++++++++- requirements.txt | 1 + 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Pipfile b/Pipfile index 0afc37d2..3bfe5209 100644 --- a/Pipfile +++ b/Pipfile @@ -23,6 +23,7 @@ pyyaml = "*" uritemplate = "*" whitenoise = "*" django-taggit = "*" +qrcode = "*" [dev-packages] coveralls = "*" diff --git a/babybuddy/models.py b/babybuddy/models.py index be565050..7b4c42d1 100644 --- a/babybuddy/models.py +++ b/babybuddy/models.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- import pytz +import json +import io from django.conf import settings from django.contrib.auth.models import User @@ -12,6 +14,8 @@ from django.utils.translation import gettext_lazy as _ from rest_framework.authtoken.models import Token +import qrcode + class Settings(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) @@ -82,6 +86,22 @@ class Settings(models.Model): Token.objects.get(user=self.user).delete() return Token.objects.get_or_create(user=self.user)[0] + def generate_login_qr_code_png(self, page_root: str) -> bytes: + json_data = { + "url": page_root, + "api_key": str(self.api_key()), + } + qr_code_data = r"BABYBUDDY-LOGIN:" + json.dumps(json_data) + + qr = qrcode.QRCode(border=1, box_size=5) + qr.add_data(qr_code_data) + qr.make(fit=True) + image = qr.make_image() + + bytesio = io.BytesIO() + image.save(bytesio, format="png") + return bytesio.getbuffer() + @property def dashboard_refresh_rate_milliseconds(self): """ diff --git a/babybuddy/templates/babybuddy/user_settings_form.html b/babybuddy/templates/babybuddy/user_settings_form.html index b7b99bf9..17c6b175 100644 --- a/babybuddy/templates/babybuddy/user_settings_form.html +++ b/babybuddy/templates/babybuddy/user_settings_form.html @@ -78,12 +78,18 @@
{% trans "API" %}
- +
{{ user.settings.api_key }}
+
+ +
+ +
+
diff --git a/babybuddy/views.py b/babybuddy/views.py index a53cde16..0d34a957 100644 --- a/babybuddy/views.py +++ b/babybuddy/views.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- +import base64 + +from urllib.parse import urljoin + from django.contrib import messages from django.contrib.auth import update_session_auth_hash from django.contrib.auth.forms import PasswordChangeForm @@ -158,14 +162,22 @@ class UserSettings(LoginRequiredMixin, View): template_name = "babybuddy/user_settings_form.html" def get(self, request): + settings = request.user.settings + + page_root = request.build_absolute_uri(reverse("babybuddy:root-router")) + base64_png = base64.b64encode( + settings.generate_login_qr_code_png(page_root) + ) + return render( request, self.template_name, { "form_user": self.form_user_class(instance=request.user), "form_settings": self.form_settings_class( - instance=request.user.settings + instance=settings ), + "login_qr_code_png": base64_png.decode(), }, ) diff --git a/requirements.txt b/requirements.txt index d0a010fe..4ebffb44 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,6 +31,7 @@ python-dateutil==2.8.2 python-dotenv==0.20.0 pytz==2022.1 pyyaml==6.0 +qrcode==7.3.1 s3transfer==0.6.0 setuptools==63.1.0 six==1.16.0