Newer
Older
from django.core.exceptions import PermissionDenied as DjangoPermissionDenied
from django.db import transaction
from django.utils import timezone
from rest_framework import generics, mixins, permissions
from rest_framework.response import Response
from rest_framework.exceptions import (NotFound, PermissionDenied,
ValidationError)
from django_filters import rest_framework as filters
from opentech.api.pagination import StandardResultsSetPagination
from opentech.apply.activity.models import Activity, COMMENT
from opentech.apply.activity.messaging import messenger, MESSAGES
from opentech.apply.determinations.views import DeterminationCreateOrUpdateView
from .models import ApplicationSubmission, RoundsAndLabs
CommentCreateSerializer,
SubmissionListSerializer,
SubmissionDetailSerializer,
)
from .permissions import IsApplyStaffUser, IsAuthor
class RoundLabFilter(filters.ModelChoiceFilter):
def filter(self, qs, value):
if not value:
return qs
return qs.filter(Q(round=value) | Q(page=value))
class SubmissionsFilter(filters.FilterSet):
round = RoundLabFilter(queryset=RoundsAndLabs.objects.all())
status = filters.MultipleChoiceFilter(choices=PHASES)
active = filters.BooleanFilter(method='filter_active')
class Meta:
model = ApplicationSubmission
fields = ('status', 'round', 'active')
def filter_active(self, value):
if value is None:
return qs
if value:
return qs.active()
else:
return qs.inactive()
class SubmissionList(generics.ListAPIView):
queryset = ApplicationSubmission.objects.current().with_latest_update()
serializer_class = SubmissionListSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
filter_backends = (filters.DjangoFilterBackend,)
filter_class = SubmissionsFilter
pagination_class = StandardResultsSetPagination
class SubmissionDetail(generics.RetrieveAPIView):
queryset = ApplicationSubmission.objects.all()
serializer_class = SubmissionDetailSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
class SubmissionAction(generics.RetrieveAPIView):
queryset = ApplicationSubmission.objects.all()
serializer_class = SubmissionActionSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
def post(self, request, *args, **kwargs):
action = request.data.get('action')
if not action:
raise ValidationError('Action must be provided.')
obj = self.get_object()
redirect = DeterminationCreateOrUpdateView.should_redirect(
request, obj, action)
if redirect:
raise NotFound({
'detail': 'The action should be performed at the determination view',
'target': redirect.url,
})
try:
obj.perform_transition(action, self.request.user, request=self.request)
except DjangoPermissionDenied as e:
raise PermissionDenied(str(e))
# refresh_from_db() raises errors for particular actions.
obj = self.get_object()
serializer = SubmissionDetailSerializer(obj, context={
'request': request,
})
return Response({
'id': serializer.data['id'],
'status': serializer.data['status'],
'actions': serializer.data['actions'],
'phase': serializer.data['phase'],
})
class RoundLabDetail(generics.RetrieveAPIView):
queryset = RoundsAndLabs.objects.all()
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
def get_object(self):
return super().get_object().specific
class RoundLabList(generics.ListAPIView):
queryset = RoundsAndLabs.objects.specific()
serializer_class = RoundLabSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
pagination_class = StandardResultsSetPagination
class NewerThanFilter(filters.ModelChoiceFilter):
def filter(self, qs, value):
if not value:
return qs
return qs.newer(value)
class CommentFilter(filters.FilterSet):
since = filters.DateTimeFilter(field_name="timestamp", lookup_expr='gte')
before = filters.DateTimeFilter(field_name="timestamp", lookup_expr='lte')
newer = NewerThanFilter(queryset=Activity.comments.all())
class Meta:
model = Activity
fields = ['submission', 'visibility', 'since', 'before', 'newer']
class CommentList(generics.ListAPIView):
queryset = Activity.comments.all()
serializer_class = CommentSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
filter_backends = (filters.DjangoFilterBackend,)
filter_class = CommentFilter
pagination_class = StandardResultsSetPagination
def get_queryset(self):
return super().get_queryset().visible_to(self.request.user)
class CommentListCreate(generics.ListCreateAPIView):
queryset = Activity.comments.all().select_related('user')
serializer_class = CommentCreateSerializer
permission_classes = (
permissions.IsAuthenticated, IsApplyStaffUser,
)
filter_backends = (filters.DjangoFilterBackend,)
pagination_class = StandardResultsSetPagination
def get_queryset(self):
return super().get_queryset().filter(
submission=self.kwargs['pk']
).visible_to(self.request.user)
def perform_create(self, serializer):
obj = serializer.save(
type=COMMENT,
user=self.request.user,
submission_id=self.kwargs['pk']
)
messenger(
MESSAGES.COMMENT,
request=self.request,
user=self.request.user,
submission=obj.submission,
related=obj,
)
class CommentEdit(
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView,
):
queryset = Activity.comments.all().select_related('user')
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
serializer_class = CommentEditSerializer
permission_classes = (
permissions.IsAuthenticated, IsAuthor
)
def post(self, request, *args, **kwargs):
return self.edit(request, *args, **kwargs)
@transaction.atomic
def edit(self, request, *args, **kwargs):
comment_to_edit = self.get_object()
comment_to_update = self.get_object()
comment_to_edit.previous = comment_to_update
comment_to_edit.pk = None
comment_to_edit.edited = timezone.now()
serializer = self.get_serializer(comment_to_edit, data=request.data)
serializer.is_valid(raise_exception=True)
if serializer.validated_data['message'] != comment_to_update.message:
self.perform_create(serializer)
comment_to_update.current = False
comment_to_update.save()
return Response(serializer.data)
return Response(self.get_serializer(comment_to_update).data)