Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/oas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ jobs:
openapi-to-postman-version: '^5.0.0'
postman-artifact-name: objects-api-postman-collection
openapi-generator-version: '^2.20.0'
spectral-ruleset: https://static.developer.overheid.nl/adr/2.1/ruleset.yaml
2 changes: 2 additions & 0 deletions docs/manual/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Objects API
* ``search_failed_for_datastore``: attempted to perform ``jsonpath`` search for a backend that does not support this operation. Additional context: ``exc_info``.
* ``object_created``: created an ``Object`` via the API. Additional context: ``object_uuid``, ``objecttype_uuid``, ``objecttype_version``, ``token_identifier``, ``token_application``.
* ``object_updated``: updated an ``Object`` via the API. Additional context: ``object_uuid``, ``objecttype_uuid``, ``objecttype_version``, ``token_identifier``, ``token_application``.
* ``deprecated_endpoint_called``: a deprecated endpoint was called. Additional context: ``endpoint``.

Objecttypes API
~~~~~~~~~~~~~~~
Expand All @@ -73,6 +74,7 @@ Objecttypes API
* ``object_version_created``: created an ``Object_version`` via the API. Additional context: ``version``, ``objecttype_uuid``, ``token_identifier``, ``token_application``.
* ``object_version_updated``: updated an ``Object_version`` via the API. Additional context: ``version``, ``objecttype_uuid``, ``token_identifier``, ``token_application``.
* ``object_version_deleted``: deleted an ``Object_version`` via the API. Additional context: ``version``, ``objecttype_uuid``, ``token_identifier``, ``token_application``.
* ``deprecated_endpoint_called``: a deprecated endpoint was called. Additional context: ``endpoint``.

Setup configuration
~~~~~~~~~~~~~~~~~~~
Expand Down
54 changes: 54 additions & 0 deletions src/objects/api/v2/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
`objecten` channel.
contact:
url: https://github.com/maykinmedia/objects-api
email: support@maykinmedia.nl
name: Maykin Media
license:
name: EUPL-1.2
paths:
Expand Down Expand Up @@ -234,6 +236,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
X-Unauthorized-Fields:
schema:
type: string
Expand Down Expand Up @@ -297,6 +304,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand Down Expand Up @@ -345,6 +357,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
X-Unauthorized-Fields:
schema:
type: string
Expand Down Expand Up @@ -415,6 +432,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand Down Expand Up @@ -480,6 +502,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand All @@ -502,6 +529,12 @@
- tokenAuth: []
responses:
'204':
headers:
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
description: No response body
/objects/{uuid}/{index}:
get:
Expand Down Expand Up @@ -543,6 +576,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand Down Expand Up @@ -596,6 +634,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand Down Expand Up @@ -763,6 +806,11 @@
description: 'The ''Coordinate Reference System'' (CRS) of the request
data. According to the GeoJSON spec, WGS84 is the default (EPSG: 4326
is the same as WGS84).'
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand Down Expand Up @@ -792,6 +840,12 @@
- {}
responses:
'200':
headers:
API-version:
schema:
type: string
description: 'Geeft een specifieke API-versie aan in de context van
een specifieke aanroep. Voorbeeld: 1.2.1.'
content:
application/json:
schema:
Expand All @@ -799,7 +853,7 @@
description: OK
components:
schemas:
GeoJSONGeometry:

Check warning on line 856 in src/objects/api/v2/openapi.yaml

View workflow job for this annotation

GitHub Actions / Checks / Lint OAS

schema-camel-case Schema name should be CamelCase in #/components/schemas/GeoJSONGeometry
title: GeoJSONGeometry
type: object
oneOf:
Expand Down Expand Up @@ -1248,7 +1302,7 @@
name: Authorization
description: Token-based authentication with required prefix "Token"
servers:
- url: /api/v2

Check warning on line 1305 in src/objects/api/v2/openapi.yaml

View workflow job for this annotation

GitHub Actions / Checks / Lint OAS

servers-use-https Server URL /api/v2 "/api/v2" must match the pattern "^https://.*".
tags:
- name: objects
- name: permissions
Expand Down
23 changes: 17 additions & 6 deletions src/objects/api/v2/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from django.urls import include, path

from drf_spectacular.views import (
SpectacularJSONAPIView,
SpectacularRedocView,
SpectacularYAMLAPIView,
)
from rest_framework import routers

from objects.utils.oas_extensions.views import (
DeprecationRedirectView,
SpectacularJSONAPIView,
SpectacularYAMLAPIView,
)

from .views import ObjectViewSet, PermissionViewSet

router = routers.DefaultRouter(trailing_slash=False)
Expand All @@ -16,20 +20,27 @@
app_name = "v2"

