Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions src/baby_serverlist/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,41 @@ class ServerStatusSerializer(serializers.Serializer):
GoodFileVersion = serializers.CharField()


class ActiveServersSerializer(serializers.Serializer):
CashDateTime = serializers.DateTimeField()
servers = ServerStatusSerializer(many=True)
class CachedServerStatusSerializer(serializers.Serializer):
Passworded = serializers.BooleanField()
ServerName = serializers.CharField()
ForkName = serializers.CharField()
BuildVersion = serializers.IntegerField()
CurrentMap = serializers.CharField()
GameMode = serializers.CharField()
IngameTime = serializers.CharField()
RoundTime = serializers.CharField()
PlayerCount = serializers.IntegerField()
PlayerCountMax = serializers.IntegerField()
ServerIP = serializers.CharField()
ServerPort = serializers.IntegerField()
WinDownload = serializers.CharField()
OSXDownload = serializers.CharField()
LinuxDownload = serializers.CharField()
fps = serializers.IntegerField()
GoodFileVersion = serializers.CharField()


class OwnedBabyServerSerializer(serializers.Serializer):
id = serializers.UUIDField()
whitelisted = serializers.BooleanField()
live = serializers.BooleanField()
status = CachedServerStatusSerializer(allow_null=True)


class BabyServerTokenSerializer(serializers.Serializer):
id = serializers.UUIDField()
serverlist_token = serializers.CharField()
whitelisted = serializers.BooleanField()


class BabyServerStatusListSerializer(serializers.Serializer):
servers = CachedServerStatusSerializer(many=True)


class RegenerateServerlistTokenSerializer(serializers.Serializer):
Expand Down
66 changes: 59 additions & 7 deletions src/baby_serverlist/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import cast

from django.core import signing
from drf_spectacular.utils import OpenApiResponse, extend_schema, extend_schema_view
from rest_framework import status
from rest_framework.generics import GenericAPIView, ListAPIView
from rest_framework.permissions import AllowAny
Expand All @@ -12,19 +13,38 @@
from accounts.models import Account
from baby_serverlist.models import SERVERLIST_TOKEN_SALT, BabyServer
from commons.cache import (
get_baby_server_status,
get_many_baby_server_statuses,
set_baby_server_heartbeat,
set_baby_server_status,
)
from commons.error_response import ErrorResponse

from .serializers import RegenerateServerlistTokenSerializer, ServerStatusSerializer
from .serializers import (
BabyServerStatusListSerializer,
BabyServerTokenSerializer,
OwnedBabyServerSerializer,
RegenerateServerlistTokenSerializer,
ServerStatusSerializer,
)

logger = logging.getLogger(__name__)


@extend_schema_view(
post=extend_schema(
request=ServerStatusSerializer,
responses={
200: OpenApiResponse(description="Status accepted and cached"),
400: OpenApiResponse(description="Invalid payload or signature"),
},
)
)
class PostServerStatusView(GenericAPIView):
"""Accepts signed status payloads from baby servers and stores the latest state in cache."""
"""Accepts signed status payloads from baby servers and stores the latest state in cache.

*** Public Endpoint ***
"""

serializer_class = ServerStatusSerializer
permission_classes = (AllowAny,)
Expand Down Expand Up @@ -59,14 +79,21 @@ def post(self, request, *args, **kwargs):
return Response(status=status.HTTP_200_OK)


@extend_schema_view(
post=extend_schema(
responses={201: BabyServerTokenSerializer},
)
)
class CreateBabyServerView(GenericAPIView):
"""Creates a new baby server for the authenticated user and returns the freshly minted token."""
"""Creates a new baby server for the authenticated user and returns the freshly minted token.

*** Requires Token Authentication. ***
"""

queryset = BabyServer.objects.all()

def post(self, request, *args, **kwargs):
user = cast(Account, request.user)

baby_server = BabyServer.objects.create(owner=user)

return Response(
Expand All @@ -79,8 +106,16 @@ def post(self, request, *args, **kwargs):
)


@extend_schema_view(
list=extend_schema(
responses={200: OwnedBabyServerSerializer(many=True)},
)
)
class ListOwnedBabyServersView(ListAPIView):
"""Lists the caller's baby servers with a derived `live` flag based on recent heartbeats."""
"""Lists the caller's baby servers with a derived `live` flag based on recent heartbeats.

*** Requires Token Authentication. ***
"""

def get_queryset(self):
user = cast(Account, self.request.user)
Expand All @@ -94,14 +129,23 @@ def list(self, request, *args, **kwargs):
"id": str(server.id),
"whitelisted": server.whitelisted,
"live": server.is_live(),
"status": get_baby_server_status(server.id),
}
for server in queryset
]
return Response(data, status=status.HTTP_200_OK)


@extend_schema_view(
list=extend_schema(
responses={200: BabyServerStatusListSerializer},
)
)
class ListBabyServersView(ListAPIView):
"""Return cached status payloads for all baby servers that have reported recently."""
"""Return cached status payloads for all baby servers that have reported recently.

*** Public Endpoint ***
"""

permission_classes = (AllowAny,)

Expand All @@ -117,8 +161,16 @@ def list(self, request, *args, **kwargs):
return Response({"servers": data}, status=status.HTTP_200_OK)


@extend_schema_view(
post=extend_schema(
responses={200: BabyServerTokenSerializer},
)
)
class RegenerateServerlistTokenView(GenericAPIView):
"""Regenerates a server's signed token after validating ownership."""
"""Regenerates a server's signed token after validating ownership.

*** Requires Token Authentication. ***
"""

serializer_class = RegenerateServerlistTokenSerializer
queryset = BabyServer.objects.all()
Expand Down
Loading