endpoints for creating projects and versions, other fixes
This commit is contained in:
parent
1899828ba5
commit
c98e43d087
|
@ -10,7 +10,7 @@ class VersionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
|
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
versions = VersionSerializer(many=True)
|
versions = VersionSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Project
|
model = Project
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from frog_api.models import AUTH_KEY_LEN
|
from frog_api.models import AUTH_KEY_LEN
|
||||||
|
from frog_api.serializers.model_serializers import ProjectSerializer, VersionSerializer
|
||||||
|
|
||||||
|
|
||||||
class ApiKeySerializer(serializers.CharField):
|
class ApiKeySerializer(serializers.CharField):
|
||||||
|
@ -7,6 +8,16 @@ class ApiKeySerializer(serializers.CharField):
|
||||||
max_length = AUTH_KEY_LEN
|
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
|
# Classes for valdating requests to create new entries
|
||||||
class CreateEntrySerializer(serializers.Serializer): # type:ignore
|
class CreateEntrySerializer(serializers.Serializer): # type:ignore
|
||||||
timestamp = serializers.IntegerField()
|
timestamp = serializers.IntegerField()
|
||||||
|
|
|
@ -27,7 +27,7 @@ class CreateCategoriesTests(APITestCase):
|
||||||
version.save()
|
version.save()
|
||||||
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse("category-structure", args=[project.slug, version.slug]),
|
reverse("version-structure", args=[project.slug, version.slug]),
|
||||||
create_json,
|
create_json,
|
||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,19 +3,26 @@ from frog_api.views import data, structure
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# structure (/project)
|
# structure (/project)
|
||||||
path(
|
|
||||||
"projects/",
|
|
||||||
structure.ProjectStructureView.as_view(),
|
|
||||||
),
|
|
||||||
re_path(
|
re_path(
|
||||||
"projects/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
|
"projects/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
|
||||||
structure.CategoryStructureView.as_view(),
|
structure.VersionStructureView.as_view(),
|
||||||
name="category-structure",
|
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)
|
# data (/data)
|
||||||
re_path(
|
re_path(
|
||||||
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/(?P<category_slug>.+)/$",
|
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/(?P<category_slug>.+)/$",
|
||||||
data.CategoryDataView.as_view(),
|
data.CategoryDataView.as_view(),
|
||||||
|
name="category-data",
|
||||||
),
|
),
|
||||||
re_path(
|
re_path(
|
||||||
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
|
"data/(?P<project_slug>.+)/(?P<version_slug>.+)/$",
|
||||||
|
@ -25,9 +32,11 @@ urlpatterns = [
|
||||||
re_path(
|
re_path(
|
||||||
"data/(?P<project_slug>.+)/$",
|
"data/(?P<project_slug>.+)/$",
|
||||||
data.ProjectDataView.as_view(),
|
data.ProjectDataView.as_view(),
|
||||||
|
name="project-data",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"data/",
|
"data/",
|
||||||
data.RootDataView.as_view(),
|
data.RootDataView.as_view(),
|
||||||
|
name="root-data",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,6 +29,13 @@ def get_category(slug: str, version: Version) -> Category:
|
||||||
return ret
|
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:
|
def validate_api_key(key: str, project: Project) -> bool:
|
||||||
if key == ULTIMATE_API_KEY or key == project.auth_key:
|
if key == ULTIMATE_API_KEY or key == project.auth_key:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -2,31 +2,93 @@ from typing import Any
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from frog_api.exceptions import AlreadyExistsException
|
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.model_serializers import ProjectSerializer
|
||||||
from frog_api.serializers.request_serializers import CreateCategoriesSerializer
|
from frog_api.serializers.request_serializers import (
|
||||||
from frog_api.views.common import get_project, get_version, validate_api_key
|
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 import status
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
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:
|
def get(self, request: Request) -> Response:
|
||||||
"""
|
"""
|
||||||
Return a list of all projects.
|
Return a digest of the database structure.
|
||||||
"""
|
"""
|
||||||
projects = Project.objects.all()
|
projects = Project.objects.all()
|
||||||
serializer = ProjectSerializer(projects, many=True)
|
serializer = ProjectSerializer(projects, many=True)
|
||||||
return Response(serializer.data)
|
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
|
API endpoint for adding new categories
|
||||||
"""
|
"""
|
||||||
|
@ -51,7 +113,7 @@ class CategoryStructureView(APIView):
|
||||||
for cat, name in categories.items():
|
for cat, name in categories.items():
|
||||||
if Category.objects.filter(slug=cat, version=version).exists():
|
if Category.objects.filter(slug=cat, version=version).exists():
|
||||||
raise AlreadyExistsException(
|
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))
|
to_save.append(Category(version=version, slug=cat, name=name))
|
||||||
|
|
||||||
|
@ -61,7 +123,7 @@ class CategoryStructureView(APIView):
|
||||||
return len(to_save)
|
return len(to_save)
|
||||||
|
|
||||||
def post(self, request: Request, project_slug: str, version_slug: str) -> Response:
|
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
|
request.data, project_slug, version_slug
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue