Source code for intranet.apps.eighth.views.api

import logging
from datetime import datetime

from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.http import Http404
from rest_framework import generics, permissions, status, views
from rest_framework.exceptions import ValidationError
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

from ..models import EighthActivity, EighthBlock, EighthScheduledActivity, EighthSignup
from ..serializers import (
    EighthActivityDetailSerializer,
    EighthActivityListSerializer,
    EighthAddSignupSerializer,
    EighthBlockDetailSerializer,
    EighthBlockListSerializer,
    EighthScheduledActivitySerializer,
    EighthSignupSerializer,
    EighthToggleFavoriteSerializer,
)

logger = logging.getLogger(__name__)


[docs]class IsAuthenticatedOrClientCredentials(permissions.BasePermission):
[docs] def has_permission(self, request, view): return bool( (request.user and request.user.is_authenticated and not request.user.is_restricted and request.user.oauth_and_api_access) or request.auth )
[docs]class EighthActivityList(generics.ListAPIView): queryset = EighthActivity.undeleted_objects.all().order_by("id") serializer_class = EighthActivityListSerializer permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs]class EighthActivityDetail(generics.RetrieveAPIView): """API endpoint that shows details of an eighth activity.""" queryset = EighthActivity.undeleted_objects.all().order_by("id") serializer_class = EighthActivityDetailSerializer permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs]class BlockPagination(PageNumberPagination): page_size = 50 page_size_query_param = "page_size" max_page_size = 200
[docs]class EighthBlockList(generics.ListAPIView): """API endpoint that lists all eighth blocks.""" serializer_class = EighthBlockListSerializer pagination_class = BlockPagination permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def is_valid_date(self, date_text): try: datetime.strptime(date_text, "%Y-%m-%d") except ValueError: return False return True
[docs] def get_queryset(self): if "start_date" in self.request.GET: start_date = self.request.GET.get("start_date") if not self.is_valid_date(start_date): raise ValidationError("Invalid format for start_date.") return EighthBlock.objects.filter(date__gte=start_date).order_by("id") if "date" in self.request.GET: date = self.request.GET.get("date") if not self.is_valid_date(date): raise ValidationError("Invalid format for date.") return EighthBlock.objects.filter(date=date).order_by("id") return EighthBlock.objects.get_blocks_this_year()
[docs]class EighthBlockDetail(views.APIView): """API endpoint that shows details for an eighth block.""" permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def get(self, request, pk): try: block = EighthBlock.objects.prefetch_related("eighthscheduledactivity_set").get(pk=pk) except EighthBlock.DoesNotExist as e: raise Http404 from e serializer = EighthBlockDetailSerializer(block, context={"request": request}) return Response(serializer.data)
[docs]class EighthUserSignupListAdd(generics.ListCreateAPIView): serializer_class = EighthAddSignupSerializer queryset = EighthSignup.objects.all().order_by("id") permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def is_valid_date(self, date_text): try: datetime.strptime(date_text, "%Y-%m-%d") except ValueError: return False return True
[docs] def list(self, request, user_id=None): # pylint: disable=arguments-differ if not user_id: user_id = request.user.id elif not get_user_model().objects.get(id=user_id).can_view_eighth: serialized = EighthSignupSerializer([], context={"request": request}, many=True) return Response(serialized.data) all_signups = EighthSignup.objects.filter(user_id=user_id).prefetch_related("scheduled_activity__block") if "date" in request.GET: date = self.request.GET.get("date") if not self.is_valid_date(date): raise ValidationError("Invalid format for date.") all_signups = all_signups.filter(scheduled_activity__block__date=date) elif "start_date" in request.GET: start_date = self.request.GET.get("start_date") if not self.is_valid_date(start_date): raise ValidationError("Invalid format for start_date.") all_signups = all_signups.filter(scheduled_activity__block__date__gte=start_date) else: all_signups = all_signups.filter(scheduled_activity__block__in=EighthBlock.objects.get_blocks_this_year()) signups = all_signups.select_related("scheduled_activity__activity").order_by( "scheduled_activity__block__date", "scheduled_activity__block__block_letter" ) serialized = EighthSignupSerializer(signups, context={"request": request}, many=True) return Response(serialized.data)
[docs] def create(self, request, user_id=None): # pylint: disable=arguments-differ if user_id and not request.user.is_eighth_admin: raise PermissionDenied elif user_id: user = get_user_model().objects.get(id=user_id) else: user = request.user serializer = EighthAddSignupSerializer(data=request.data, context={"request": request}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) if ( "activity" not in serializer.validated_data or "block" not in serializer.validated_data or serializer.validated_data.get("use_scheduled_activity", False) ): schactivity = serializer.validated_data["scheduled_activity"] else: schactivity = ( EighthScheduledActivity.objects.filter(activity=serializer.validated_data["activity"]) .filter(block=serializer.validated_data["block"]) .get() ) if "force" in serializer.validated_data: force = serializer.validated_data["force"] else: force = False if force and not request.user.is_eighth_admin: return Response({"error": "You are not an administrator."}, status=status.HTTP_400_BAD_REQUEST) schactivity.add_user(user, request, force=force) return Response(EighthActivityDetailSerializer(schactivity.activity, context={"request": request}).data, status=status.HTTP_201_CREATED)
[docs]class EighthUserFavoritesListToggle(generics.ListCreateAPIView): serializer_class = EighthToggleFavoriteSerializer queryset = EighthActivity.undeleted_objects.all() permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def get_queryset(self): user_id = self.request.user.id user = get_user_model().objects.get(id=user_id) return user.favorited_activity_set.all()
[docs] def list(self, request): # pylint: disable=arguments-differ serialized = EighthActivityListSerializer(self.get_queryset(), context={"request": request}, many=True) return Response(serialized.data)
[docs] def create(self, request, user_id=None): # pylint: disable=arguments-differ if user_id: user = get_user_model().objects.get(id=user_id) else: user = request.user serializer = EighthToggleFavoriteSerializer(data=request.data, context={"request": request}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) activity = serializer.validated_data["activity"] favorites = user.favorited_activity_set if activity in favorites.all(): favorites.remove(activity) else: favorites.add(activity) return Response(EighthActivityDetailSerializer(activity, context={"request": request}).data, status=status.HTTP_201_CREATED)
# except EighthActivity.DoesNotExist: # return Response({"error": "The activity does not exist"}, status=status.HTTP_400_BAD_REQUEST) # except Exception: # return Response({"error": "An unknown error occurred"}, status=status.HTTP_400_BAD_REQUEST)
[docs]class EighthUserFavoritesAdd(generics.CreateAPIView): serializer_class = EighthActivityDetailSerializer queryset = EighthActivity.undeleted_objects.all() permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def get_queryset(self): user_id = self.request.user.id user = get_user_model().objects.get(id=user_id) return user.favorited_activity_set.all()
[docs] def create(self, request, user_id=None): # pylint: disable=arguments-differ if user_id: user = get_user_model().objects.get(id=user_id) else: user = request.user try: activity = EighthActivity.objects.get(id=request.data.get("id")) favorites = user.favorited_activity_set favorites.add(activity) return Response(EighthActivityDetailSerializer(activity, context={"request": request}).data, status=status.HTTP_201_CREATED) except EighthActivity.DoesNotExist: return Response({"error": "The activity does not exist"}, status=status.HTTP_400_BAD_REQUEST) except Exception: return Response({"error": "An unknown error occurred"}, status=status.HTTP_400_BAD_REQUEST)
[docs]class EighthUserFavoritesRemove(generics.ListCreateAPIView): serializer_class = EighthActivityListSerializer queryset = EighthActivity.undeleted_objects.all() permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def get_queryset(self): user_id = self.request.user.id user = get_user_model().objects.get(id=user_id) return user.favorited_activity_set.all()
[docs] def list(self, request): # pylint: disable=arguments-differ serialized = EighthActivityListSerializer(self.get_queryset(), context={"request": request}, many=True) return Response(serialized.data)
[docs] def create(self, request, user_id=None): # pylint: disable=arguments-differ if user_id: user = get_user_model().objects.get(id=user_id) else: user = request.user try: activity = EighthActivity.objects.get(id=request.data.get("id")) favorites = user.favorited_activity_set favorites.remove(activity) return Response(EighthActivityDetailSerializer(activity, context={"request": request}).data, status=status.HTTP_201_CREATED) except EighthActivity.DoesNotExist: return Response({"error": "The activity does not exist"}, status=status.HTTP_400_BAD_REQUEST) except Exception: return Response({"error": "An unknown error occurred"}, status=status.HTTP_400_BAD_REQUEST)
[docs]class EighthScheduledActivitySignupList(views.APIView): """API endpoint that lists all signups for a certain scheduled activity.""" permission_classes = (IsAuthenticatedOrClientCredentials,)
[docs] def get(self, request, scheduled_activity_id): scheduled_activity = EighthScheduledActivity.objects.get(id=scheduled_activity_id) serializer = EighthScheduledActivitySerializer(scheduled_activity, context={"request": request}) return Response(serializer.data)
[docs]class EighthSignupDetail(generics.RetrieveAPIView): """API endpoint that shows details of an eighth signup.""" queryset = EighthSignup.objects.all() serializer_class = EighthSignupSerializer permission_classes = (IsAuthenticatedOrClientCredentials,)