Skip to content

Commit 74be4bb

Browse files
authored
Merge pull request #208 from maykinmedia/feature/adr-api-validation
📝 [open-api-workflows#30] use adr api linter
2 parents b98c18c + efba8fa commit 74be4bb

File tree

7 files changed

+146
-5
lines changed

7 files changed

+146
-5
lines changed

.github/workflows/oas.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ jobs:
2525
openapi-to-postman-version: '^5.0.0'
2626
postman-artifact-name: objecttypes-api-postman-collection
2727
openapi-generator-version: '^2.20.0'
28+
spectral-ruleset: https://static.developer.overheid.nl/adr/2.1/ruleset.yaml

src/objecttypes/api/v2/openapi.yaml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ info:
3434
3535
contact:
3636
url: https://github.com/maykinmedia/objecttypes-api
37+
name: Maykin Media
38+
email: support@maykinmedia.nl
3739
license:
3840
name: EUPL-1.2
3941
paths:
@@ -75,6 +77,12 @@ paths:
7577
- tokenAuth: []
7678
responses:
7779
'200':
80+
headers:
81+
API-version:
82+
schema:
83+
type: string
84+
description: 'Geeft een specifieke API-versie aan in de context van
85+
een specifieke aanroep. Voorbeeld: 1.2.1.'
7886
content:
7987
application/json:
8088
schema:
@@ -103,6 +111,12 @@ paths:
103111
- tokenAuth: []
104112
responses:
105113
'201':
114+
headers:
115+
API-version:
116+
schema:
117+
type: string
118+
description: 'Geeft een specifieke API-versie aan in de context van
119+
een specifieke aanroep. Voorbeeld: 1.2.1.'
106120
content:
107121
application/json:
108122
schema:
@@ -138,6 +152,12 @@ paths:
138152
- tokenAuth: []
139153
responses:
140154
'200':
155+
headers:
156+
API-version:
157+
schema:
158+
type: string
159+
description: 'Geeft een specifieke API-versie aan in de context van
160+
een specifieke aanroep. Voorbeeld: 1.2.1.'
141161
content:
142162
application/json:
143163
schema:
@@ -173,6 +193,12 @@ paths:
173193
- tokenAuth: []
174194
responses:
175195
'201':
196+
headers:
197+
API-version:
198+
schema:
199+
type: string
200+
description: 'Geeft een specifieke API-versie aan in de context van
201+
een specifieke aanroep. Voorbeeld: 1.2.1.'
176202
content:
177203
application/json:
178204
schema:
@@ -204,6 +230,12 @@ paths:
204230
- tokenAuth: []
205231
responses:
206232
'200':
233+
headers:
234+
API-version:
235+
schema:
236+
type: string
237+
description: 'Geeft een specifieke API-versie aan in de context van
238+
een specifieke aanroep. Voorbeeld: 1.2.1.'
207239
content:
208240
application/json:
209241
schema:
@@ -247,6 +279,12 @@ paths:
247279
- tokenAuth: []
248280
responses:
249281
'200':
282+
headers:
283+
API-version:
284+
schema:
285+
type: string
286+
description: 'Geeft een specifieke API-versie aan in de context van
287+
een specifieke aanroep. Voorbeeld: 1.2.1.'
250288
content:
251289
application/json:
252290
schema:
@@ -290,6 +328,12 @@ paths:
290328
- tokenAuth: []
291329
responses:
292330
'200':
331+
headers:
332+
API-version:
333+
schema:
334+
type: string
335+
description: 'Geeft een specifieke API-versie aan in de context van
336+
een specifieke aanroep. Voorbeeld: 1.2.1.'
293337
content:
294338
application/json:
295339
schema:
@@ -320,6 +364,12 @@ paths:
320364
- tokenAuth: []
321365
responses:
322366
'204':
367+
headers:
368+
API-version:
369+
schema:
370+
type: string
371+
description: 'Geeft een specifieke API-versie aan in de context van
372+
een specifieke aanroep. Voorbeeld: 1.2.1.'
323373
description: No response body
324374
/objecttypes/{uuid}:
325375
get:
@@ -338,6 +388,12 @@ paths:
338388
- tokenAuth: []
339389
responses:
340390
'200':
391+
headers:
392+
API-version:
393+
schema:
394+
type: string
395+
description: 'Geeft een specifieke API-versie aan in de context van
396+
een specifieke aanroep. Voorbeeld: 1.2.1.'
341397
content:
342398
application/json:
343399
schema:
@@ -373,6 +429,12 @@ paths:
373429
- tokenAuth: []
374430
responses:
375431
'200':
432+
headers:
433+
API-version:
434+
schema:
435+
type: string
436+
description: 'Geeft een specifieke API-versie aan in de context van
437+
een specifieke aanroep. Voorbeeld: 1.2.1.'
376438
content:
377439
application/json:
378440
schema:
@@ -407,6 +469,12 @@ paths:
407469
- tokenAuth: []
408470
responses:
409471
'200':
472+
headers:
473+
API-version:
474+
schema:
475+
type: string
476+
description: 'Geeft een specifieke API-versie aan in de context van
477+
een specifieke aanroep. Voorbeeld: 1.2.1.'
410478
content:
411479
application/json:
412480
schema:
@@ -428,6 +496,12 @@ paths:
428496
- tokenAuth: []
429497
responses:
430498
'204':
499+
headers:
500+
API-version:
501+
schema:
502+
type: string
503+
description: 'Geeft een specifieke API-versie aan in de context van
504+
een specifieke aanroep. Voorbeeld: 1.2.1.'
431505
description: No response body
432506
components:
433507
schemas:

src/objecttypes/api/v2/urls.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from django.urls import include, path
22

3-
from drf_spectacular.views import (
3+
from drf_spectacular.views import SpectacularRedocView
4+
from vng_api_common import routers
5+
6+
from objecttypes.utils.views import (
7+
DeprecationRedirectView,
48
SpectacularJSONAPIView,
5-
SpectacularRedocView,
69
SpectacularYAMLAPIView,
710
)
8-
from vng_api_common import routers
911

1012
from .views import ObjectTypeViewSet, ObjectVersionViewSet
1113

@@ -20,17 +22,25 @@
2022
app_name = "v2"
2123

2224
urlpatterns = [
23-
path("", SpectacularJSONAPIView.as_view(), name="schema-json"),
2425
path(
2526
"/",
2627
include(
2728
[
2829
# schema
2930
path(
3031
"schema/openapi.yaml",
32+
DeprecationRedirectView.as_view(pattern_name="v2:schema"),
33+
),
34+
path(
35+
"openapi.yaml",
3136
SpectacularYAMLAPIView.as_view(),
3237
name="schema",
3338
),
39+
path(
40+
"openapi.json",
41+
SpectacularJSONAPIView.as_view(),
42+
name="schema-json",
43+
),
3444
path(
3545
"schema/",
3646
SpectacularRedocView.as_view(url_name="schema"),

src/objecttypes/conf/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
"SERVE_INCLUDE_SCHEMA": False,
6565
"CONTACT": {
6666
"url": "https://github.com/maykinmedia/objecttypes-api",
67+
"name": "Maykin Media",
68+
"email": "support@maykinmedia.nl",
6769
},
6870
"LICENSE": {"name": "EUPL-1.2"},
6971
"EXTERNAL_DOCS": {

src/objecttypes/conf/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"objecttypes.utils",
2828
]
2929

30+
MIDDLEWARE += ["vng_api_common.middleware.APIVersionHeaderMiddleware"]
3031

3132
# Internationalization
3233
# https://docs.djangoproject.com/en/3.0/topics/i18n/

src/objecttypes/utils/autoschema.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from drf_spectacular.utils import OpenApiParameter
77
from rest_framework.test import APIRequestFactory
88
from rest_framework_nested.viewsets import NestedViewSetMixin
9+
from vng_api_common.constants import VERSION_HEADER
910
from vng_api_common.schema import HTTP_STATUS_CODE_TITLES
1011

1112

@@ -19,10 +20,19 @@ def get_operation_id(self):
1920
return f"{model_name}_{self.view.action}"
2021
return super().get_operation_id()
2122

23+
def get_response_serializers(
24+
self,
25+
):
26+
if self.method == "DELETE":
27+
return {204: None}
28+
29+
return super().get_response_serializers()
30+
2231
def get_override_parameters(self):
2332
content_type_headers = self.get_content_type_headers()
2433
parent_path_headers = self.get_parent_path_headers()
25-
return content_type_headers + parent_path_headers
34+
version_headers = self.get_version_headers()
35+
return content_type_headers + parent_path_headers + version_headers
2636

2737
def _get_response_for_code(
2838
self, serializer, status_code, media_types=None, direction="response"
@@ -51,6 +61,20 @@ def get_content_type_headers(self) -> list:
5161
)
5262
]
5363

64+
def get_version_headers(self) -> list[OpenApiParameter]:
65+
return [
66+
OpenApiParameter(
67+
name=VERSION_HEADER,
68+
type=str,
69+
location=OpenApiParameter.HEADER,
70+
description=_(
71+
"Geeft een specifieke API-versie aan in de context van "
72+
"een specifieke aanroep. Voorbeeld: 1.2.1."
73+
),
74+
response=True,
75+
)
76+
]
77+
5478
def get_parent_path_headers(self) -> list:
5579
"""for nested viewsets"""
5680
if not isinstance(self.view, NestedViewSetMixin):

src/objecttypes/utils/views.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from django.utils.translation import gettext_lazy as _
2+
from django.views.generic import RedirectView
23

34
import structlog
5+
from drf_spectacular.views import (
6+
SpectacularJSONAPIView as _SpectacularJSONAPIView,
7+
SpectacularYAMLAPIView as _SpectacularYAMLAPIView,
8+
)
49
from open_api_framework.conf.utils import config
510
from rest_framework import status
611
from rest_framework.response import Response
@@ -45,3 +50,27 @@ def exception_handler(exc, context):
4550
)
4651

4752
return response
53+
54+
55+
class AllowAllOriginsMixin:
56+
def dispatch(self, request, *args, **kwargs):
57+
response = super().dispatch(request, *args, **kwargs)
58+
response["Access-Control-Allow-Origin"] = "*"
59+
return response
60+
61+
62+
class SpectacularYAMLAPIView(AllowAllOriginsMixin, _SpectacularYAMLAPIView):
63+
"""Spectacular YAML API view with Access-Control-Allow-Origin set to allow all"""
64+
65+
66+
class SpectacularJSONAPIView(AllowAllOriginsMixin, _SpectacularJSONAPIView):
67+
"""Spectacular JSON API view with Access-Control-Allow-Origin set to allow all"""
68+
69+
70+
class DeprecationRedirectView(RedirectView):
71+
def get(self, request, *args, **kwargs):
72+
logger.warning(
73+
"deprecated_endpoint_called",
74+
endpoint=request.path,
75+
)
76+
return super().get(request, *args, **kwargs)

0 commit comments

Comments
 (0)