Skip to content

Commit

Permalink
API: removal of drf_yasg (OpenAPI 2.0 Swagger) (#9108)
Browse files Browse the repository at this point in the history
* Removal of drf_yasg

* Clean filterwarnings
  • Loading branch information
kiblik authored Feb 15, 2024
1 parent 77f0cf1 commit 648554b
Show file tree
Hide file tree
Showing 17 changed files with 70 additions and 1,748 deletions.
43 changes: 0 additions & 43 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -3910,49 +3910,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


drf-yasg
1.20.0
BSD License
.. |br| raw:: html

<br />

#######
License
#######

********************
BSD 3-Clause License
********************

Copyright (c) 2017 - 2019, Cristian V. <[email protected]> |br|\ All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


ecdsa
0.17.0
MIT
Expand Down
9 changes: 8 additions & 1 deletion docs/content/en/getting_started/upgrading/2.32.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
title: 'Upgrading to DefectDojo Version 2.32.x'
toc_hide: true
weight: -20240205
description: No special instructions.
description: Breaking change: Removal of OpenAPI 2.0 Swagger
---
There are no special instructions for upgrading to 2.32.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.32.0) for the contents of the release.

**Removal**

The OpenAPI 2.0 Swagger API documentation was removed in favor of the existing
OpenAPI 3.0 API documentation page.

*Note*: The API has not changed in any way and behaves the same between OAPI2 and OAPI3
7 changes: 2 additions & 5 deletions docs/content/en/integrations/api-v2-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ Docs link on the user drop down menu in the header.

![image](../../images/api_v2_1.png)

