Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Components.security_scheme #375

Merged
merged 2 commits into from
Feb 3, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion apispec/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,20 @@ def __init__(self, plugins, openapi_version):
self._schemas = {}
self._parameters = {}
self._responses = {}
self._security_schemes = {}

def to_dict(self):
schemas_key = 'definitions' if self.openapi_version.major < 3 else 'schemas'
if self.openapi_version.major < 3:
schemas_key = 'definitions'
security_key = 'securityDefinitions'
else:
schemas_key = 'schemas'
security_key = 'securitySchemes'
return {
'parameters': self._parameters,
'responses': self._responses,
schemas_key: self._schemas,
security_key: self._security_schemes,
}

def schema(
Expand Down Expand Up @@ -187,6 +194,19 @@ def response(self, ref_id, **kwargs):
self._responses[ref_id] = ret
return self

def security_scheme(self, sec_id, **kwargs):
"""Add a security scheme which can be referenced.

:param str sec_id: sec_id to use as reference
:param dict kwargs: security scheme fields
"""
if sec_id in self._security_schemes:
raise DuplicateComponentNameError(
'Another security scheme with name "{}" is already registered.'.format(sec_id),
)
self._security_schemes[sec_id] = kwargs
return self


class APISpec(object):
"""Stores metadata that describes a RESTful API using the OpenAPI specification.
Expand Down
23 changes: 22 additions & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from apispec import APISpec, BasePlugin
from apispec.exceptions import APISpecError, DuplicateComponentNameError

from .utils import get_definitions, get_paths, get_parameters, get_responses
from .utils import get_definitions, get_paths, get_parameters, get_responses, get_security_schemes


description = 'This is a sample Petstore server. You can find out more '
Expand Down Expand Up @@ -397,6 +397,27 @@ def test_response_duplicate_name(self, spec):
):
spec.components.response('test_response', **route_spec['responses']['200'])

def test_security_scheme(self, spec):
sec_scheme = {'type': 'apiKey', 'in': 'header', 'name': 'X-API-Key'}
spec.components.security_scheme('ApiKeyAuth', **sec_scheme)
assert get_security_schemes(spec)['ApiKeyAuth'] == sec_scheme

def test_security_scheme_is_chainable(self, spec):
spec.components.security_scheme('sec_1').security_scheme('sec_2')
security_schemes = get_security_schemes(spec)
assert 'sec_1' in security_schemes
assert 'sec_2' in security_schemes

def test_security_scheme_duplicate_name(self, spec):
sec_scheme_1 = {'type': 'apiKey', 'in': 'header', 'name': 'X-API-Key'}
sec_scheme_2 = {'type': 'apiKey', 'in': 'header', 'name': 'X-API-Key-2'}
spec.components.security_scheme('ApiKeyAuth', **sec_scheme_1)
with pytest.raises(
DuplicateComponentNameError,
match='Another security scheme with name "ApiKeyAuth" is already registered.',
):
spec.components.security_scheme('ApiKeyAuth', **sec_scheme_2)

def test_path_check_invalid_http_method(self, spec):
spec.path('/pet/{petId}', operations={'get': {}})
spec.path('/pet/{petId}', operations={'x-dummy': {}})
Expand Down
5 changes: 5 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def get_responses(spec):
return spec.to_dict()['responses']
return spec.to_dict()['components']['responses']

def get_security_schemes(spec):
if spec.openapi_version.major < 3:
return spec.to_dict()['securityDefinitions']
return spec.to_dict()['components']['securitySchemes']

def get_paths(spec):
return spec.to_dict()['paths']

Expand Down