diff --git a/Dockerfile b/Dockerfile index e7843b0..8a2722a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:3.18 -RUN apk --no-cache add python3 inkscape bash imagemagick ghostscript font-noto -RUN apk --no-cache add py3-pip && pip3 install --break-system-packages django tzdata gunicorn +RUN apk --no-cache add python3 inkscape bash imagemagick ghostscript font-noto py3-pip +RUN pip3 install --break-system-packages django tzdata gunicorn google-api-python-client ADD backend /zetikettes diff --git a/backend/zetikettes/tikette/middleware.py b/backend/zetikettes/tikette/middleware.py new file mode 100644 index 0000000..fd0a7e0 --- /dev/null +++ b/backend/zetikettes/tikette/middleware.py @@ -0,0 +1,15 @@ +from django.http import HttpResponse + + +def cors_everywhere(get_response): + def middleware(request): + if request.method == 'OPTIONS': + response = HttpResponse() + else: + response = get_response(request) + response["Access-Control-Allow-Origin"] = request.headers.get("Origin", "*") + response["Access-Control-Allow-Credentials"] = "true" + response["Access-Control-Allow-Headers"] = "x-csrftoken" + return response + + return middleware diff --git a/backend/zetikettes/tikette/views.py b/backend/zetikettes/tikette/views.py index 99a7835..5dc52b4 100644 --- a/backend/zetikettes/tikette/views.py +++ b/backend/zetikettes/tikette/views.py @@ -1,14 +1,44 @@ import json +import sys from django.conf import settings +from django.core.exceptions import PermissionDenied from django.http import JsonResponse from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt +from google.auth.transport import requests +from google.oauth2 import id_token from .planche import generate as stickersheet -from .models import Tikette, Tikategory +from .models import Tikette, Tikategory, Tizer -CORS={'access-control-allow-origin': '*'} + +def ok(payload=None): + return JsonResponse({'status': 'ok', **(payload or {})}) + + +def post_please(f): + def __f(request): + if request.method != "POST": + return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'}, + status=405, headers={'Allow': 'POST'}) + return f(request) + return __f + + +def auth_only(f): + def __f(request): + # check that email is valid + # exp? + print(request.META, file=sys.stderr) + if 'user_data' not in request.session: + raise PermissionDenied('Not logged in') + email = request.session['user_data']['email'] + resp = Tizer.objects.filter(email=email) + if not resp: + raise PermissionDenied('User not found') + return f(request) + return __f def quirk_bold_allergens(ingredients): @@ -21,6 +51,7 @@ def quirk_bold_allergens(ingredients): return ", ".join(out) +@auth_only def get_list(request): tikettes = [{ 'id': x.id, @@ -35,22 +66,21 @@ def get_list(request): 'color': x.color, 'subs': {x.name: x.default for x in x.category.subs.all()}, } for x in Tikette.objects.all()] - return JsonResponse({'status': 'ok', 'tikettes': tikettes}, headers=CORS) + return ok({'tikettes': tikettes}) +@auth_only def get_categories(request): tikats = [{ 'id': x.id, 'name': x.name, } for x in Tikategory.objects.all()] - return JsonResponse({'status': 'ok', 'tikats': tikats}, headers=CORS) + return ok({'tikats': tikats}) -@csrf_exempt +@auth_only +@post_please def generate(request): - if request.method != "POST": - return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'}) - payload = json.loads(request.body) subs = dict(payload['subs']) @@ -61,27 +91,47 @@ def generate(request): out_dir=settings.TIKETTE_OUT_DIR, landscape=payload['landscape']) - return JsonResponse({'status': 'ok', 'file': pdfpath}, headers=CORS) + return ok({'file': pdfpath}) -@csrf_exempt +@auth_only +@post_please def newtikette(request): - if request.method != "POST": - return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'}) - payload = json.loads(request.body) tikette = Tikette(**payload) tikette.save() - return JsonResponse({'status': 'ok'}, headers=CORS) + return ok() -@csrf_exempt +@auth_only +@post_please def deletetikette(request): - if request.method != "POST": - return JsonResponse({'status': 'notok', 'message': 'this isn\'t the way'}) - payload = json.loads(request.body) Tikette.objects.get(id=payload["id"]).delete() - return JsonResponse({'status': 'ok'}, headers=CORS) + return ok() + + +@csrf_exempt +@post_please +def signin(request): + payload = json.loads(request.body) + token = payload['token'] + + try: + user_data = id_token.verify_oauth2_token( + token, requests.Request(), settings.GOOGLE_OAUTH_CLIENT_ID + ) + except ValueError: + raise + return JsonResponse({'status': 'notok'}, status=403) + + request.session['user_data'] = user_data + + return ok(user_data) + + +def signout(request): + del request.session['user_data'] + return ok() diff --git a/backend/zetikettes/zetikettes/settings.py b/backend/zetikettes/zetikettes/settings.py index 59f63fd..f6ce435 100644 --- a/backend/zetikettes/zetikettes/settings.py +++ b/backend/zetikettes/zetikettes/settings.py @@ -53,6 +53,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'tikette.middleware.cors_everywhere', ] ROOT_URLCONF = 'zetikettes.urls' @@ -129,3 +130,6 @@ STATIC_ROOT = 'www_static' # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# not a secret +GOOGLE_OAUTH_CLIENT_ID = '634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com' diff --git a/backend/zetikettes/zetikettes/urls.py b/backend/zetikettes/zetikettes/urls.py index 4059fad..b0b1195 100644 --- a/backend/zetikettes/zetikettes/urls.py +++ b/backend/zetikettes/zetikettes/urls.py @@ -29,4 +29,6 @@ urlpatterns = [ path('generate', tikette.views.generate), path('newtikette', tikette.views.newtikette), path('deletetikette', tikette.views.deletetikette), + path('signin', tikette.views.signin), + path('signout', tikette.views.signout), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/frontend/config.js b/frontend/config.js index d63e462..1cbf26f 100644 --- a/frontend/config.js +++ b/frontend/config.js @@ -1 +1,2 @@ const backend_api = '/zetikettes/srv/' +const google_oauth_client_id = '634510965520-c5l7f15fn4koraqhpqfe01ssn8v0q2qk.apps.googleusercontent.com'; diff --git a/frontend/index.html b/frontend/index.html index e6d8810..dee14dc 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -14,6 +14,7 @@ + @@ -46,6 +47,7 @@ main {

+
addNouveau produit