chess_rpg_backend/game/api/v1/views.py

170 lines
5.7 KiB
Python

from rest_framework import status
from rest_framework.generics import GenericAPIView, UpdateAPIView
from rest_framework.mixins import (
CreateModelMixin,
RetrieveModelMixin,
ListModelMixin,
DestroyModelMixin,
UpdateModelMixin,
)
from rest_framework.response import Response
from game.authentication import PlayerAuthentication
from game.models import Hero, Deck
from game.api.v1.serializers import (
CreateHeroSerializer,
GetHeroSerializer,
CreatePlayerSerializer,
ListHeroSerializer,
CreateDeckSerializer,
GetDeckSerializer,
ObtainTokenPairSerializer,
)
from game.services.jwt import sign_jwt
class ListCreateHeroView(GenericAPIView, CreateModelMixin, ListModelMixin):
authentication_classes = (PlayerAuthentication,)
def perform_create(self, serializer):
return serializer.save()
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = self.perform_create(serializer)
return Response({"uuid": instance.uuid}, status=status.HTTP_201_CREATED)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def get_serializer_class(self):
if self.request.method == "GET":
return ListHeroSerializer
else:
return CreateHeroSerializer
def get_queryset(self):
return Hero.objects.filter(player_id=self.request.user.id)
class RetrieveHeroView(RetrieveModelMixin, UpdateAPIView, GenericAPIView):
serializer_class = GetHeroSerializer
lookup_field = "uuid"
queryset = Hero.objects.all()
def get_authenticators(self):
if self.request.method != "GET":
self.authentication_classes = [PlayerAuthentication]
return [auth() for auth in self.authentication_classes]
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
class PlayerCreateView(GenericAPIView, CreateModelMixin):
serializer_class = CreatePlayerSerializer
def perform_create(self, serializer):
return serializer.save()
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = self.perform_create(serializer)
access_jwt = sign_jwt({"id": instance.id, "type": "access"}, t_life=3600)
refresh_jwt = sign_jwt({"jit": instance.get_auth_session(), "type": "refresh"})
return Response(
{
"access_token": access_jwt,
"refresh_token": refresh_jwt,
"deck_id": instance.get_last_deck().id,
},
status=status.HTTP_201_CREATED,
)
class DeckCreateView(GenericAPIView, CreateModelMixin):
serializer_class = CreateDeckSerializer
authentication_classes = (PlayerAuthentication,)
def perform_create(self, serializer):
return serializer.save(player=self.request.user)
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = self.perform_create(serializer)
heroes_list = ListHeroSerializer(instance.get_heroes(), many=True)
heroes_list.data["deck_id"] = instance.id
return Response(heroes_list.data, status=status.HTTP_201_CREATED)
class RetireUpdateDeleteDeckView(
RetrieveHeroView, DestroyModelMixin, UpdateModelMixin, GenericAPIView
):
lookup_field = "id"
queryset = Deck.objects.all()
def get_serializer_class(self):
if self.request.method == "GET":
return GetDeckSerializer
else:
return CreateDeckSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def perform_update(self, serializer):
return serializer.update(self.get_object(), self.request.data)
def put(self, request, *args, **kwargs):
if not self._check_user_identity(kwargs["id"]):
return Response(
"Attempt to change another user's deck",
status=status.HTTP_403_FORBIDDEN,
)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = self.perform_update(serializer)
heroes_list = ListHeroSerializer(instance.get_heroes(), many=True)
return Response(heroes_list.data, status=status.HTTP_200_OK)
def delete(self, request, *args, **kwargs):
if not self._check_user_identity(kwargs["id"]):
return Response(
"Attempt to delete another user's deck",
status=status.HTTP_403_FORBIDDEN,
)
self.destroy(request, *args, **kwargs)
return Response(
f"Destroyed deck with id {kwargs['id']}", status=status.HTTP_200_OK
)
def _check_user_identity(self, deck_id) -> bool:
return deck_id in list(
Deck.objects.filter(player_id=self.request.user.id).values_list(
"id", flat=True
)
)
class RefreshAuthKey(GenericAPIView):
serializer_class = ObtainTokenPairSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
access_jwt = sign_jwt(
{"id": serializer.player_id, "type": "access"}, t_life=3600
)
return Response({"access_token": access_jwt}, status=status.HTTP_200_OK)