Skip to content

Commit d915f23

Browse files
committed
Security validation with Api Key support
1 parent 75643da commit d915f23

File tree

18 files changed

+219
-37
lines changed

18 files changed

+219
-37
lines changed

openapi_core/schema/components/factories.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from openapi_core.compat import lru_cache
22
from openapi_core.schema.components.models import Components
33
from openapi_core.schema.schemas.generators import SchemasGenerator
4+
from openapi_core.schema.security_schemes.generators import (
5+
SecuritySchemesGenerator,
6+
)
47

58

69
class ComponentsFactory(object):
@@ -15,15 +18,18 @@ def create(self, components_spec):
1518
schemas_spec = components_deref.get('schemas', {})
1619
responses_spec = components_deref.get('responses', {})
1720
parameters_spec = components_deref.get('parameters', {})
18-
request_bodies_spec = components_deref.get('request_bodies', {})
21+
request_bodies_spec = components_deref.get('requestBodies', {})
22+
security_schemes_spec = components_deref.get('securitySchemes', {})
1923

2024
schemas = self.schemas_generator.generate(schemas_spec)
2125
responses = self._generate_response(responses_spec)
2226
parameters = self._generate_parameters(parameters_spec)
2327
request_bodies = self._generate_request_bodies(request_bodies_spec)
28+
security_schemes = self._generate_security_schemes(
29+
security_schemes_spec)
2430
return Components(
2531
schemas=list(schemas), responses=responses, parameters=parameters,
26-
request_bodies=request_bodies,
32+
request_bodies=request_bodies, security_schemes=security_schemes,
2733
)
2834

2935
@property
@@ -39,3 +45,7 @@ def _generate_parameters(self, parameters_spec):
3945

4046
def _generate_request_bodies(self, request_bodies_spec):
4147
return request_bodies_spec
48+
49+
def _generate_security_schemes(self, security_schemes_spec):
50+
return SecuritySchemesGenerator(self.dereferencer).generate(
51+
security_schemes_spec)

openapi_core/schema/components/models.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ class Components(object):
33

44
def __init__(
55
self, schemas=None, responses=None, parameters=None,
6-
request_bodies=None):
6+
request_bodies=None, security_schemes=None):
77
self.schemas = schemas and dict(schemas) or {}
88
self.responses = responses and dict(responses) or {}
99
self.parameters = parameters and dict(parameters) or {}
1010
self.request_bodies = request_bodies and dict(request_bodies) or {}
11+
self.security_schemes = (
12+
security_schemes and dict(security_schemes) or {}
13+
)

openapi_core/schema/operations/generators.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
from openapi_core.schema.parameters.generators import ParametersGenerator
1212
from openapi_core.schema.request_bodies.factories import RequestBodyFactory
1313
from openapi_core.schema.responses.generators import ResponsesGenerator
14-
from openapi_core.schema.security.factories import SecurityRequirementFactory
14+
from openapi_core.schema.security_requirements.generators import (
15+
SecurityRequirementsGenerator,
16+
)
1517
from openapi_core.schema.servers.generators import ServersGenerator
1618

1719

@@ -39,16 +41,12 @@ def generate(self, path_name, path):
3941
tags_list = operation_deref.get('tags', [])
4042
summary = operation_deref.get('summary')
4143
description = operation_deref.get('description')
42-
security_requirements_list = operation_deref.get('security', [])
44+
security_spec = operation_deref.get('security', [])
4345
servers_spec = operation_deref.get('servers', [])
4446

4547
servers = self.servers_generator.generate(servers_spec)
46-
47-
security = None
48-
if security_requirements_list:
49-
security = list(map(
50-
self.security_requirement_factory.create,
51-
security_requirements_list))
48+
security = self.security_requirements_generator.generate(
49+
security_spec)
5250

