-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3948 from open-formulieren/feature/3825-public-api
Public API endpoints
- Loading branch information
Showing
13 changed files
with
247 additions
and
0 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
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,7 @@ | ||
from django.urls import include, path | ||
|
||
app_name = "public" | ||
|
||
urlpatterns = [ | ||
path("forms/", include("openforms.forms.api.public_api.urls")), | ||
] |
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
Empty file.
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,10 @@ | ||
from django_filters import rest_framework as filters | ||
|
||
from ...models import Form | ||
|
||
|
||
class FormCategoryNameFilter(filters.FilterSet): | ||
|
||
class Meta: | ||
model = Form | ||
fields = ("category__uuid",) |
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,18 @@ | ||
from rest_framework.pagination import BasePagination | ||
from rest_framework.response import Response | ||
|
||
|
||
class NoPagination(BasePagination): | ||
def paginate_queryset(self, queryset, request, view=None): | ||
return queryset | ||
|
||
def get_paginated_response(self, data): | ||
return Response({"results": data}) | ||
|
||
def get_paginated_response_schema(self, schema): | ||
return { | ||
"type": "object", | ||
"properties": { | ||
"results": schema, | ||
}, | ||
} |
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,6 @@ | ||
from rest_framework.permissions import BasePermission | ||
|
||
|
||
class ViewFormPermission(BasePermission): | ||
def has_permission(self, request, view): | ||
return request.user.has_perm("forms.view_form") |
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,16 @@ | ||
from rest_framework import serializers | ||
|
||
from ...models import Form | ||
|
||
|
||
class FormSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = Form | ||
fields = ( | ||
"uuid", | ||
"name", | ||
"internal_name", | ||
"slug", | ||
) | ||
ref_name = "PublicForm" |
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,13 @@ | ||
from django.urls import path | ||
|
||
from .views import FormListView | ||
|
||
app_name = "forms" | ||
|
||
urlpatterns = [ | ||
path( | ||
"", | ||
FormListView.as_view(), | ||
name="forms-list", | ||
), | ||
] |
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,30 @@ | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from drf_spectacular.utils import extend_schema, extend_schema_view | ||
from rest_framework import permissions | ||
from rest_framework.authentication import TokenAuthentication | ||
from rest_framework.generics import ListAPIView | ||
|
||
from ...models import Form | ||
from .filters import FormCategoryNameFilter | ||
from .pagination import NoPagination | ||
from .permissions import ViewFormPermission | ||
from .serializers import FormSerializer | ||
|
||
|
||
@extend_schema_view( | ||
get=extend_schema( | ||
summary=_("List forms"), | ||
description=_( | ||
"List the available forms with minimal information. Does not include soft deleted forms." | ||
), | ||
), | ||
) | ||
class FormListView(ListAPIView): | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (permissions.IsAuthenticated, ViewFormPermission) | ||
|
||
serializer_class = FormSerializer | ||
filterset_class = FormCategoryNameFilter | ||
queryset = Form.objects.filter(_is_deleted=False) | ||
pagination_class = NoPagination |
Empty file.
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,74 @@ | ||
from rest_framework import status | ||
from rest_framework.reverse import reverse | ||
from rest_framework.test import APITestCase | ||
|
||
from openforms.accounts.tests.factories import TokenFactory, UserFactory | ||
|
||
from ..factories import CategoryFactory, FormFactory | ||
|
||
|
||
class TestPublicFormEndpoint(APITestCase): | ||
@classmethod | ||
def setUpTestData(cls): | ||
super().setUpTestData() | ||
|
||
user = UserFactory.create(user_permissions=["forms.view_form"]) | ||
|
||
blue_cat = CategoryFactory.create(name="Blue") | ||
red_cat = CategoryFactory.create(name="Red") | ||
|
||
FormFactory.create(slug="deleted-form", deleted_=True) | ||
FormFactory.create(slug="1-form", category=blue_cat) | ||
FormFactory.create(slug="2-form", category=blue_cat) | ||
FormFactory.create(slug="3-form", category=red_cat) | ||
|
||
cls.blue_cat = blue_cat | ||
cls.user = user | ||
|
||
def test_cant_access_without_token(self): | ||
response = self.client.get( | ||
reverse( | ||
"api:public:forms:forms-list", | ||
) | ||
) | ||
|
||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) | ||
|
||
def test_cant_access_without_view_form_permission(self): | ||
token = TokenFactory() | ||
|
||
response = self.client.get( | ||
reverse( | ||
"api:public:forms:forms-list", | ||
), | ||
HTTP_AUTHORIZATION=f"Token {token.key}", | ||
) | ||
|
||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) | ||
|
||
def test_deleted_forms_not_included(self): | ||
token = TokenFactory(user=self.user) | ||
|
||
response = self.client.get( | ||
reverse( | ||
"api:public:forms:forms-list", | ||
), | ||
HTTP_AUTHORIZATION=f"Token {token.key}", | ||
) | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
self.assertEqual(len(response.data["results"]), 3) | ||
|
||
def test_filter_on_category_uuid(self): | ||
token = TokenFactory(user=self.user) | ||
|
||
response = self.client.get( | ||
reverse( | ||
"api:public:forms:forms-list", | ||
), | ||
data={"category__uuid": str(self.blue_cat.uuid)}, | ||
HTTP_AUTHORIZATION=f"Token {token.key}", | ||
) | ||
|
||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
self.assertEqual(len(response.data["results"]), 2) |