
We started decorating Keystone with schema validation similarly to other services. Since Keystone uses Flask and thus we do not use base processing split the processing into separate method and call it. Change-Id: I4e70b85bb16a40cb3dff0d5ddc6004aabe0d1c62
184 lines
6.1 KiB
Python
184 lines
6.1 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
import copy
|
|
|
|
from typing import Any
|
|
|
|
from keystone.application_credential import (
|
|
schema as application_credential_schema,
|
|
)
|
|
|
|
from codegenerator.common.schema import TypeSchema
|
|
from codegenerator.common.schema import ParameterSchema
|
|
from codegenerator.openapi.keystone_schemas import common
|
|
|
|
# Application Credentials
|
|
APPLICATION_CREDENTIAL_ACCESS_RULES_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"access_rules": copy.deepcopy(
|
|
application_credential_schema._access_rules_properties
|
|
),
|
|
"links": copy.deepcopy(common.LINKS_SCHEMA),
|
|
},
|
|
}
|
|
|
|
APPLICATION_CREDENTIAL_ACCESS_RULE_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"access_rule": copy.deepcopy(
|
|
application_credential_schema._access_rules_properties["items"]
|
|
),
|
|
},
|
|
}
|
|
|
|
APPLICATION_CREDENTIAL_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "The ID of the application credential.",
|
|
},
|
|
"project_id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "The ID of the project the application credential was created for and that authentication requests using this application credential will be scoped to.",
|
|
},
|
|
**application_credential_schema._application_credential_properties,
|
|
},
|
|
}
|
|
APPLICATION_CREDENTIAL_SCHEMA["properties"].pop("secret", None)
|
|
|
|
APPLICATION_CREDENTIAL_CONTAINER_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"application_credential": copy.deepcopy(APPLICATION_CREDENTIAL_SCHEMA)
|
|
},
|
|
}
|
|
|
|
APPLICATION_CREDENTIAL_CREATE_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"application_credential": copy.deepcopy(
|
|
application_credential_schema.application_credential_create
|
|
)
|
|
},
|
|
}
|
|
|
|
APPLICATION_CREDENTIAL_CREATE_RESPONSE_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"application_credential": copy.deepcopy(APPLICATION_CREDENTIAL_SCHEMA)
|
|
},
|
|
}
|
|
# Update `secret` field
|
|
APPLICATION_CREDENTIAL_CREATE_RESPONSE_SCHEMA["properties"][
|
|
"application_credential"
|
|
]["properties"]["secret"] = {
|
|
"type": "string",
|
|
"description": "The secret for the application credential, either generated by the server or provided by the user. This is only ever shown once in the response to a create request. It is not stored nor ever shown again. If the secret is lost, a new application credential must be created.",
|
|
}
|
|
|
|
APPLICATION_CREDENTIALS_SCHEMA: dict[str, Any] = {
|
|
"type": "object",
|
|
"properties": {
|
|
"application_credentials": {
|
|
"type": "array",
|
|
"items": copy.deepcopy(APPLICATION_CREDENTIAL_SCHEMA),
|
|
},
|
|
},
|
|
}
|
|
|
|
APPLICATION_CREDENTIALS_LIST_PARAMETERS = {
|
|
"application_credentials_name": {
|
|
"in": "query",
|
|
"name": "name",
|
|
"description": "The name of the application credential. Must be unique to a user.",
|
|
"schema": {"type": "string"},
|
|
},
|
|
}
|
|
|
|
|
|
def _post_process_operation_hook(
|
|
openapi_spec, operation_spec, path: str | None = None
|
|
):
|
|
"""Hook to allow service specific generator to modify details"""
|
|
operationId = operation_spec.operationId
|
|
if operationId == "users/user_id/application_credentials:get":
|
|
for (
|
|
key,
|
|
val,
|
|
) in APPLICATION_CREDENTIALS_LIST_PARAMETERS.items():
|
|
openapi_spec.components.parameters.setdefault(
|
|
key, ParameterSchema(**val)
|
|
)
|
|
ref = f"#/components/parameters/{key}"
|
|
if ref not in [x.ref for x in operation_spec.parameters]:
|
|
operation_spec.parameters.append(ParameterSchema(ref=ref))
|
|
|
|
|
|
def _get_schema_ref(
|
|
openapi_spec,
|
|
name,
|
|
description=None,
|
|
schema_def=None,
|
|
action_name=None,
|
|
) -> tuple[str | None, str | None, bool]:
|
|
mime_type: str = "application/json"
|
|
ref: str
|
|
# ### Application Credentials
|
|
if name == "UsersAccess_RuleGetResponse":
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIAL_ACCESS_RULE_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
elif name == "UsersAccess_RulesGetResponse":
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIAL_ACCESS_RULES_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
elif name == "UsersApplication_CredentialsGetResponse":
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIALS_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
elif name in [
|
|
"UsersApplication_CredentialGetResponse",
|
|
]:
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIAL_CONTAINER_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
elif name == "UsersApplication_CredentialsPostRequest":
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIAL_CREATE_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
elif name == "UsersApplication_CredentialsPostResponse":
|
|
openapi_spec.components.schemas.setdefault(
|
|
name,
|
|
TypeSchema(**APPLICATION_CREDENTIAL_CREATE_RESPONSE_SCHEMA),
|
|
)
|
|
ref = f"#/components/schemas/{name}"
|
|
|
|
else:
|
|
return (None, None, False)
|
|
|
|
return (ref, mime_type, True)
|