5351
external_docs = None
5452
if 'externalDocs' in operation_deref:
@@ -67,10 +65,10 @@ def generate(self, path_name, path):
6765
Operation(
6866
http_method, path_name, responses, list(parameters),
6967
summary=summary, description=description,
70-
external_docs=external_docs, security=security,
68+
external_docs=external_docs, security=list(security),
7169
request_body=request_body, deprecated=deprecated,
7270
operation_id=operation_id, tags=list(tags_list),
73-
servers=servers,
71+
servers=list(servers),
7472
),
7573
)
7674

@@ -96,8 +94,8 @@ def request_body_factory(self):
9694

9795
@property
9896
@lru_cache()
99-
def security_requirement_factory(self):
100-
return SecurityRequirementFactory(self.dereferencer)
97+
def security_requirements_generator(self):
98+
return SecurityRequirementsGenerator(self.dereferencer)
10199

102100
@property
103101
@lru_cache()

openapi_core/schema/security/factories.py

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""OpenAPI core security requirements generators module"""
2+
from openapi_core.schema.security_requirements.models import (
3+
SecurityRequirement,
4+
)
5+
6+
7+
class SecurityRequirementsGenerator(object):
8+
9+
def __init__(self, dereferencer):
10+
self.dereferencer = dereferencer
11+
12+
def generate(self, security_spec):
13+
security_deref = self.dereferencer.dereference(security_spec)
14+
for security_requirement_spec in security_deref:
15+
name = next(iter(security_requirement_spec))
16+
scope_names = security_requirement_spec[name]
17+
18+
yield SecurityRequirement(name, scope_names=scope_names)

openapi_core/schema/security/models.py renamed to openapi_core/schema/security_requirements/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""OpenAPI core security models module"""
1+
"""OpenAPI core security requirements models module"""
22

33

44
class SecurityRequirement(object):

openapi_core/schema/security_schemes/__init__.py

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""OpenAPI core security schemes enums module"""
2+
from enum import Enum
3+
4+
5+
class SecuritySchemeType(Enum):
6+
7+
API_KEY = 'apiKey'
8+
HTTP = 'http'
9+
OAUTH2 = 'oauth2'
10+
OPEN_ID_CONNECT = 'openIdConnect'
11+
12+
13+
class ApiKeyLocation(Enum):
14+
15+
QUERY = 'query'
16+
HEADER = 'header'
17+
COOKIE = 'cookie'
18+
19+
@classmethod
20+
def has_value(cls, value):
21+
return (any(value == item.value for item in cls))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""OpenAPI core security schemes generators module"""
2+
import logging
3+
4+
from six import iteritems
5+
6+
from openapi_core.schema.security_schemes.models import SecurityScheme
7+
8+
log = logging.getLogger(__name__)
9+
10+
11+
class SecuritySchemesGenerator(object):
12+
13+
def __init__(self, dereferencer):
14+
self.dereferencer = dereferencer
15+
16+
def generate(self, security_schemes_spec):
17+
security_schemes_deref = self.dereferencer.dereference(
18+
security_schemes_spec)
19+
20+
for scheme_name, scheme_spec in iteritems(security_schemes_deref):
21+
scheme_deref = self.dereferencer.dereference(scheme_spec)
22+
scheme_type = scheme_deref['type']
23+
description = scheme_deref.get('description')
24+
name = scheme_deref.get('name')
25+
apikey_in = scheme_deref.get('in')
26+
scheme = scheme_deref.get('scheme')
27+
bearer_format = scheme_deref.get('bearerFormat')
28+
flows = scheme_deref.get('flows')
29+
open_id_connect_url = scheme_deref.get('openIdConnectUrl')
30+
31+
scheme = SecurityScheme(
32+
scheme_type, description=description, name=name,
33+
apikey_in=apikey_in, scheme=scheme,
34+
bearer_format=bearer_format, flows=flows,
35+
open_id_connect_url=open_id_connect_url,
36+
)
37+
yield scheme_name, scheme

0 commit comments

Comments
 (0)