Skip to content

Commit

Permalink
add ModelView API for CatalogEntry
Browse files Browse the repository at this point in the history
Signed-off-by: Akihiko Kuroda <[email protected]>
  • Loading branch information
akihikokuroda committed Jan 31, 2024
1 parent dabd9bc commit 62f8330
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 4 deletions.
11 changes: 11 additions & 0 deletions gateway/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,14 @@ def has_object_permission(self, request, view, obj):
if isinstance(obj, RuntimeJob):
return obj.job.author == request.user
return obj.author == request.user


class CatalogUpdate(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to update it.
"""

def has_object_permission(self, request, view, obj):
if request.method == "GET":
return True
return obj.program.author == request.user
11 changes: 10 additions & 1 deletion gateway/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from django.conf import settings
from rest_framework import serializers
from .models import Program, Job, JobConfig, RuntimeJob
from .models import Program, Job, JobConfig, RuntimeJob, CatalogEntry


class JobConfigSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -87,3 +87,12 @@ class RuntimeJobSerializer(serializers.ModelSerializer):

class Meta:
model = RuntimeJob


class CatalogEntrySerializer(serializers.ModelSerializer):
"""
Serializer for the catalog entry model.
"""

class Meta:
model = CatalogEntry
11 changes: 11 additions & 0 deletions gateway/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,14 @@ class RuntimeJobSerializer(serializers.RuntimeJobSerializer):

class Meta(serializers.RuntimeJobSerializer.Meta):
fields = ["job", "runtime_job"]


class CatalogEntrySerializer(serializers.CatalogEntrySerializer):
"""
Catalog entry serializer first version. Serializer for the catalog entry model.
"""

program = ProgramSerializer(many=False)

class Meta(serializers.CatalogEntrySerializer.Meta):
fields = ["id", "title", "description", "tags", "created", "updated", "program"]
5 changes: 5 additions & 0 deletions gateway/api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,10 @@
v1_views.RuntimeJobViewSet,
basename=v1_views.RuntimeJobViewSet.BASE_NAME,
)
router.register(
r"catalog_entries",
v1_views.CatalogEntryViewSet,
basename=v1_views.CatalogEntryViewSet.BASE_NAME,
)

urlpatterns = router.urls
21 changes: 19 additions & 2 deletions gateway/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@


from api import views
from api.models import Program, Job, RuntimeJob
from api.permissions import IsOwner
from api.models import Program, Job, RuntimeJob, CatalogEntry
from api.permissions import IsOwner, CatalogUpdate
from . import serializers as v1_serializers
from . import services as v1_services

Expand Down Expand Up @@ -83,3 +83,20 @@ def get_serializer_class(self):

def get_queryset(self):
return RuntimeJob.objects.all().filter(job__author=self.request.user)


class CatalogEntryViewSet(
views.CatalogEntryViewSet
): # pylint: disable=too-many-ancestors
"""
CatalogEntry view set first version. Use CatalogEntrySerializer V1.
"""

serializer_class = v1_serializers.CatalogEntrySerializer
permission_classes = [permissions.IsAuthenticated, CatalogUpdate]

def get_serializer_class(self):
return v1_serializers.CatalogEntrySerializer

def get_queryset(self):
return CatalogEntry.objects.all()
16 changes: 15 additions & 1 deletion gateway/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from utils import sanitize_file_path

from .exceptions import InternalServerErrorException, ResourceNotFoundException
from .models import Program, Job, RuntimeJob
from .models import Program, Job, RuntimeJob, CatalogEntry
from .ray import get_job_handler
from .serializers import JobSerializer, ExistingProgramSerializer, JobConfigSerializer
from .services import JobService, ProgramService, JobConfigService
Expand Down Expand Up @@ -521,3 +521,17 @@ def get_serializer_class(self):

def get_queryset(self):
return RuntimeJob.objects.all().filter(job__author=self.request.user)


class CatalogEntryViewSet(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
"""
CatalogEntry ViewSet configuration using ModelViewSet.
"""

BASE_NAME = "catalog_entries"

def get_serializer_class(self):
return self.serializer_class

def get_queryset(self):
return CatalogEntry.objects.all()
87 changes: 87 additions & 0 deletions gateway/tests/api/test_v1_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,90 @@ def test_list_runtimejob(self):
format="json",
)
self.assertEqual(programs_response.json(), '["runtime_job_3"]')

def test_catalog_entry(self):
"""Tests catalog entry."""

# Non-owner
auth = reverse("rest_login")
response = self.client.post(
auth, {"username": "test_user_2", "password": "123"}, format="json"
)
token_2 = response.data.get("access")
self.client.credentials(HTTP_AUTHORIZATION="Bearer " + token_2)

# list catalog
programs_response = self.client.get(
"/api/v1/catalog_entries/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)
self.assertEqual(programs_response.json().get("count"), 2)

id = programs_response.json()["results"][0]["id"]
programs_response = self.client.get(
"/api/v1/catalog_entries/" + str(id) + "/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)

# Update catalog
programs_response = self.client.patch(
"/api/v1/catalog_entries/" + str(id) + "/",
data={"tags": "newtag"},
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_403_FORBIDDEN)

# Program owner
auth = reverse("rest_login")
response = self.client.post(
auth, {"username": "test_user", "password": "123"}, format="json"
)
token = response.data.get("access")
self.client.credentials(HTTP_AUTHORIZATION="Bearer " + token)

# list catalog
programs_response = self.client.get(
"/api/v1/catalog_entries/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)
self.assertEqual(programs_response.json().get("count"), 2)

id = programs_response.json()["results"][0]["id"]
programs_response = self.client.get(
"/api/v1/catalog_entries/" + str(id) + "/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)

# Update catalog
programs_response = self.client.patch(
"/api/v1/catalog_entries/" + str(id) + "/",
data={"tags": "newtag"},
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)

programs_response = self.client.get(
"/api/v1/catalog_entries/" + str(id) + "/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)
self.assertEqual(programs_response.json()["tags"], "newtag")

# delete catalog
programs_response = self.client.delete(
"/api/v1/catalog_entries/" + str(id) + "/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_204_NO_CONTENT)

programs_response = self.client.get(
"/api/v1/catalog_entries/",
format="json",
)
self.assertEqual(programs_response.status_code, status.HTTP_200_OK)
self.assertEqual(programs_response.json().get("count"), 1)
self.assertNotEqual(programs_response.json()["results"][0]["id"], id)
23 changes: 23 additions & 0 deletions gateway/tests/fixtures/fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,28 @@
"job": "1a7947f9-6ae8-4e3d-ac1e-e7d608deec84",
"runtime_job": "runtime_job_5"
}
},
{
"model": "api.catalogentry",
"fields": {
"title": "CatalogEntry1",
"description": "tast catalog entry 1",
"tags": "tag1, tag2",
"created": "2023-02-01T15:30:43.281796Z",
"updated": "2023-02-03T15:30:43.281796Z",
"program": "1a7947f9-6ae8-4e3d-ac1e-e7d608deec82"
}
},
{
"model": "api.catalogentry",
"fields": {
"title": "CatalogEntry2",
"description": "tast catalog entry 2",
"tags": "tag3",
"created": "2023-03-01T15:30:43.281796Z",
"updated": "2023-03-03T15:30:43.281796Z",
"program": "1a7947f9-6ae8-4e3d-ac1e-e7d608deec82"
}
}
]

0 comments on commit 62f8330

Please sign in to comment.