-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into SS-666-inform-notebooks-shut-down
- Loading branch information
Showing
18 changed files
with
351 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from django.http import JsonResponse | ||
from rest_framework import generics, viewsets | ||
from rest_framework.response import Response | ||
|
||
from studio.system_version import SystemVersion | ||
|
||
|
||
class OpenAPI(generics.GenericAPIView): | ||
""" | ||
The Open API basic API information endpoints. | ||
""" | ||
|
||
def get(self, request): | ||
print(f"Entered OpenAPI.get. Requested API version {request.version}") | ||
return Response({"hello": "world"}) | ||
|
||
|
||
class APIInfo(viewsets.GenericViewSet): | ||
""" | ||
The Open API basic API information endpoints, in accordance to the standard | ||
https://dev.dataportal.se/rest-api-profil/versionhantering | ||
:returns dict: A dictionary of app-info information. | ||
""" | ||
|
||
def get_api_info(self, request): | ||
print(f"Entered OpenAPI.get_api_info. Requested API version {request.version}") | ||
|
||
if request.version == "beta": | ||
data = { | ||
"apiName": "SciLifeLab Serve OpenAPI", | ||
"apiVersion": "beta", | ||
"apiReleased": "TODO", | ||
"apiDocumentation": "TODO", | ||
"apiStatus": "beta", | ||
"latest-api-version": "v1", | ||
} | ||
return JsonResponse(data) | ||
|
||
elif request.version == "v1": | ||
data = { | ||
"apiName": "SciLifeLab Serve OpenAPI", | ||
"apiVersion": "1.0.0", | ||
"apiReleased": "TODO", | ||
"apiDocumentation": "TODO", | ||
"apiStatus": "beta", | ||
"latest-api-version": "v1", | ||
} | ||
return JsonResponse(data) | ||
|
||
|
||
def are_you_there(request): | ||
""" | ||
Most simple API endpoint useful for testing | ||
and verifications. | ||
:returns bool: true | ||
""" | ||
return JsonResponse({"status": True}) | ||
|
||
|
||
def get_system_version(request): | ||
""" | ||
Gets the version of the deployed application. | ||
:returns dict: A dictionary of system version information. | ||
""" | ||
data = { | ||
"system-version": SystemVersion().get_gitref(), | ||
"build-date": SystemVersion().get_build_date(), | ||
"image-tag": SystemVersion().get_imagetag(), | ||
} | ||
return JsonResponse(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from django.db.models import Q | ||
from django.http import JsonResponse | ||
from django.shortcuts import get_object_or_404 | ||
from rest_framework import viewsets | ||
from rest_framework.exceptions import NotFound | ||
|
||
from apps.models import AppInstance, Apps | ||
|
||
|
||
class PublicAppsAPI(viewsets.ReadOnlyModelViewSet): | ||
""" | ||
The Public Apps API with read-only methods to get public apps information. | ||
""" | ||
|
||
def list(self, request): | ||
""" | ||
This endpoint gets a list of public apps. | ||
:returns list: A list of app information. | ||
""" | ||
print("PublicAppsAPI. Entered list method.") | ||
print(f"Requested API version {request.version}") | ||
|
||
queryset = ( | ||
AppInstance.objects.filter(~Q(state="Deleted"), access="public") | ||
.order_by("-updated_on")[:8] | ||
.values("id", "name", "app_id", "table_field", "description", "updated_on") | ||
) | ||
|
||
list_apps = list(queryset) | ||
for app in list_apps: | ||
add_data = Apps.objects.get(id=app["app_id"]) | ||
app["app_type"] = add_data.name | ||
data = {"data": list_apps} | ||
print("LIST: ", data) | ||
return JsonResponse(data) | ||
|
||
def retrieve(self, request, pk=None): | ||
""" | ||
This endpoint retrieves a single public app instance. | ||
:returns dict: A dict of app information. | ||
""" | ||
print(f"PublicAppsAPI. Entered retrieve method with pk = {pk}") | ||
print(f"Requested API version {self.request.version}") | ||
queryset = AppInstance.objects.all().values( | ||
"id", "name", "app_id", "table_field", "description", "updated_on", "access", "state" | ||
) | ||
app = get_object_or_404(queryset, pk=pk) | ||
if app["state"] == "Deleted": | ||
raise NotFound("this app has been deleted") | ||
if app["access"] != "public": | ||
raise NotFound() | ||
|
||
add_data = Apps.objects.get(id=app["app_id"]) | ||
app["app_type"] = add_data.name | ||
data = {"app": app} | ||
return JsonResponse(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import rest_framework.routers as drfrouters | ||
from django.conf.urls import include | ||
from django.urls import path | ||
from rest_framework_nested import routers | ||
|
||
from .common_api import APIInfo, are_you_there, get_system_version | ||
from .public_apps_api import PublicAppsAPI | ||
|
||
app_name = "openapi" | ||
|
||
router_drf = drfrouters.DefaultRouter() | ||
router = routers.SimpleRouter(trailing_slash=False) | ||
|
||
urlpatterns = [ | ||
path("", include(router_drf.urls)), | ||
path("", include(router.urls)), | ||
# Generic API endpoints | ||
path("are-you-there", are_you_there), | ||
path("system-version", get_system_version), | ||
path("api-info", APIInfo.as_view({"get": "get_api_info"})), | ||
# The Apps API | ||
path("public-apps", PublicAppsAPI.as_view({"get": "list"})), | ||
path("public-apps/<int:pk>", PublicAppsAPI.as_view({"get": "retrieve"})), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import json | ||
import os | ||
|
||
from rest_framework import status | ||
from rest_framework.test import APITestCase | ||
|
||
|
||
class OpenApiTests(APITestCase): | ||
"""Tests for the Open API generic base endpoints""" | ||
|
||
BASE_API_URL = "/openapi/v1/" | ||
|
||
def test_get_are_you_there(self): | ||
"""Tests the API endpoint /are-you-there""" | ||
url = os.path.join(self.BASE_API_URL, "are-you-there") | ||
response = self.client.get(url, format="json") | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
actual = json.loads(response.content) | ||
self.assertEqual(actual, {"status": True}) | ||
|
||
def test_get_system_version(self): | ||
"""Tests the API endpoint /system-version""" | ||
url = os.path.join(self.BASE_API_URL, "system-version") | ||
response = self.client.get(url, format="json") | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
print(response.content) | ||
actual = json.loads(response.content) | ||
assert actual["system-version"] == "" | ||
assert actual["build-date"] == "" | ||
assert actual["image-tag"] == "" | ||
|
||
def test_app_info(self): | ||
"""Tests the API endpoint /api-info""" | ||
url = os.path.join(self.BASE_API_URL, "api-info") | ||
response = self.client.get(url, format="json") | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
print(response.content) | ||
actual = json.loads(response.content) | ||
self.assertEqual(actual["apiName"], "SciLifeLab Serve OpenAPI") | ||
self.assertEqual(actual["apiVersion"], "1.0.0") | ||
self.assertEqual(actual["apiReleased"], "TODO") | ||
self.assertEqual(actual["apiDocumentation"], "TODO") | ||
self.assertEqual(actual["apiStatus"], "beta") | ||
self.assertEqual(actual["latest-api-version"], "v1") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import json | ||
import os | ||
from datetime import date, datetime | ||
|
||
from django.contrib.auth import get_user_model | ||
from rest_framework import status | ||
from rest_framework.test import APITestCase | ||
|
||
from apps.models import AppInstance, Apps | ||
from projects.models import Project | ||
|
||
User = get_user_model() | ||
|
||
test_user = {"username": "[email protected]", "email": "[email protected]", "password": "bar"} | ||
|
||
|
||
class PublicAppsApiTests(APITestCase): | ||
"""Tests for the public apps API resource endpoints""" | ||
|
||
BASE_API_URL = "/openapi/v1/" | ||
|
||
@classmethod | ||
def setUpTestData(cls): | ||
cls.user = User.objects.create_user(test_user["username"], test_user["email"], test_user["password"]) | ||
cls.project = Project.objects.create_project(name="test-perm", owner=cls.user, description="", repository="") | ||
cls.app = Apps.objects.create(name="Some App", slug="some-app") | ||
|
||
cls.app_instance = AppInstance.objects.create( | ||
access="public", | ||
owner=cls.user, | ||
name="test_app_instance_public", | ||
description="My app description", | ||
app=cls.app, | ||
project=cls.project, | ||
parameters={ | ||
"environment": {"pk": ""}, | ||
}, | ||
) | ||
|
||
def test_public_apps_list(self): | ||
"""Tests the API resource public-apps default endpoint (action list)""" | ||
url = os.path.join(self.BASE_API_URL, "public-apps") | ||
response = self.client.get(url, format="json") | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
print(response.content) | ||
actual = json.loads(response.content)["data"] | ||
self.assertEqual(len(actual), 1) | ||
|
||
app = actual[0] | ||
self.assertEqual(app["id"], self.app_instance.id) | ||
self.assertIsNotNone(app["name"]) | ||
self.assertEqual(app["name"], self.app_instance.name) | ||
self.assertTrue(app["app_id"] > 0) | ||
self.assertEqual(app["description"], self.app_instance.description) | ||
updated_on = datetime.fromisoformat(app["updated_on"][:-1]) | ||
self.assertEqual(datetime.date(updated_on), datetime.date(self.app_instance.updated_on)) | ||
self.assertEqual(app["app_type"], self.app_instance.app.name) | ||
|
||
def test_public_apps_single_app(self): | ||
"""Tests the API resource public-apps get single object""" | ||
id = str(self.app_instance.id) | ||
url = os.path.join(self.BASE_API_URL, "public-apps/", id) | ||
response = self.client.get(url, format="json") | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
print(response.content) | ||
actual = json.loads(response.content)["app"] | ||
print(type(actual)) | ||
|
||
self.assertEqual(actual["id"], self.app_instance.id) | ||
self.assertIsNotNone(actual["name"]) | ||
self.assertEqual(actual["name"], self.app_instance.name) | ||
self.assertTrue(actual["app_id"] > 0) | ||
self.assertEqual(actual["description"], self.app_instance.description) | ||
updated_on = datetime.fromisoformat(actual["updated_on"][:-1]) | ||
self.assertEqual(datetime.date(updated_on), datetime.date(self.app_instance.updated_on)) | ||
self.assertEqual(actual["app_type"], self.app_instance.app.name) | ||
|
||
def test_public_apps_single_app_notfound(self): | ||
"""Tests the API resource public-apps get single object for a non-existing id""" | ||
id = "-1" | ||
url = os.path.join(self.BASE_API_URL, "public-apps/", id) | ||
response = self.client.get(url, format="json") | ||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
from django.contrib.auth import get_user_model | ||
from rest_framework.authtoken.models import Token | ||
|
||
import os | ||
User = get_user_model() | ||
|
||
|
||
def run(*args): | ||
admin = User.objects.get(username="admin") | ||
if not User.objects.filter(email='[email protected]').exists(): | ||
User.objects.create_superuser('admin', '[email protected]', os.getenv("DJANGO_SUPERUSER_PASSWORD")) | ||
|
||
admin = User.objects.get(username="[email protected]") | ||
try: | ||
_ = Token.objects.get(user=admin) | ||
except Token.DoesNotExist: | ||
|
Oops, something went wrong.