mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-12-10 05:37:46 +01:00
Compare commits
8 Commits
qrcode-tot
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4059efa6c6 | ||
|
|
e146548658 | ||
|
|
1c891d6708 | ||
|
|
f3289de5d8 | ||
|
|
68ea640736 | ||
|
|
00176c3cef | ||
|
|
de841c8143 | ||
|
|
43603d7359 |
@@ -28,3 +28,6 @@ OIDC_RSA_PRIVATE_KEY=CHANGE_ME
|
||||
# Activity configuration
|
||||
TRUSTED_ACTIVITY_MAIL=
|
||||
ACTIVITY_EMAIL_MANAGER=
|
||||
|
||||
# App Store App ID
|
||||
APP_STORE_APP_ID=P5246D3AFQ.org.crans.bde.note
|
||||
|
||||
@@ -89,11 +89,3 @@ class OAuthSerializer(serializers.ModelSerializer):
|
||||
'note',
|
||||
'memberships',
|
||||
)
|
||||
|
||||
|
||||
class QRCodeCheckSerializer(serializers.Serializer):
|
||||
data = serializers.CharField(
|
||||
label="Données du QR Code",
|
||||
help_text="Le contenu brut lu depuis le QR Code (Username + Token)",
|
||||
required=True
|
||||
)
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include
|
||||
from django.urls import re_path, path
|
||||
from django.urls import re_path
|
||||
from rest_framework import routers
|
||||
|
||||
from .views import UserInformationView
|
||||
from .viewsets import ContentTypeViewSet, UserViewSet, QRCodeVerificationViewSet
|
||||
from .viewsets import ContentTypeViewSet, UserViewSet
|
||||
|
||||
# Routers provide an easy way of automatically determining the URL conf.
|
||||
# Register each app API router and user viewset
|
||||
router = routers.DefaultRouter()
|
||||
router.register('models', ContentTypeViewSet)
|
||||
router.register('user', UserViewSet)
|
||||
router.register('check_qrcode', QRCodeVerificationViewSet, basename='check_qrcode')
|
||||
|
||||
if "activity" in settings.INSTALLED_APPS:
|
||||
from activity.api.urls import register_activity_urls
|
||||
@@ -62,7 +61,6 @@ app_name = 'api'
|
||||
# Additionally, we include login URLs for the browsable API.
|
||||
urlpatterns = [
|
||||
re_path('^', include(router.urls)),
|
||||
path('me/', UserInformationView.as_view({'get': 'retrieve'})),
|
||||
path('me/qrcode/', UserInformationView.as_view({'get': 'qrcode'})),
|
||||
re_path('^me/', UserInformationView.as_view()),
|
||||
re_path('^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
]
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
# 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 django.http.response import HttpResponse
|
||||
from rest_framework import viewsets, mixins
|
||||
from rest_framework.generics import RetrieveAPIView
|
||||
|
||||
from .serializers import OAuthSerializer
|
||||
|
||||
|
||||
class UserInformationView(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||
class UserInformationView(RetrieveAPIView):
|
||||
"""
|
||||
These fields are give to OAuth authenticators.
|
||||
"""
|
||||
@@ -24,11 +18,3 @@ class UserInformationView(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||
|
||||
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.note)}{pyotp.TOTP(secret, interval=30).now()}")
|
||||
buffer = BytesIO()
|
||||
qr_img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
return HttpResponse(buffer, content_type="image/png")
|
||||
|
||||
@@ -2,22 +2,18 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import re
|
||||
import base64
|
||||
import os
|
||||
|
||||
import pyotp
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django.db.models import Q
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet, GenericViewSet
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet
|
||||
from permission.backends import PermissionBackend
|
||||
from note.models import Alias
|
||||
|
||||
from .filters import RegexSafeSearchFilter
|
||||
from .serializers import UserSerializer, ContentTypeSerializer, QRCodeCheckSerializer
|
||||
from .serializers import UserSerializer, ContentTypeSerializer
|
||||
|
||||
|
||||
def is_regex(pattern):
|
||||
@@ -128,17 +124,3 @@ class ContentTypeViewSet(ReadOnlyModelViewSet):
|
||||
filter_backends = [DjangoFilterBackend, RegexSafeSearchFilter]
|
||||
filterset_fields = ['id', 'app_label', 'model', ]
|
||||
search_fields = ['$app_label', '$model', ]
|
||||
|
||||
|
||||
class QRCodeVerificationViewSet(GenericViewSet):
|
||||
serializer_class = QRCodeCheckSerializer
|
||||
queryset = User.objects.none()
|
||||
|
||||
def get_view_name(self):
|
||||
return "Vérification QR Code"
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
secret = base64.b32encode(os.getenv("DJANGO_SECRET_KEY").encode())
|
||||
return Response({'valid': pyotp.TOTP(secret, interval=30).verify(serializer.validated_data['data'][-6:])})
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.views.defaults import bad_request, permission_denied, page_not_found
|
||||
from member.views import CustomLoginView
|
||||
|
||||
from .admin import admin_site
|
||||
from .views import IndexView
|
||||
from .views import IndexView, apple_app_site_association
|
||||
|
||||
urlpatterns = [
|
||||
# Dev so redirect to something random
|
||||
@@ -33,6 +33,9 @@ urlpatterns = [
|
||||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
path('api/', include('api.urls')),
|
||||
path('permission/', include('permission.urls')),
|
||||
|
||||
# Apple App Site Association
|
||||
path('.well-known/apple-app-site-association', apple_app_site_association),
|
||||
]
|
||||
|
||||
# During development, serve static and media files
|
||||
|
||||
@@ -6,6 +6,8 @@ from django.urls import reverse
|
||||
from django.views.generic import RedirectView
|
||||
from note.models import Alias
|
||||
from permission.backends import PermissionBackend
|
||||
from django.http import JsonResponse
|
||||
import os
|
||||
|
||||
|
||||
class IndexView(LoginRequiredMixin, RedirectView):
|
||||
@@ -28,3 +30,13 @@ class IndexView(LoginRequiredMixin, RedirectView):
|
||||
|
||||
# Non-Kfet members will don't see the transfer page, but their profile page
|
||||
return reverse("member:user_detail", args=(user.pk,))
|
||||
|
||||
def apple_app_site_association(request):
|
||||
data = {
|
||||
"webcredentials": {
|
||||
"apps": [
|
||||
os.getenv("APP_STORE_APP_ID")
|
||||
]
|
||||
}
|
||||
}
|
||||
return JsonResponse(data)
|
||||
|
||||
@@ -20,5 +20,3 @@ python-memcached~=1.62
|
||||
phonenumbers~=9.0.8
|
||||
tablib~=3.8.0
|
||||
Pillow>=11.3.0
|
||||
pyotp~=2.9.0
|
||||
qrcode~=8.2
|
||||
Reference in New Issue
Block a user