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

1from django.conf import settings 

2from django.utils import timezone 

3 

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 

8 

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 

13 

14from .serializers import ReferenceFaceSerializer 

15 

16 

17class YourPhotosView(ListAPIView): 

18 serializer_class = PhotoListSerializer 

19 permission_classes = [IsAuthenticatedOrTokenHasScope] 

20 required_scopes = ["photos:read", "facedetection:read"] 

21 

22 schema = AutoSchema(operation_id_base="FacedetectionMatches") 

23 

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) 

30 

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) 

36 

37 def get_queryset(self): 

38 return get_user_photos(self.request.member) 

39 

40 

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 } 

50 

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) 

56 

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) 

72 

73 def perform_create(self, serializer): 

74 serializer.save(user=self.request.member) 

75 

76 def get_queryset(self): 

77 return self.request.member.reference_faces.filter( 

78 marked_for_deletion_at__isnull=True 

79 ).all() 

80 

81 

82class ReferenceFaceDeleteView(DestroyAPIView): 

83 serializer_class = ReferenceFaceSerializer 

84 permission_classes = [IsAuthenticatedOrTokenHasScope] 

85 required_scopes = ["facedetection:write"] 

86 

87 def get_queryset(self): 

88 return self.request.member.reference_faces.filter( 

89 marked_for_deletion_at__isnull=True 

90 ).all() 

91 

92 def perform_destroy(self, instance): 

93 instance.marked_for_deletion_at = timezone.now() 

94 instance.save()