Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 16 additions & 0 deletions src/lapidary_render/model/conv_cst.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@ def mk_security_fn(auth: python.Auth) -> cst.BaseStatement:
fn_name = cst.Name(f'{auth.type}_{auth.python_name}')

match auth:
case python.HttpBearerAuth(): # check first because it's a subclass of ApiKeyAuth
return mk_auth_http_bearer(auth, fn_name)
case python.ApiKeyAuth():
return mk_auth_api_key(cast(python.ApiKeyAuth, auth), fn_name)
case python.HttpBasicAuth():
Expand Down Expand Up @@ -660,6 +662,20 @@ def mk_auth_api_key(auth: python.ApiKeyAuth, fn_name: cst.Name):
auth_key=str_literal(auth.key),
)

def mk_auth_http_bearer(auth: python.HttpBearerAuth, fn_name: cst.Name):
param_name = auth.location.value + '_name'
return cst.helpers.parse_template_statement(
"""def {fn_name}(api_key: str) -> lapidary.runtime.NamedAuth:
return {auth_name}, {auth_class}(
api_key="Bearer " + api_key,
{param_name}={auth_key},
)""",
fn_name=fn_name,
auth_name=str_literal(auth.name),
auth_class=mk_name('lapidary', 'runtime', 'auth', auth.location.value.capitalize() + 'ApiKey'),
param_name=cst.Name(param_name),
auth_key=str_literal(auth.key),
)

def mk_security_module(module: python.SecurityModule) -> cst.Module:
return cst.Module(
Expand Down
25 changes: 21 additions & 4 deletions src/lapidary_render/model/conv_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,12 +401,14 @@ def process_security_requirement(
# need separate method to resolve references before calling a single-dispatched method
@resolve_ref
def process_security_scheme(self, value: openapi.SecurityScheme, stack: Stack) -> None:
match value.type:
case 'apiKey':
match value.type, value.scheme:
case 'apiKey', _:
self.process_security_scheme_api_key(value, stack)
case 'oauth2':
case 'oauth2', _:
self.process_security_scheme_oauth2(value, stack)
case 'http':
case 'http', 'bearer':
self.process_security_scheme_http_bearer(value, stack)
case 'http', _:
self.process_security_scheme_http(value, stack)

def process_security_scheme_api_key(self, value: openapi.SecurityScheme, stack: Stack) -> None:
Expand Down Expand Up @@ -507,6 +509,20 @@ def process_security_scheme_http(self, value: openapi.SecurityScheme, stack: Sta
except KeyError:
raise NotImplementedError(stack.push('scheme'), value.scheme) from None

def process_security_scheme_http_bearer(self, value: openapi.SecurityScheme, stack: Stack) -> None:
logger.debug('Process HTTP Bearer security scheme %s', stack)
auth_name = stack.top()
flow_name = f'http_{auth_name}'

if flow_name in self.target.security_schemes:
return

self.target.security_schemes[flow_name] = python.HttpBearerAuth(
name=auth_name,
python_name=names.maybe_mangle_name(auth_name),
format=value.format,
)


def param_style(
style: str | None,
Expand Down Expand Up @@ -568,4 +584,5 @@ def map_process(
HTTP_SCHEMES = {
'basic': python.HttpBasicAuth,
'digest': python.HttpDigestAuth,
'bearer': python.HttpBearerAuth,
}
1 change: 1 addition & 0 deletions src/lapidary_render/model/python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
ClientInit,
HttpBasicAuth,
HttpDigestAuth,
HttpBearerAuth,
ImplicitOAuth2Flow,
MetadataModel,
MimeMap,
Expand Down
9 changes: 9 additions & 0 deletions src/lapidary_render/model/python/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ class HttpBasicAuth(Auth):
type: str = 'http_basic'


@dc.dataclass(kw_only=True, frozen=True)
class HttpBearerAuth(ApiKeyAuth):
type: str = 'http'
scheme: str = 'bearer'
key: str = 'Authorization'
location: ParamLocation = ParamLocation.HEADER
format: str | None = 'bearer_token'
bearer_format: str | None = 'bearer_token'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?
Did you write this code yourself?


@dc.dataclass(kw_only=True, frozen=True)
class HttpDigestAuth(Auth):
scheme: str = 'digest'
Expand Down
4 changes: 4 additions & 0 deletions tests/e2e/render/expected/dummy/lapidary/openapi/dummy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ components:
http_digest:
type: http
scheme: digest
http_bearer:
type: http
scheme: bearer
responses:
default:
content:
Expand Down Expand Up @@ -265,3 +268,4 @@ security:
- api-key-query: [ ]
- http_basic: [ ]
- http_digest: [ ]
- http_bearer: [ ]
1 change: 1 addition & 0 deletions tests/e2e/render/expected/dummy/src/test_dummy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(
{'api-key-query': ()},
{'http_basic': ()},
{'http_digest': ()},
{'http_bearer': ()},
),
base_url=base_url,
**kwargs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,10 @@ def http_digest_http_digest(
username=user_name,
password=password,
)


def http_http_bearer(api_key: str) -> lapidary.runtime.NamedAuth:
return 'http_bearer', lapidary.runtime.auth.HeaderApiKey(
api_key="Bearer " + api_key,
header_name='Authorization',
)
4 changes: 4 additions & 0 deletions tests/e2e/render/initial/dummy/lapidary/openapi/dummy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ components:
http_digest:
type: http
scheme: digest
http_bearer:
type: http
scheme: bearer
responses:
default:
content:
Expand Down Expand Up @@ -265,3 +268,4 @@ security:
- api-key-query: [ ]
- http_basic: [ ]
- http_digest: [ ]
- http_bearer: [ ]
3 changes: 3 additions & 0 deletions tests/process/security_schemes/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ components:
name: Authorization
type: apiKey
in: cookie
bearerToken:
type: http
scheme: bearer
9 changes: 9 additions & 0 deletions tests/process/test_security_scheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,12 @@ def test_process_security_schemes(path: Path):
location=python.ParamLocation.COOKIE,
format='{}',
)
assert converter.target.security_schemes['http_bearerToken'] == python.HttpBearerAuth(
type='http',
scheme='bearer',
name='bearerToken',
python_name='bearerToken',
key='Authorization',
location=python.ParamLocation.HEADER,
format = '{}'
)