Louis Mazin 4db822aebe big maj
2026-10-05 17:52:28 +02:00

62 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.db import transaction
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import serializers
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Note, Poll, PollVote
from .permissions import can_edit_note
from .polls import can_vote, is_closed
from .serializers import NoteSerializer
from .views import visible_notes
class PollVoteView(APIView):
permission_classes = [IsAuthenticated]
@transaction.atomic
def put(self, request, pk):
note = get_object_or_404(visible_notes(request.user), pk=pk, kind='poll')
get_object_or_404(Note.objects.select_for_update(), pk=note.pk)
# Relire après le verrou : règles, droits et clôture peuvent avoir changé.
note = get_object_or_404(visible_notes(request.user), pk=pk, kind='poll')
poll = get_object_or_404(Poll, note=note)
if is_closed(poll):
raise ValidationError('Ce sondage est clôturé.')
if not can_vote(request.user, note):
raise PermissionDenied('Ce sondage est réservé aux destinataires indiqués.')
choices = serializers.ListField(child=serializers.IntegerField(min_value=1), min_length=1, max_length=30).run_validation(request.data.get('option_ids'))
if len(set(choices)) != len(choices) or poll.options.filter(pk__in=choices).count() != len(choices):
raise ValidationError('Choisissez des réponses distinctes appartenant à ce sondage.')
expected = 1 if poll.vote_mode == 'single' else poll.exact_choices if poll.vote_mode == 'exact' else None
if expected is not None and len(choices) != expected:
raise ValidationError(f'Sélectionnez exactement {expected} réponse(s).')
vote, _ = PollVote.objects.get_or_create(poll=poll, user=request.user)
vote.options.set(choices)
vote.save()
if not poll.locked_at:
poll.locked_at = timezone.now()
poll.save(update_fields=['locked_at'])
fresh = visible_notes(request.user).get(pk=pk)
return Response(NoteSerializer(fresh, context={'request': request}).data)
class PollCloseView(APIView):
permission_classes = [IsAuthenticated]
@transaction.atomic
def post(self, request, pk):
note = get_object_or_404(visible_notes(request.user), pk=pk, kind='poll')
get_object_or_404(Note.objects.select_for_update(), pk=note.pk)
note = get_object_or_404(visible_notes(request.user), pk=pk, kind='poll')
if not can_edit_note(request.user, note):
raise PermissionDenied('Seuls l’auteur et les administrateurs autorisés peuvent clôturer ce sondage.')
poll = get_object_or_404(Poll, note=note)
if not poll.closed_at:
poll.closed_at = timezone.now()
poll.save(update_fields=['closed_at'])
return Response(NoteSerializer(visible_notes(request.user).get(pk=pk), context={'request': request}).data)