commonground-api-common 2.2.0__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- commonground_api_common-2.2.0.data/scripts/patch_content_types → commonground_api_common-2.3.0.data/scripts/generate_schema +2 -4
- {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/METADATA +10 -3
- {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/RECORD +25 -38
- {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/WHEEL +1 -1
- vng_api_common/__init__.py +1 -1
- vng_api_common/api/views.py +1 -0
- vng_api_common/apps.py +43 -26
- vng_api_common/audittrails/utils.py +44 -0
- vng_api_common/conf/api.py +33 -45
- vng_api_common/contrib/setup_configuration/models.py +14 -0
- vng_api_common/contrib/setup_configuration/steps.py +24 -1
- vng_api_common/extensions/file.py +26 -0
- vng_api_common/extensions/gegevensgroep.py +16 -0
- vng_api_common/extensions/geojson.py +270 -0
- vng_api_common/extensions/hyperlink.py +37 -0
- vng_api_common/extensions/polymorphic.py +68 -0
- vng_api_common/extensions/query.py +20 -0
- vng_api_common/filters.py +0 -1
- vng_api_common/generators.py +12 -113
- vng_api_common/notifications/api/views.py +3 -3
- vng_api_common/oas.py +6 -7
- vng_api_common/schema.py +414 -158
- vng_api_common/views.py +1 -1
- commonground_api_common-2.2.0.data/scripts/generate_schema +0 -39
- commonground_api_common-2.2.0.data/scripts/use_external_components +0 -16
- vng_api_common/inspectors/cache.py +0 -57
- vng_api_common/inspectors/fields.py +0 -126
- vng_api_common/inspectors/files.py +0 -121
- vng_api_common/inspectors/geojson.py +0 -360
- vng_api_common/inspectors/polymorphic.py +0 -72
- vng_api_common/inspectors/query.py +0 -91
- vng_api_common/inspectors/utils.py +0 -40
- vng_api_common/inspectors/view.py +0 -547
- vng_api_common/management/__init__.py +0 -0
- vng_api_common/management/commands/__init__.py +0 -0
- vng_api_common/management/commands/generate_autorisaties.py +0 -43
- vng_api_common/management/commands/generate_notificaties.py +0 -40
- vng_api_common/management/commands/generate_swagger.py +0 -197
- vng_api_common/management/commands/patch_error_contenttypes.py +0 -61
- vng_api_common/management/commands/use_external_components.py +0 -94
- vng_api_common/templates/vng_api_common/api_schema_to_markdown_table.md +0 -16
- vng_api_common/templates/vng_api_common/autorisaties.md +0 -15
- vng_api_common/templates/vng_api_common/notificaties.md +0 -24
- {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/top_level.txt +0 -0
- /vng_api_common/{inspectors → extensions}/__init__.py +0 -0
@@ -1,197 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import os
|
3
|
-
|
4
|
-
from django.apps import apps
|
5
|
-
from django.conf import settings
|
6
|
-
from django.contrib.auth import get_user_model
|
7
|
-
from django.core.exceptions import ImproperlyConfigured
|
8
|
-
from django.template.loader import render_to_string
|
9
|
-
from django.urls import NoReverseMatch, reverse
|
10
|
-
from django.utils.module_loading import import_string
|
11
|
-
|
12
|
-
from drf_yasg import openapi
|
13
|
-
from drf_yasg.app_settings import swagger_settings
|
14
|
-
from drf_yasg.management.commands import generate_swagger
|
15
|
-
from rest_framework.settings import api_settings
|
16
|
-
|
17
|
-
from ...version import get_major_version
|
18
|
-
|
19
|
-
|
20
|
-
class Table:
|
21
|
-
def __init__(self, resource: str):
|
22
|
-
self.resource = resource
|
23
|
-
self.rows = []
|
24
|
-
|
25
|
-
|
26
|
-
class Row:
|
27
|
-
def __init__(
|
28
|
-
self,
|
29
|
-
label: str,
|
30
|
-
description: str,
|
31
|
-
type: str,
|
32
|
-
required: bool,
|
33
|
-
create: bool,
|
34
|
-
read: bool,
|
35
|
-
update: bool,
|
36
|
-
delete: bool,
|
37
|
-
):
|
38
|
-
self.label = label
|
39
|
-
self.description = description
|
40
|
-
self.type = type
|
41
|
-
self.required = required
|
42
|
-
self.create = create
|
43
|
-
self.read = read
|
44
|
-
self.update = update
|
45
|
-
self.delete = delete
|
46
|
-
|
47
|
-
|
48
|
-
class Command(generate_swagger.Command):
|
49
|
-
"""
|
50
|
-
Patches to the provided command to modify the schema.
|
51
|
-
"""
|
52
|
-
|
53
|
-
leave_locale_alone = True
|
54
|
-
|
55
|
-
def add_arguments(self, parser):
|
56
|
-
super().add_arguments(parser)
|
57
|
-
parser.add_argument("--to-markdown-table", action="store_true")
|
58
|
-
|
59
|
-
parser.add_argument(
|
60
|
-
"--info", dest="info", default=None, help="Path to schema info object"
|
61
|
-
)
|
62
|
-
|
63
|
-
parser.add_argument(
|
64
|
-
"--urlconf",
|
65
|
-
dest="urlconf",
|
66
|
-
default=None,
|
67
|
-
help="Urlconf for schema generator",
|
68
|
-
)
|
69
|
-
|
70
|
-
def get_mock_request(self, *args, **kwargs):
|
71
|
-
request = super().get_mock_request(*args, **kwargs)
|
72
|
-
request.version = api_settings.DEFAULT_VERSION
|
73
|
-
return request
|
74
|
-
|
75
|
-
def write_schema(self, schema, stream, format):
|
76
|
-
del schema.host
|
77
|
-
del schema.schemes
|
78
|
-
super().write_schema(schema, stream, format)
|
79
|
-
|
80
|
-
# need to overwrite the generator class...
|
81
|
-
def handle(
|
82
|
-
self,
|
83
|
-
output_file,
|
84
|
-
overwrite,
|
85
|
-
format,
|
86
|
-
api_url,
|
87
|
-
mock,
|
88
|
-
api_version,
|
89
|
-
user,
|
90
|
-
private,
|
91
|
-
generator_class_name,
|
92
|
-
info=None,
|
93
|
-
urlconf=None,
|
94
|
-
**options,
|
95
|
-
):
|
96
|
-
# disable logs of WARNING and below
|
97
|
-
logging.disable(logging.WARNING)
|
98
|
-
|
99
|
-
if info:
|
100
|
-
info = import_string(info)
|
101
|
-
else:
|
102
|
-
info = getattr(swagger_settings, "DEFAULT_INFO", None)
|
103
|
-
|
104
|
-
if not isinstance(info, openapi.Info):
|
105
|
-
raise ImproperlyConfigured(
|
106
|
-
'settings.SWAGGER_SETTINGS["DEFAULT_INFO"] should be an '
|
107
|
-
"import string pointing to an openapi.Info object"
|
108
|
-
)
|
109
|
-
|
110
|
-
if not format:
|
111
|
-
if os.path.splitext(output_file)[1] in (".yml", ".yaml"):
|
112
|
-
format = "yaml"
|
113
|
-
format = format or "json"
|
114
|
-
|
115
|
-
try:
|
116
|
-
api_root = reverse("api-root", kwargs={"version": get_major_version()})
|
117
|
-
except NoReverseMatch:
|
118
|
-
api_root = reverse("api-root")
|
119
|
-
|
120
|
-
api_url = (
|
121
|
-
api_url
|
122
|
-
or swagger_settings.DEFAULT_API_URL # noqa
|
123
|
-
or f"http://example.com{api_root}" # noqa
|
124
|
-
)
|
125
|
-
|
126
|
-
if user:
|
127
|
-
# Only call get_user_model if --user was passed in order to
|
128
|
-
# avoid crashing if auth is not configured in the project
|
129
|
-
user = get_user_model().objects.get(username=user)
|
130
|
-
|
131
|
-
mock = mock or private or (user is not None) or (api_version is not None)
|
132
|
-
if mock and not api_url:
|
133
|
-
raise ImproperlyConfigured(
|
134
|
-
"--mock-request requires an API url; either provide "
|
135
|
-
"the --url argument or set the DEFAULT_API_URL setting"
|
136
|
-
)
|
137
|
-
|
138
|
-
request = None
|
139
|
-
if mock:
|
140
|
-
request = self.get_mock_request(api_url, format, user)
|
141
|
-
|
142
|
-
api_version = api_version or api_settings.DEFAULT_VERSION
|
143
|
-
if request and api_version:
|
144
|
-
request.version = api_version
|
145
|
-
|
146
|
-
generator = self.get_schema_generator(
|
147
|
-
generator_class_name, info, settings.API_VERSION, api_url
|
148
|
-
)
|
149
|
-
schema = self.get_schema(generator, request, not private)
|
150
|
-
|
151
|
-
if output_file == "-":
|
152
|
-
self.write_schema(schema, self.stdout, format)
|
153
|
-
else:
|
154
|
-
with open(output_file, "w", encoding="utf8") as stream:
|
155
|
-
if options["to_markdown_table"]:
|
156
|
-
self.to_markdown_table(schema, stream)
|
157
|
-
else:
|
158
|
-
self.write_schema(schema, stream, format)
|
159
|
-
|
160
|
-
def to_markdown_table(self, schema, stream):
|
161
|
-
template = "vng_api_common/api_schema_to_markdown_table.md"
|
162
|
-
tables = []
|
163
|
-
|
164
|
-
whitelist = [model._meta.object_name for model in apps.get_models()]
|
165
|
-
|
166
|
-
for resource, definition in schema.definitions.items():
|
167
|
-
if resource not in whitelist:
|
168
|
-
continue
|
169
|
-
|
170
|
-
if not hasattr(definition, "properties"):
|
171
|
-
continue
|
172
|
-
|
173
|
-
table = Table(resource)
|
174
|
-
for field, _schema in definition.properties.items():
|
175
|
-
if isinstance(_schema, openapi.SchemaRef):
|
176
|
-
continue
|
177
|
-
required = (
|
178
|
-
hasattr(definition, "required") and field in definition.required
|
179
|
-
)
|
180
|
-
|
181
|
-
readonly = getattr(_schema, "readOnly", False)
|
182
|
-
table.rows.append(
|
183
|
-
Row(
|
184
|
-
label=field,
|
185
|
-
description=getattr(_schema, "description", ""),
|
186
|
-
type=_schema.type,
|
187
|
-
required=required,
|
188
|
-
create=not readonly,
|
189
|
-
read=True,
|
190
|
-
update=not readonly,
|
191
|
-
delete=not readonly,
|
192
|
-
)
|
193
|
-
)
|
194
|
-
tables.append(table)
|
195
|
-
|
196
|
-
markdown = render_to_string(template, context={"tables": tables})
|
197
|
-
stream.write(markdown)
|
@@ -1,61 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Patch the content-type of error responses.
|
3
|
-
|
4
|
-
Due to the changes between Swagger 2.0 and OpenAPI 3.0, we cannot handle
|
5
|
-
this at the Python level.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from django.core.management import BaseCommand
|
9
|
-
|
10
|
-
import oyaml as yaml
|
11
|
-
|
12
|
-
from ...views import ERROR_CONTENT_TYPE
|
13
|
-
|
14
|
-
|
15
|
-
class Command(BaseCommand):
|
16
|
-
help = "Patch the error-response content types in the OAS 3 spec"
|
17
|
-
|
18
|
-
def add_arguments(self, parser):
|
19
|
-
parser.add_argument(
|
20
|
-
"api-spec", help="Path to the openapi spec. Will be overwritten!"
|
21
|
-
)
|
22
|
-
|
23
|
-
def patch_response(self, response):
|
24
|
-
content = {}
|
25
|
-
|
26
|
-
for contenttype, _response in response["content"].items():
|
27
|
-
contenttype = ERROR_CONTENT_TYPE
|
28
|
-
content[contenttype] = _response
|
29
|
-
|
30
|
-
response["content"] = content
|
31
|
-
|
32
|
-
def handle(self, **options):
|
33
|
-
source = options["api-spec"]
|
34
|
-
|
35
|
-
# Enforce the file to be read as UTF-8 to prevent any platform
|
36
|
-
# dependent encoding.
|
37
|
-
with open(source, "r", encoding="utf8") as infile:
|
38
|
-
spec = yaml.safe_load(infile)
|
39
|
-
|
40
|
-
for endpoint in spec["paths"].values():
|
41
|
-
for data in endpoint.values():
|
42
|
-
# filter the available request methods
|
43
|
-
if not "responses" in data:
|
44
|
-
continue
|
45
|
-
|
46
|
-
for status, response in data["responses"].items():
|
47
|
-
# Only edit the error responses which are defined directly
|
48
|
-
# and not referencing existing error responses
|
49
|
-
if not (400 <= int(status) < 600) or not "content" in response:
|
50
|
-
continue
|
51
|
-
|
52
|
-
self.patch_response(response)
|
53
|
-
|
54
|
-
for status, response in spec["components"]["responses"].items():
|
55
|
-
if not (400 <= int(status) < 600):
|
56
|
-
continue
|
57
|
-
|
58
|
-
self.patch_response(response)
|
59
|
-
|
60
|
-
with open(source, "w", encoding="utf8") as outfile:
|
61
|
-
yaml.dump(spec, outfile, default_flow_style=False)
|
@@ -1,94 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Replace internal references to external for reusable components
|
3
|
-
|
4
|
-
Due to the limitations of drf_yasg we cannot handle this at the Python level
|
5
|
-
"""
|
6
|
-
|
7
|
-
import os.path
|
8
|
-
|
9
|
-
from django.conf import settings
|
10
|
-
from django.core.management import BaseCommand
|
11
|
-
|
12
|
-
import oyaml as yaml
|
13
|
-
import requests
|
14
|
-
|
15
|
-
|
16
|
-
class QuotedString(str):
|
17
|
-
pass
|
18
|
-
|
19
|
-
|
20
|
-
def quoted_scalar(dumper, data):
|
21
|
-
# a representer to force quotations on scalars
|
22
|
-
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="'")
|
23
|
-
|
24
|
-
|
25
|
-
def replace_refs(source: dict, replace_dict: dict) -> None:
|
26
|
-
for k, v in source.items():
|
27
|
-
if isinstance(v, dict):
|
28
|
-
replace_refs(v, replace_dict)
|
29
|
-
|
30
|
-
if k != "$ref":
|
31
|
-
continue
|
32
|
-
|
33
|
-
if v in replace_dict:
|
34
|
-
source[k] = QuotedString(replace_dict[v])
|
35
|
-
|
36
|
-
|
37
|
-
class Command(BaseCommand):
|
38
|
-
help = "Replace internal references to external for reusable components"
|
39
|
-
|
40
|
-
def add_arguments(self, parser):
|
41
|
-
parser.add_argument(
|
42
|
-
"api-spec", help="Path to the openapi spec. Will be overwritten!"
|
43
|
-
)
|
44
|
-
parser.add_argument(
|
45
|
-
"output", help="Path to the yaml file with external components"
|
46
|
-
)
|
47
|
-
|
48
|
-
def handle(self, **options):
|
49
|
-
source = options["api-spec"]
|
50
|
-
output = options["output"]
|
51
|
-
common_url = settings.COMMON_SPEC
|
52
|
-
try:
|
53
|
-
response = requests.get(common_url)
|
54
|
-
response.raise_for_status()
|
55
|
-
common_yaml = response.text
|
56
|
-
except requests.exceptions.RequestException:
|
57
|
-
return
|
58
|
-
|
59
|
-
common_spec = yaml.safe_load(common_yaml)
|
60
|
-
common_components = common_spec["components"]
|
61
|
-
|
62
|
-
with open(source, "r", encoding="utf8") as infile:
|
63
|
-
spec = yaml.safe_load(infile)
|
64
|
-
components = spec["components"]
|
65
|
-
refs = {}
|
66
|
-
|
67
|
-
for scope, scope_items in components.items():
|
68
|
-
if scope not in common_components:
|
69
|
-
continue
|
70
|
-
|
71
|
-
for item, item_spec in scope_items.copy().items():
|
72
|
-
if item not in common_components[scope]:
|
73
|
-
continue
|
74
|
-
|
75
|
-
common_item_spec = common_components[scope][item]
|
76
|
-
if item_spec == common_item_spec:
|
77
|
-
# add ref to replace
|
78
|
-
ref = f"#/components/{scope}/{item}"
|
79
|
-
refs[ref] = f"{common_url}{ref}"
|
80
|
-
|
81
|
-
# remove item from internal components
|
82
|
-
del components[scope][item]
|
83
|
-
|
84
|
-
# remove empty components
|
85
|
-
for scope, scope_items in components.copy().items():
|
86
|
-
if not scope_items:
|
87
|
-
del components[scope]
|
88
|
-
|
89
|
-
# replace all refs
|
90
|
-
replace_refs(spec, refs)
|
91
|
-
|
92
|
-
with open(output, "w", encoding="utf8") as outfile:
|
93
|
-
yaml.add_representer(QuotedString, quoted_scalar)
|
94
|
-
yaml.dump(spec, outfile, default_flow_style=False)
|
@@ -1,16 +0,0 @@
|
|
1
|
-
{% load vng_api_common %}# Resources
|
2
|
-
|
3
|
-
Dit document beschrijft de (RGBZ-)objecttypen die als resources ontsloten
|
4
|
-
worden met de beschikbare attributen.
|
5
|
-
|
6
|
-
{% for table in tables %}
|
7
|
-
## {{ table.resource }}
|
8
|
-
|
9
|
-
Objecttype op [GEMMA Online]({{ table.resource|gemmaonline_url }})
|
10
|
-
|
11
|
-
| Attribuut | Omschrijving | Type | Verplicht | CRUD* |
|
12
|
-
| --- | --- | --- | --- | --- |{% for row in table.rows %}
|
13
|
-
| {{ row.label|md_table_cell }} | {{ row.description|md_table_cell }} | {{ row.type|md_table_cell }} | {{ row.required|yesno:"ja,nee" }} | {{ row|crud }} |{% endfor %}
|
14
|
-
{% endfor %}
|
15
|
-
|
16
|
-
* Create, Read, Update, Delete
|
@@ -1,15 +0,0 @@
|
|
1
|
-
{% load vng_api_common markup_tags %}
|
2
|
-
# Autorisaties
|
3
|
-
## Scopes voor {{ project_name }} API
|
4
|
-
|
5
|
-
Scopes worden typisch per component gedefinieerd en geven aan welke rechten er zijn.
|
6
|
-
Zie de repository van de [Autorisaties API](https://github.com/VNG-Realisatie/autorisaties-api)
|
7
|
-
|
8
|
-
{% for scope in scopes %}
|
9
|
-
### {{ scope.label }}
|
10
|
-
|
11
|
-
**Scope**
|
12
|
-
`{{ scope.label }}`
|
13
|
-
|
14
|
-
{{ scope.description|default:"" }}
|
15
|
-
{% endfor %}
|
@@ -1,24 +0,0 @@
|
|
1
|
-
## Notificaties
|
2
|
-
## Berichtkenmerken voor {{ project_name }} API
|
3
|
-
|
4
|
-
Kanalen worden typisch per component gedefinieerd. Producers versturen berichten op bepaalde kanalen,
|
5
|
-
consumers ontvangen deze. Consumers abonneren zich via een notificatiecomponent (zoals {{ 'https://notificaties-api.vng.cloud/api/v1/schema/'|urlize }}) op berichten.
|
6
|
-
|
7
|
-
Hieronder staan de kanalen beschreven die door deze component gebruikt worden, met de kenmerken bij elk bericht.
|
8
|
-
|
9
|
-
De architectuur van de notificaties staat beschreven op {{ 'https://github.com/VNG-Realisatie/notificaties-api'|urlize }}.
|
10
|
-
|
11
|
-
{% for kanaal in kanalen %}
|
12
|
-
### {{ kanaal.label }}
|
13
|
-
|
14
|
-
**Kanaal**
|
15
|
-
`{{ kanaal.label }}`
|
16
|
-
|
17
|
-
{{ kanaal.description|default:""|urlize }}
|
18
|
-
|
19
|
-
**Resources en acties**
|
20
|
-
|
21
|
-
{% for resource, actions in kanaal.get_usage %}
|
22
|
-
* <code>{{ resource }}</code>: {{ actions|join:", " }}
|
23
|
-
{% endfor %}
|
24
|
-
{% endfor %}
|
{commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/top_level.txt
RENAMED
File without changes
|
File without changes
|