-
-
Notifications
You must be signed in to change notification settings - Fork 767
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
Attach operation specification to connexion.request #937
Comments
Right, I agree. That info could be exposed to the views, somehow. At this moment I don't know how we should do that though. |
Was any progress made on this? I am attempting to implement role-based access by specifying allowed roles by adding |
+1 I'm trying to find a way to get at the schema of the current operation because the defaults are not provided in json body objects |
Perhaps the same way that the request context is passed ? |
@brockhaywood We have since moved away from connexion to using FastAPI instead, but if it is of any help to you, this is how we solved this issue, specifically with our role based access functionality. During the setup of the app, it looked like this. This is how we would get access to the OpenAPI specification at arbitrary points in the application. Assume we had a specification which defines a path like this. Note the custom paths:
/admin/grant-tokens:
post:
tags:
- tokens
x-roles:
- admin
summary: Grant pre-paid tokens
description: >
Generate and save pre-paid tokens to a user
requestBody:
required: true
description: Information about the tokens and who to grant tokens to
content:
application/json:
schema:
$ref: "#/components/schemas/GrantTokensRequest"
responses:
"200":
description: Returns an empty response if successful
"403":
description: Unauthorized
"500":
description: Internal server error app = connexion.App(__name__, specification_dir="./openapi/", options=options)
openapi_definition = "openapi.yaml"
spec = app.add_api(openapi_definition, arguments={"title": "app"}, validate_responses=True).specification
app.app.config["specification"] = spec Then, in our security controller, we had these functions. def get_current_operation_id() -> str:
spec = current_app.config["specification"]
# connexion converts {} to <>, so have to convert it back for it to be a correct operationId
operation_id = request.url_rule.rule.replace(spec.base_path, "").replace("<", "{").replace(">", "}") # type: str
return operation_id This function would retrieve the the def get_current_operation_roles() -> List[str]:
spec = current_app.config["specification"]
operation_id = get_current_operation_id()
try:
operation = spec.get_operation(operation_id, request.method.lower())
except Exception:
logging.getLogger(__name__).exception("Failed to match request to an operation")
# Kind of ugly to throw an error like this, but better to return an internal server error
# than to accidentally let users without the appropriate role get access
raise Exception("Failed to match request to an operation")
return operation.get("x-roles", []) # type: ignore We would then call this function during the authentication step in our security_controller_.py. |
@frjonsen thanks! that is quite helpful. I'm going to play around with this approach. |
Flask does only rudimentary JSON deserialisation to primitives or dictionaries. With named types defined in the swagger spec (object declarations) we could deserialise the dicts to custom DTO classes (which also could be easily generated). However during decoding in
app.json_decoder
we only get a dictionary and there is no way of telling which type we should transform to. It would be great if connexion exposed some kind of information about the spec for the current view.Example code I played around with
Actual behaviour
I couldn't find any such meta information on the request.
Additional info:
The text was updated successfully, but these errors were encountered: