mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-28 19:19:52 +00:00
Merge pull request #284 from p1c2u/fix/remove-security-fix
Remove security on operation level fix
This commit is contained in:
commit
f2b5bbe1f3
6 changed files with 148 additions and 13 deletions
|
@ -42,12 +42,16 @@ class OperationsGenerator(object):
|
||||||
tags_list = operation_deref.get('tags', [])
|
tags_list = operation_deref.get('tags', [])
|
||||||
summary = operation_deref.get('summary')
|
summary = operation_deref.get('summary')
|
||||||
description = operation_deref.get('description')
|
description = operation_deref.get('description')
|
||||||
security_spec = operation_deref.get('security', [])
|
|
||||||
servers_spec = operation_deref.get('servers', [])
|
servers_spec = operation_deref.get('servers', [])
|
||||||
|
|
||||||
servers = self.servers_generator.generate(servers_spec)
|
servers = self.servers_generator.generate(servers_spec)
|
||||||
security = self.security_requirements_generator.generate(
|
|
||||||
security_spec)
|
security = None
|
||||||
|
if 'security' in operation_deref:
|
||||||
|
security_spec = operation_deref.get('security')
|
||||||
|
security = self.security_requirements_generator.generate(
|
||||||
|
security_spec)
|
||||||
|
|
||||||
extensions = self.extensions_generator.generate(operation_deref)
|
extensions = self.extensions_generator.generate(operation_deref)
|
||||||
|
|
||||||
external_docs = None
|
external_docs = None
|
||||||
|
@ -67,7 +71,7 @@ class OperationsGenerator(object):
|
||||||
Operation(
|
Operation(
|
||||||
http_method, path_name, responses, list(parameters),
|
http_method, path_name, responses, list(parameters),
|
||||||
summary=summary, description=description,
|
summary=summary, description=description,
|
||||||
external_docs=external_docs, security=list(security),
|
external_docs=external_docs, security=security,
|
||||||
request_body=request_body, deprecated=deprecated,
|
request_body=request_body, deprecated=deprecated,
|
||||||
operation_id=operation_id, tags=list(tags_list),
|
operation_id=operation_id, tags=list(tags_list),
|
||||||
servers=list(servers), extensions=extensions,
|
servers=list(servers), extensions=extensions,
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Operation(object):
|
||||||
self.summary = summary
|
self.summary = summary
|
||||||
self.description = description
|
self.description = description
|
||||||
self.external_docs = external_docs
|
self.external_docs = external_docs
|
||||||
self.security = security
|
self.security = security and list(security)
|
||||||
self.request_body = request_body
|
self.request_body = request_body
|
||||||
self.deprecated = deprecated
|
self.deprecated = deprecated
|
||||||
self.operation_id = operation_id
|
self.operation_id = operation_id
|
||||||
|
|
|
@ -87,7 +87,10 @@ class RequestValidator(BaseValidator):
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_security(self, request, operation):
|
def _get_security(self, request, operation):
|
||||||
security = operation.security or self.spec.security
|
security = self.spec.security
|
||||||
|
if operation.security is not None:
|
||||||
|
security = operation.security
|
||||||
|
|
||||||
if not security:
|
if not security:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
41
tests/integration/data/v3.0/security_override.yaml
Normal file
41
tests/integration/data/v3.0/security_override.yaml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
openapi: "3.0.0"
|
||||||
|
info:
|
||||||
|
title: Minimal OpenAPI specification with security override
|
||||||
|
version: "0.1"
|
||||||
|
security:
|
||||||
|
- api_key: []
|
||||||
|
paths:
|
||||||
|
/resource/{resId}:
|
||||||
|
parameters:
|
||||||
|
- name: resId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: the ID of the resource to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: Default security.
|
||||||
|
post:
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: Override security.
|
||||||
|
put:
|
||||||
|
security: []
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: Remove security.
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
api_key:
|
||||||
|
type: apiKey
|
||||||
|
name: api_key
|
||||||
|
in: query
|
||||||
|
petstore_auth:
|
||||||
|
type: http
|
||||||
|
scheme: basic
|
|
@ -152,14 +152,15 @@ class TestPetstore(object):
|
||||||
assert variable.default == variable_spec['default']
|
assert variable.default == variable_spec['default']
|
||||||
assert variable.enum == variable_spec.get('enum')
|
assert variable.enum == variable_spec.get('enum')
|
||||||
|
|
||||||
security_spec = operation_spec.get('security', [])
|
security_spec = operation_spec.get('security')
|
||||||
for idx, security_req in enumerate(operation.security):
|
if security_spec is not None:
|
||||||
assert type(security_req) == SecurityRequirement
|
for idx, security_req in enumerate(operation.security):
|
||||||
|
assert type(security_req) == SecurityRequirement
|
||||||
|
|
||||||
security_req_spec = security_spec[idx]
|
security_req_spec = security_spec[idx]
|
||||||
for scheme_name in security_req:
|
for scheme_name in security_req:
|
||||||
security_req[scheme_name] == security_req_spec[
|
security_req[scheme_name] == security_req_spec[
|
||||||
scheme_name]
|
scheme_name]
|
||||||
|
|
||||||
responses_spec = operation_spec.get('responses')
|
responses_spec = operation_spec.get('responses')
|
||||||
|
|
||||||
|
|
86
tests/integration/validation/test_security_override.py
Normal file
86
tests/integration/validation/test_security_override.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from six import text_type
|
||||||
|
|
||||||
|
from openapi_core.shortcuts import create_spec
|
||||||
|
from openapi_core.validation.exceptions import InvalidSecurity
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
from openapi_core.testing import MockRequest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def request_validator(spec):
|
||||||
|
return RequestValidator(spec)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture('class')
|
||||||
|
def spec(factory):
|
||||||
|
spec_dict = factory.spec_from_file("data/v3.0/security_override.yaml")
|
||||||
|
return create_spec(spec_dict)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSecurityOverride(object):
|
||||||
|
|
||||||
|
host_url = 'http://petstore.swagger.io'
|
||||||
|
|
||||||
|
api_key = '12345'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def api_key_encoded(self):
|
||||||
|
api_key_bytes = self.api_key.encode('utf8')
|
||||||
|
api_key_bytes_enc = b64encode(api_key_bytes)
|
||||||
|
return text_type(api_key_bytes_enc, 'utf8')
|
||||||
|
|
||||||
|
def test_default(self, request_validator):
|
||||||
|
args = {'api_key': self.api_key}
|
||||||
|
request = MockRequest(
|
||||||
|
self.host_url, 'get', '/resource/one', args=args)
|
||||||
|
|
||||||
|
result = request_validator.validate(request)
|
||||||
|
|
||||||
|
assert not result.errors
|
||||||
|
assert result.security == {
|
||||||
|
'api_key': self.api_key,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_default_invalid(self, request_validator):
|
||||||
|
request = MockRequest(self.host_url, 'get', '/resource/one')
|
||||||
|
|
||||||
|
result = request_validator.validate(request)
|
||||||
|
|
||||||
|
assert type(result.errors[0]) == InvalidSecurity
|
||||||
|
assert result.security is None
|
||||||
|
|
||||||
|
def test_override(self, request_validator):
|
||||||
|
authorization = 'Basic ' + self.api_key_encoded
|
||||||
|
headers = {
|
||||||
|
'Authorization': authorization,
|
||||||
|
}
|
||||||
|
request = MockRequest(
|
||||||
|
self.host_url, 'post', '/resource/one', headers=headers)
|
||||||
|
|
||||||
|
result = request_validator.validate(request)
|
||||||
|
|
||||||
|
assert not result.errors
|
||||||
|
assert result.security == {
|
||||||
|
'petstore_auth': self.api_key_encoded,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_override_invalid(self, request_validator):
|
||||||
|
request = MockRequest(
|
||||||
|
self.host_url, 'post', '/resource/one')
|
||||||
|
|
||||||
|
result = request_validator.validate(request)
|
||||||
|
|
||||||
|
assert type(result.errors[0]) == InvalidSecurity
|
||||||
|
assert result.security is None
|
||||||
|
|
||||||
|
def test_remove(self, request_validator):
|
||||||
|
request = MockRequest(
|
||||||
|
self.host_url, 'put', '/resource/one')
|
||||||
|
|
||||||
|
result = request_validator.validate(request)
|
||||||
|
|
||||||
|
assert not result.errors
|
||||||
|
assert result.security == {}
|
Loading…
Reference in a new issue