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()
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,
)
194
195
196
197
198
199
200
201
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
class CommentEdit(
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView,
):
queryset = Activity.comments.all()
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)