The documentation is generated using [Django Rest Framework
Yet Another Swagger Generator](https://github.com/axnsan12/drf-yasg/), and is
interactive. On the top of API v2 docs is a link that generates an OpenAPI v2 spec.

As a preparation to move to OpenAPIv3, we have added an compatible spec and documentation at [`/api/v2/oa3/swagger-ui/`](https://demo.defectdojo.org/api/v2/oa3/swagger-ui/)
The documentation is generated using [drf-spectacular](https://drf-spectacular.readthedocs.io/) at [`/api/v2/oa3/swagger-ui/`](https://demo.defectdojo.org/api/v2/oa3/swagger-ui/), and is
interactive. On the top of API v2 docs is a link that generates an OpenAPI v3 spec.

To interact with the documentation, a valid Authorization header value
is needed. Visit the `/api/key-v2` view to generate your
Expand Down
5 changes: 0 additions & 5 deletions dojo/api_v2/mixins.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from django.db import DEFAULT_DB_ALIAS
from django.contrib.admin.utils import NestedObjects
from drf_spectacular.utils import extend_schema
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework import status
from rest_framework.authtoken.models import Token
Expand All @@ -17,10 +16,6 @@ class DeletePreviewModelMixin:
status.HTTP_200_OK: serializers.DeletePreviewSerializer(many=True)
},
)
@swagger_auto_schema(
method="get",
responses={"default": serializers.DeletePreviewSerializer(many=True)},
)
@action(detail=True, methods=["get"], filter_backends=[], suffix="List")
def delete_preview(self, request, pk=None):
object = self.get_object()
Expand Down
3 changes: 1 addition & 2 deletions dojo/api_v2/prefetch/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from .mixins import PrefetchListMixin, PrefetchRetrieveMixin
from .schema import get_prefetch_schema

__all__ = ["PrefetchListMixin", "PrefetchRetrieveMixin", "get_prefetch_schema"]
__all__ = ["PrefetchListMixin", "PrefetchRetrieveMixin"]
168 changes: 45 additions & 123 deletions dojo/api_v2/prefetch/schema.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,5 @@
from drf_yasg import openapi, utils
from .prefetcher import _Prefetcher
from .utils import _get_prefetchable_fields
from ..schema import extra_schema
from ..schema.utils import LazySchemaRef


def get_prefetch_schema(methods, serializer):
"""Swagger / OpenAPI v2 (drf-yasg) Return a composable swagger schema that contains in the query the fields that can be prefetch from the model
supported by the serializer and in the reponse the structure of these fields in a new top-level attribute
named prefetch.
Returns:
ComposableSchema: A swagger schema
"""
prefetcher = _Prefetcher()
fields = _get_prefetchable_fields(serializer())

field_to_serializer = dict(
[
(name, prefetcher._find_serializer(field_type))
for name, field_type in fields
if prefetcher._find_serializer(field_type)
]
)
fields_to_refname = dict(
[
(name, utils.get_serializer_ref_name(serializer()))
for name, serializer in field_to_serializer.items()
]
)
fields_name = [
name
for name, field_type in fields
if prefetcher._find_serializer(field_type)
]

# New openapi parameter corresponding to the prefetchable fields
prefetch_params = [
openapi.Parameter(
"prefetch",
in_=openapi.IN_QUERY,
required=False,
type=openapi.TYPE_ARRAY,
items=openapi.Items(type=openapi.TYPE_STRING, enum=fields_name),
)
]

additional_props = dict(
[
(
name,
openapi.Schema(
type=openapi.TYPE_OBJECT,
read_only=True,
additional_properties=LazySchemaRef(
fields_to_refname[name], True
),
),
)
for name in fields_name
]
)
prefetch_response = {
"200": {
"prefetch": openapi.Schema(
type=openapi.TYPE_OBJECT, properties=additional_props
)
}
}

schema = extra_schema.IdentitySchema()
for method in methods:
schema = schema.composeWith(
extra_schema.ExtraParameters(method, prefetch_params)
)
schema = schema.composeWith(
extra_schema.ExtraResponseField(method, prefetch_response)
)

return schema


def _get_path_to_GET_serializer_map(generator):
Expand All @@ -97,6 +18,25 @@ def _get_path_to_GET_serializer_map(generator):
return path_to_GET_serializer


def get_serializer_ref_name(serializer):
"""Get serializer's ref_name
inspired by https://github.com/axnsan12/drf-yasg/blob/78031f0c189585c30fccb5005a6899f2d34289a9/src/drf_yasg/utils.py#L416
:param serializer: Serializer instance
:return: Serializer's ``ref_name`` or ``None`` for inline serializer
:rtype: str or None
"""
serializer_meta = getattr(serializer, 'Meta', None)
serializer_name = type(serializer).__name__
if hasattr(serializer_meta, 'ref_name'):
ref_name = serializer_meta.ref_name
else:
ref_name = serializer_name
if ref_name.endswith('Serializer'):
ref_name = ref_name[:-len('Serializer')]
return ref_name


def prefetch_postprocessing_hook(result, generator, request, public):
"""OpenAPI v3 (drf-spectacular) Some endpoints are using the PrefetchListMixin and PrefetchRetrieveMixin.
These have nothing to do with Django prefetch_related.
Expand Down Expand Up @@ -131,55 +71,37 @@ def prefetch_postprocessing_hook(result, generator, request, public):
"enum": field_names,
}

field_to_serializer = dict(
[
(name, prefetcher._find_serializer(field_type))
for name, field_type in fields
if prefetcher._find_serializer(field_type)
]
)
fields_to_refname = dict(
[
(name, utils.get_serializer_ref_name(serializer()))
for name, serializer in field_to_serializer.items()
]
)
properties = dict(
[
(
name,
dict(
[
("type", "object"),
("readOnly", True),
(
"additionalProperties",
dict(
[
(
"$ref",
"#/components/schemas/"
+ fields_to_refname[
name
],
)
]
),
),
]
),
)
for name in field_names
]
)
field_to_serializer = {
name: prefetcher._find_serializer(field_type)
for name, field_type in fields
if prefetcher._find_serializer(field_type)
}

fields_to_refname = {
name: get_serializer_ref_name(serializer())
for name, serializer in field_to_serializer.items()
}

properties = {
name: {
"type": "object",
"readOnly": True,
"additionalProperties": {
"$ref": f"#/components/schemas/{fields_to_refname[name]}"
}
}
for name in field_names
}

ref = paths[path]["get"]["responses"]["200"]["content"][
"application/json"
]["schema"]["$ref"]
component_name = ref.split("/")[-1]
result["components"]["schemas"][component_name][
"properties"
]["prefetch"] = dict(
[("type", "object"), ("properties", properties)]
)
]["prefetch"] = {
"type": "object",
"properties": properties,
}

return result
17 changes: 0 additions & 17 deletions dojo/api_v2/schema/__init__.py

This file was deleted.

Loading

0 comments on commit 648554b

Please sign in to comment.