Skip to content

Commit

Permalink
improve handling of discouraged SECURITY setting (fixes #48 fixes #136)
Browse files Browse the repository at this point in the history
  • Loading branch information
tfranzel committed Oct 13, 2020
1 parent 6f2c447 commit ab979c1
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
8 changes: 4 additions & 4 deletions docs/blueprints.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ djangorestframework-api-key
---------------------------

Since `djangorestframework-api-key <https://github.com/florimondmanca/djangorestframework-api-key>`_ has
not entry in ``authentication_classes``, `drf-spectacular` does not pick up this library. To alleviate
no entry in ``authentication_classes``, `drf-spectacular` cannot pick up this library. To alleviate
this shortcoming, you can manually add the appropriate security scheme.

.. note:: The usage of ``APPEND_COMPONENTS`` and ``SECURITY`` is discouraged, unless there are special
circumstances like here for example. They apply globally and additional local ``security`` sections
silently override the global ``security`` section.
.. note:: Usage of the ``SECURITY`` setting is discouraged, unless there are special circumstances
like here for example. For almost all cases ``OpenApiAuthenticationExtension`` is strongly preferred,
because ``SECURITY`` will get appended to every endpoint in the schema regardless of effectiveness.

.. code:: python
Expand Down
3 changes: 3 additions & 0 deletions drf_spectacular/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ def get_auth(self):
)
self.registry.register_on_missing(component)

if spectacular_settings.SECURITY:
auths.extend(spectacular_settings.SECURITY)

perms = [p.__class__ for p in self.view.get_permissions()]
if permissions.AllowAny in perms:
auths.append({})
Expand Down
2 changes: 0 additions & 2 deletions drf_spectacular/plumbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,6 @@ def build_root_object(paths, components):
root['info']['license'] = settings.LICENSE
if settings.SERVERS:
root['servers'] = settings.SERVERS
if settings.SECURITY:
root['security'] = settings.SECURITY
if settings.TAGS:
root['tags'] = settings.TAGS
if settings.EXTERNAL_DOCS:
Expand Down
7 changes: 4 additions & 3 deletions drf_spectacular/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@

# Append OpenAPI objects to path and components in addition to the generated objects
'APPEND_PATHS': {},
'APPEND_COMPONENTS': {},

# DEPRECATED - please don't use this anymore as it has tricky implications that
# DISCOURAGED - please don't use this anymore as it has tricky implications that
# are hard to get right. For authentication, OpenApiAuthenticationExtension are
# strongly preferred because they are more robust and easy to write.
'APPEND_COMPONENTS': {},
'SECURITY': None,
# However if used, the list of methods is appended to every endpoint in the schema!
'SECURITY': [],

# Postprocessing functions that run at the end of schema generation.
# must satisfy interface result = hook(generator, request, public, result)
Expand Down
21 changes: 21 additions & 0 deletions tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1007,3 +1007,24 @@ class XViewset(viewsets.ReadOnlyModelViewSet):
substitution = schema['components']['schemas']['PaginatedXList']
assert substitution['type'] == 'object'
assert substitution['properties']['results']['items']['$ref'] == '#/components/schemas/X'


@mock.patch(
'drf_spectacular.settings.spectacular_settings.SECURITY',
[{'apiKeyAuth': []}]
)
@mock.patch(
'drf_spectacular.settings.spectacular_settings.APPEND_COMPONENTS',
{"securitySchemes": {"apiKeyAuth": {"type": "apiKey", "in": "header", "name": "Authorization"}}}
)
def test_manual_security_method_addition(no_warnings):
@extend_schema(responses=OpenApiTypes.FLOAT)
@api_view(['GET'])
def view_func(request, format=None):
pass # pragma: no cover

schema = generate_schema('/x/', view_function=view_func)
operation_security = schema['paths']['/x/']['get']['security']
schema_security = schema['components']['securitySchemes']
assert len(operation_security) == 4 and any(['apiKeyAuth' in os for os in operation_security])
assert len(schema_security) == 3 and 'apiKeyAuth' in schema_security

0 comments on commit ab979c1

Please sign in to comment.