1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-12-10 05:37:46 +01:00

Compare commits

..

2 Commits

Author SHA1 Message Date
alexismdr
a25afea16d fix: line length for linters 2025-12-09 20:19:29 +01:00
alexismdr
56167a21b5 feat: check min/max promotion year
* min year is 1912 (ENSET creation year)
* max year is same as default

WARNING : Changing this behavior could break iOS/Android apps. Please change Swift/Kotlin code accordingly.
2025-12-09 19:28:56 +01:00
6 changed files with 12 additions and 51 deletions

View File

@@ -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
)

View File

@@ -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')),
]

View File

@@ -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")

View File

@@ -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:])})

View File

@@ -19,6 +19,7 @@ from phonenumber_field.modelfields import PhoneNumberField
from permission.models import Role
from registration.tokens import email_validation_token
from note.models import MembershipTransaction
from django.core.validators import MaxValueValidator, MinValueValidator
class Profile(models.Model):
@@ -76,6 +77,10 @@ class Profile(models.Model):
default=datetime.date.today().year if datetime.date.today().month >= 8 else datetime.date.today().year - 1,
verbose_name=_("promotion"),
help_text=_("Year of entry to the school (None if not ENS student)"),
validators=[
MinValueValidator(1912),
MaxValueValidator(datetime.date.today().year if datetime.date.today().month >= 8 else datetime.date.today().year - 1)
],
)
address = models.CharField(

View File

@@ -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