endpoints for creating projects and versions, other fixes

This commit is contained in:
Ethan Roseman 2022-08-28 22:59:52 +09:00
parent 1899828ba5
commit c98e43d087
No known key found for this signature in database
GPG Key ID: 27F9FCEB8E4969BD
6 changed files with 106 additions and 17 deletions

View File

@ -10,7 +10,7 @@ class VersionSerializer(serializers.HyperlinkedModelSerializer):
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
versions = VersionSerializer(many=True)
versions = VersionSerializer(many=True, read_only=True)
class Meta:
model = Project

View File

@ -1,5 +1,6 @@
from rest_framework import serializers
from frog_api.models import AUTH_KEY_LEN
from frog_api.serializers.model_serializers import ProjectSerializer, VersionSerializer
class ApiKeySerializer(serializers.CharField):
@ -7,6 +8,16 @@ class ApiKeySerializer(serializers.CharField):
max_length = AUTH_KEY_LEN
class CreateProjectSerializer(serializers.Serializer): # type:ignore
api_key = ApiKeySerializer()
project = ProjectSerializer()
class CreateVersionSerializer(serializers.Serializer): # type:ignore
api_key = ApiKeySerializer()
version = VersionSerializer()
# Classes for valdating requests to create new entries
class CreateEntrySerializer(serializers.Serializer): # type:ignore
timestamp = serializers.IntegerField()

View File

@ -27,7 +27,7 @@ class CreateCategoriesTests(APITestCase):
version.save()
response = self.client.post(
reverse("category-structure", args=[project.slug, version.slug]),
reverse("version-structure", args=[project.slug, version.slug]),
create_json,
format="json",
)

View File

@ -3,19 +3,26 @@ from frog_api.views import data, structure
urlpatterns = [
# structure (/project)
path(
"projects/",
structure.ProjectStructureView.as_view(),
),
re_path(
"projects/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
structure.CategoryStructureView.as_view(),
name="category-structure",
structure.VersionStructureView.as_view(),
name="version-structure",
),
re_path(
"projects/(?P<project_slug>.+)/$",
structure.ProjectStructureView.as_view(),
name="project-structure",
),
path(
"projects/",
structure.RootStructureView.as_view(),
name="root-structure",
),
# data (/data)
re_path(
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/(?P<category_slug>.+)/$",
data.CategoryDataView.as_view(),
name="category-data",
),
re_path(
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
@ -25,9 +32,11 @@ urlpatterns = [
re_path(
"data/(?P<project_slug>.+)/$",
data.ProjectDataView.as_view(),
name="project-data",
),
path(
"data/",
data.RootDataView.as_view(),
name="root-data",
),
]

View File

@ -29,6 +29,13 @@ def get_category(slug: str, version: Version) -> Category:
return ret
def validate_ultimate_api_key(key: str) -> bool:
if key == ULTIMATE_API_KEY:
return True
else:
raise InvalidAPIKeyException()
def validate_api_key(key: str, project: Project) -> bool:
if key == ULTIMATE_API_KEY or key == project.auth_key:
return True

View File

@ -2,31 +2,93 @@ from typing import Any
from django.db import models
from frog_api.exceptions import AlreadyExistsException
from frog_api.models import Category, Project
from frog_api.models import Category, Project, Version
from frog_api.serializers.model_serializers import ProjectSerializer
from frog_api.serializers.request_serializers import CreateCategoriesSerializer
from frog_api.views.common import get_project, get_version, validate_api_key
from frog_api.serializers.request_serializers import (
CreateCategoriesSerializer,
CreateProjectSerializer,
CreateVersionSerializer,
)
from frog_api.views.common import (
get_project,
get_version,
validate_api_key,
validate_ultimate_api_key,
)
from rest_framework import status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from frog_api.views.data import DEFAULT_CATEGORY_NAME, DEFAULT_CATEGORY_SLUG
class ProjectStructureView(APIView):
class RootStructureView(APIView):
"""
API endpoint that allows projects to be viewed.
API endpoint that allows the structure of the database to be viewed or edited.
"""
def get(self, request: Request) -> Response:
"""
Return a list of all projects.
Return a digest of the database structure.
"""
projects = Project.objects.all()
serializer = ProjectSerializer(projects, many=True)
return Response(serializer.data)
def post(self, request: Request) -> Response:
"""
Create a new project.
"""
request_ser = CreateProjectSerializer(data=request.data)
class CategoryStructureView(APIView):
validate_ultimate_api_key(request_ser.data["api_key"])
if request_ser.is_valid():
request_ser.project.save()
return Response(request_ser.project.data, status=status.HTTP_201_CREATED)
return Response(request_ser.errors, status=status.HTTP_400_BAD_REQUEST)
class ProjectStructureView(APIView):
"""
API endpoint for adding a new version
"""
def post(self, request: Request, project_slug: str) -> Response:
request_ser = CreateVersionSerializer(data=request.data)
project = get_project(project_slug)
validate_api_key(request_ser.data["api_key"], project)
if request_ser.is_valid():
if Version.objects.filter(
slug=request_ser.data["version"]["slug"], project=project
).exists():
raise AlreadyExistsException(
f"Version with slug {request_ser.data['version']['slug']} already exists"
)
version = Version(
project=project,
slug=request_ser.data["version"]["slug"],
name=request_ser.data["version"]["name"],
)
version.save()
# Create the default category
default_cat = Category(
version=version,
slug=DEFAULT_CATEGORY_SLUG,
name=DEFAULT_CATEGORY_NAME,
)
default_cat.save()
return Response(request_ser.version.data, status=status.HTTP_201_CREATED)
return Response(request_ser.errors, status=status.HTTP_400_BAD_REQUEST)
class VersionStructureView(APIView):
"""
API endpoint for adding new categories
"""
@ -51,7 +113,7 @@ class CategoryStructureView(APIView):
for cat, name in categories.items():
if Category.objects.filter(slug=cat, version=version).exists():
raise AlreadyExistsException(
f"Category {cat} already exists for project '{project_slug}', version '{version_slug}'"
f"Category '{cat}' already exists for project '{project_slug}', version '{version_slug}'"
)
to_save.append(Category(version=version, slug=cat, name=name))
@ -61,7 +123,7 @@ class CategoryStructureView(APIView):
return len(to_save)
def post(self, request: Request, project_slug: str, version_slug: str) -> Response:
result = CategoryStructureView.create_categories(
result = VersionStructureView.create_categories(
request.data, project_slug, version_slug
)