urlpatterns = [
path("", SpectacularJSONAPIView.as_view(), name="schema-json"),
path(
"/",
include(
[
# schema
path(
"schema/openapi.yaml",
DeprecationRedirectView.as_view(pattern_name="v2:schema-yaml"),
),
path(
"openapi.yaml",
SpectacularYAMLAPIView.as_view(),
name="schema",
name="schema-yaml",
),
path(
"openapi.json",
SpectacularJSONAPIView.as_view(),
name="schema-json",
),
path(
"schema/",
SpectacularRedocView.as_view(url_name="schema"),
SpectacularRedocView.as_view(url_name="schema-yaml"),
name="schema-redoc",
),
# actual endpoints
Expand Down
2 changes: 2 additions & 0 deletions src/objects/conf/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
"SERVE_INCLUDE_SCHEMA": False,
"CONTACT": {
"url": "https://github.com/maykinmedia/objects-api",
"email": "support@maykinmedia.nl",
"name": "Maykin Media",
},
"LICENSE": {"name": "EUPL-1.2"},
"EXTERNAL_DOCS": {
Expand Down
4 changes: 3 additions & 1 deletion src/objects/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
"objects.utils",
]


MIDDLEWARE += [
"vng_api_common.middleware.APIVersionHeaderMiddleware",
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

Expand Down
2 changes: 1 addition & 1 deletion src/objects/tests/v2/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@


class APISchemaTest(APITestCase):
def test_schema_endoint(self):
def test_schema_endpoint(self):
response = self.client.get(reverse("schema-redoc"))
self.assertEqual(response.status_code, status.HTTP_200_OK)
30 changes: 29 additions & 1 deletion src/objects/utils/autoschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from drf_spectacular.openapi import AutoSchema as _AutoSchema
from drf_spectacular.plumbing import build_parameter_type, get_view_model
from drf_spectacular.utils import OpenApiParameter
from vng_api_common.constants import VERSION_HEADER
from vng_api_common.geo import DEFAULT_CRS, HEADER_ACCEPT, HEADER_CONTENT
from vng_api_common.schema import HTTP_STATUS_CODE_TITLES

Expand All @@ -18,6 +19,14 @@


class AutoSchema(_AutoSchema):
def get_response_serializers(
self,
):
if self.method == "DELETE":
return {204: None}

return super().get_response_serializers()

def get_operation_id(self):
"""
Use model name as a base for operation_id
Expand All @@ -29,10 +38,15 @@ def get_operation_id(self):

def get_override_parameters(self):
"""Add request GEO headers"""
params = super().get_override_parameters()

geo_headers = self.get_geo_headers()
content_type_headers = self.get_content_type_headers()
version_headers = self.get_version_headers()
field_params = self.get_fields_params()
return geo_headers + content_type_headers + field_params
return (
params + geo_headers + content_type_headers + version_headers + field_params
)

def _get_filter_parameters(self):
"""remove filter parameters from all actions except LIST"""
Expand Down Expand Up @@ -121,6 +135,20 @@ def get_content_type_headers(self) -> list:
)
]

def get_version_headers(self) -> list[OpenApiParameter]:
return [
OpenApiParameter(
name=VERSION_HEADER,
type=str,
location=OpenApiParameter.HEADER,
description=_(
"Geeft een specifieke API-versie aan in de context van "
"een specifieke aanroep. Voorbeeld: 1.2.1."
),
response=True,
)
]

def get_fields_params(self) -> list[OpenApiParameter]:
if self.method != "GET":
return []
Expand Down
33 changes: 33 additions & 0 deletions src/objects/utils/oas_extensions/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.views.generic import RedirectView

import structlog
from drf_spectacular.views import (
SpectacularJSONAPIView as _SpectacularJSONAPIView,
SpectacularYAMLAPIView as _SpectacularYAMLAPIView,
)

logger = structlog.stdlib.get_logger(__name__)


class AllowAllOriginsMixin:
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
response["Access-Control-Allow-Origin"] = "*"
return response


class SpectacularYAMLAPIView(AllowAllOriginsMixin, _SpectacularYAMLAPIView):
"""Spectacular YAML API view with Access-Control-Allow-Origin set to allow all"""


class SpectacularJSONAPIView(AllowAllOriginsMixin, _SpectacularJSONAPIView):
"""Spectacular JSON API view with Access-Control-Allow-Origin set to allow all"""


class DeprecationRedirectView(RedirectView):
def get(self, request, *args, **kwargs):
logger.warning(
"deprecated_endpoint_called",
endpoint=request.path,
)
return super().get(request, *args, **kwargs)