diff --git a/apps/api/urls.py b/apps/api/urls.py index 4452e4d7..ff093187 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -3,7 +3,7 @@ from django.conf import settings from django.conf.urls import include -from django.urls import re_path +from django.urls import re_path, path from rest_framework import routers from .views import UserInformationView @@ -61,6 +61,7 @@ app_name = 'api' # Additionally, we include login URLs for the browsable API. urlpatterns = [ re_path('^', include(router.urls)), - re_path('^me/', UserInformationView.as_view()), + path('me/', UserInformationView.as_view({'get': 'retrieve'})), + path('me/qrcode/', UserInformationView.as_view({'get': 'qrcode'})), re_path('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] diff --git a/apps/api/views.py b/apps/api/views.py index a6667042..d0a0522c 100644 --- a/apps/api/views.py +++ b/apps/api/views.py @@ -1,13 +1,19 @@ # Copyright (C) 2018-2025 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later +import base64 +import os +from io import BytesIO +import qrcode +import pyotp from django.contrib.auth.models import User -from rest_framework.generics import RetrieveAPIView +from django.http.response import HttpResponse +from rest_framework import viewsets, mixins from .serializers import OAuthSerializer -class UserInformationView(RetrieveAPIView): +class UserInformationView(mixins.RetrieveModelMixin, viewsets.GenericViewSet): """ These fields are give to OAuth authenticators. """ @@ -18,3 +24,11 @@ class UserInformationView(RetrieveAPIView): def get_object(self): return self.request.user + + def qrcode(self, request, *args, **kwargs): + secret = base64.b32encode(os.getenv("DJANGO_SECRET_KEY").encode()) + qr_img = qrcode.make(f"{str(request.user.username)}{pyotp.TOTP(secret, interval=30).now()}") + buffer = BytesIO() + qr_img.save(buffer, format="PNG") + buffer.seek(0) + return HttpResponse(buffer, content_type="image/png")