From b27c042b313e0b90b8332cc98d59a842d1c54ccc Mon Sep 17 00:00:00 2001 From: Pedro Brochado Date: Mon, 1 Jul 2024 15:15:22 -0300 Subject: [PATCH] Fixed drf JSONField being interpreted as Any Drf JSONField is actually 'any' because it can be of any type (list, obj int, bool, etc). Nevertheless, we (and drf-spectacular) always interpret it as being of type 'object'. In v0.27.0, drf-spectacular fixed that on their side, which broke us. Although it is not correct to keep using JSONFields strictly as a object, this commit adds a drf-spectacular extension that enforces that it should always be trated as an 'object' on openapi schema generation. The reason is to provide a safe fix for our users, who need their bindings working the same way as they always did. Closes: #3639 --- CHANGES/3639.bugfix | 1 + pulp_rpm/app/__init__.py | 6 ++++++ pulp_rpm/app/schema/extensions.py | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 CHANGES/3639.bugfix create mode 100644 pulp_rpm/app/schema/extensions.py diff --git a/CHANGES/3639.bugfix b/CHANGES/3639.bugfix new file mode 100644 index 000000000..8ca6e6431 --- /dev/null +++ b/CHANGES/3639.bugfix @@ -0,0 +1 @@ +Fixed openapi schema generation by monkeypatching that drf JSONField is always an OA 'object'. diff --git a/pulp_rpm/app/__init__.py b/pulp_rpm/app/__init__.py index 3324c37e3..e035a6f66 100644 --- a/pulp_rpm/app/__init__.py +++ b/pulp_rpm/app/__init__.py @@ -11,3 +11,9 @@ class PulpRpmPluginAppConfig(PulpPluginAppConfig): version = "3.28.0.dev" python_package_name = "pulp-rpm" domain_compatible = True + + def ready(self): + # include drf-spectacular Extension module + import pulp_rpm.app.schema.extensions # noqa: E402, F401 + + super().ready() diff --git a/pulp_rpm/app/schema/extensions.py b/pulp_rpm/app/schema/extensions.py new file mode 100644 index 000000000..4c7634133 --- /dev/null +++ b/pulp_rpm/app/schema/extensions.py @@ -0,0 +1,23 @@ +"""drf-spectacular Extensions. + +See: +https://drf-spectacular.readthedocs.io/en/latest/customization.html#step-5-extensions +""" +from drf_spectacular.extensions import OpenApiSerializerFieldExtension +from drf_spectacular.plumbing import build_basic_type +from drf_spectacular.types import OpenApiTypes + + +class RestrictedJsonFieldExtension(OpenApiSerializerFieldExtension): + """ + Workaround to makes drf JSONField to produce only Object Type. + + See: + https://github.com/tfranzel/drf-spectacular/issues/1242 + """ + + target_class = "rest_framework.fields.JSONField" + # match_subclasses = True # not needed here but good to know. + + def map_serializer_field(self, auto_schema, direction): + return build_basic_type(OpenApiTypes.OBJECT)