Coverage for website/facedetection/api/v2/views.py: 50.77%
55 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1from django.conf import settings
2from django.utils import timezone
4from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
5from rest_framework.exceptions import PermissionDenied
6from rest_framework.generics import DestroyAPIView, ListAPIView, ListCreateAPIView
7from rest_framework.schemas.openapi import AutoSchema
9from facedetection.services import get_user_photos
10from photos.api.v2.serializers.photo import PhotoListSerializer
11from thaliawebsite.api.v2.permissions import IsAuthenticatedOrTokenHasScopeForMethod
12from utils.media.services import fetch_thumbnails
14from .serializers import ReferenceFaceSerializer
17class YourPhotosView(ListAPIView):
18 serializer_class = PhotoListSerializer
19 permission_classes = [IsAuthenticatedOrTokenHasScope]
20 required_scopes = ["photos:read", "facedetection:read"]
22 schema = AutoSchema(operation_id_base="FacedetectionMatches")
24 def get(self, request, *args, **kwargs):
25 if not request.member or not request.member.has_active_membership():
26 raise PermissionDenied(
27 detail="You need to be a member in order to view your facedetection photos."
28 )
29 return self.list(request, *args, **kwargs)
31 def get_serializer(self, *args, **kwargs):
32 if len(args) > 0:
33 photos = args[0]
34 fetch_thumbnails([photo.file for photo in photos])
35 return super().get_serializer(*args, **kwargs)
37 def get_queryset(self):
38 return get_user_photos(self.request.member)
41class ReferenceFaceListView(ListCreateAPIView):
42 serializer_class = ReferenceFaceSerializer
43 permission_classes = [
44 IsAuthenticatedOrTokenHasScopeForMethod,
45 ]
46 required_scopes_per_method = {
47 "GET": ["facedetection:read"],
48 "POST": ["facedetection:write"],
49 }
51 def get_serializer(self, *args, **kwargs):
52 if len(args) > 0:
53 reference_faces = args[0]
54 fetch_thumbnails([reference.file for reference in reference_faces])
55 return super().get_serializer(*args, **kwargs)
57 def create(self, request, *args, **kwargs):
58 if not request.member.has_active_membership():
59 raise PermissionDenied(
60 detail="You need to be a member to use this feature."
61 )
62 if (
63 request.member.reference_faces.filter(
64 marked_for_deletion_at__isnull=True,
65 ).count()
66 >= settings.FACEDETECTION_MAX_NUM_REFERENCE_FACES
67 ):
68 raise PermissionDenied(
69 detail="You have reached the maximum number of reference faces."
70 )
71 return super().create(request, *args, **kwargs)
73 def perform_create(self, serializer):
74 serializer.save(user=self.request.member)
76 def get_queryset(self):
77 return self.request.member.reference_faces.filter(
78 marked_for_deletion_at__isnull=True
79 ).all()
82class ReferenceFaceDeleteView(DestroyAPIView):
83 serializer_class = ReferenceFaceSerializer
84 permission_classes = [IsAuthenticatedOrTokenHasScope]
85 required_scopes = ["facedetection:write"]
87 def get_queryset(self):
88 return self.request.member.reference_faces.filter(
89 marked_for_deletion_at__isnull=True
90 ).all()
92 def perform_destroy(self, instance):
93 instance.marked_for_deletion_at = timezone.now()
94 instance.save()