Skip to content
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

ACSBP-3718 Update to use openapi 3.1 #284

Merged
merged 27 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9fc2c1a
use 3.1.0
auramix Mar 15, 2023
81540e7
update comment
auramix Mar 15, 2023
1f9256d
updated v3 version
auramix Mar 15, 2023
c3c9299
change references from 3.0.2 --> 3.1.0
auramix Mar 15, 2023
84d6543
update json-schema for v3
auramix Mar 16, 2023
5a466af
uppercase booleans
auramix Mar 16, 2023
b93b320
black reformat
auramix Mar 16, 2023
98c0b49
black created some line length problems for flake8
auramix Mar 17, 2023
ecd3e0b
convert to using null as a type
auramix May 12, 2023
742e008
Merge branch 'master' into acsbp-3718
auramix May 12, 2023
ea3868a
updates for 3.1
auramix May 15, 2023
dec0e66
fix linting with black
auramix May 15, 2023
8130195
Merge branch 'master' into acsbp-3718
auramix May 16, 2023
64b34cd
swagger: update static dir with latest dist files
auramix May 20, 2023
2565a42
readme: add shell command for replacing ui files
auramix May 25, 2023
49631b9
Merge branch 'master' into acsbp-3718
auramix Jul 26, 2023
3b816b8
update static files
auramix Jul 26, 2023
e1db68e
fix version
auramix Jul 26, 2023
c4bf500
Bump version: 2.4.1 → 3.0.0
auramix Jul 26, 2023
913efaa
update OApi 3.1 spec
auramix Jul 26, 2023
439affa
replace false -> False
auramix Jul 26, 2023
cf8bc7a
update true -> True
auramix Jul 26, 2023
8474029
set id to schema url as per
auramix Jul 26, 2023
355b1c8
Revert "set id to schema url as per"
auramix Jul 27, 2023
81c3516
update jsonschema
auramix Jul 27, 2023
5bfce94
lint: blackify
auramix Jul 27, 2023
1bc656e
remove B950 update
auramix Aug 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ max-line-length = 120
exclude = .git/*, build/*, examples/*, venv/*, setup.py
per-file-ignores =
flask_rebar/__init__.py: F401 flask_rebar/*/__init__.py: F401
select = B950
extend-ignore = E501
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't have a problem with us switching to B950 instead of E501, but this change should be made in a separate PR.

9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ Installation
pip install flask-rebar


Replacing static swagger-ui files
-------------

If you'd like to replace swagger-ui's static files (`flask_rebar/swagger_ui/static`) with those of the latest release,
run the following from the root of the project.

.. code-block::
curl -L https://api.github.com/repos/swagger-api/swagger-ui/tarball | tar -xv --directory=flask_rebar/swagger_ui/static --strip-components=2 "*/dist/"
Copy link
Contributor

Choose a reason for hiding this comment

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

nice


Documentation
-------------

Expand Down
6 changes: 3 additions & 3 deletions flask_rebar/swagger_generation/authenticator_to_swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ def get_security_schemes(self, obj, context):

OpenAPI Specification for defining security schemes
2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object
3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#fixed-fields-6
3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#fixed-fields-6
(see securitySchemes field)

OpenAPI Specification for Security Scheme Object
2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-scheme-object
3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#security-scheme-object
3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#security-scheme-object


Example: An authenticator that makes use of an api_key and an application_key scheme
Expand Down Expand Up @@ -81,7 +81,7 @@ def get_security_requirements(self, obj, context):

OpenAPI Specification for Security Requirement Object
2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object
3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#security-requirement-object
3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#security-requirement-object

Example: Require oauth with scope "read:stuff" OR api_key AND application_key
[
Expand Down
45 changes: 27 additions & 18 deletions flask_rebar/swagger_generation/marshmallow_to_swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,16 @@ def convert(self, obj, context):
)
)

if context.openapi_version == 3 and obj.allow_none:
jsonschema_obj["nullable"] = True

return jsonschema_obj

# With OpenApi 3.1 nullable has been removed entirely
# and allowing 'none' means we return an array of allowed types that includes sw.null
auramix marked this conversation as resolved.
Show resolved Hide resolved
def null_type_determination(self, obj, context, sw_type):
if context.openapi_version == 3 and obj.allow_none:
return [sw_type, sw.null]
else:
return sw_type

@sets_swagger_attr(sw.default)
def get_default(self, obj, context):
if (
Expand Down Expand Up @@ -349,7 +354,7 @@ class ListConverter(FieldConverter):

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.array
return self.null_type_determination(obj, context, sw.array)

@sets_swagger_attr(sw.items)
def get_items(self, obj, context):
Expand All @@ -361,47 +366,47 @@ class DictConverter(FieldConverter):

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.object_
return self.null_type_determination(obj, context, sw.object_)


class IntegerConverter(FieldConverter):
MARSHMALLOW_TYPE = m.fields.Integer

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.integer
return self.null_type_determination(obj, context, sw.integer)


class StringConverter(FieldConverter):
MARSHMALLOW_TYPE = m.fields.String

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.string
return self.null_type_determination(obj, context, sw.string)


class NumberConverter(FieldConverter):
MARSHMALLOW_TYPE = m.fields.Number

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.number
return self.null_type_determination(obj, context, sw.number)


class BooleanConverter(FieldConverter):
MARSHMALLOW_TYPE = m.fields.Boolean

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.boolean
return self.null_type_determination(obj, context, sw.boolean)


class DateTimeConverter(FieldConverter):
MARSHMALLOW_TYPE = m.fields.DateTime

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.string
return self.null_type_determination(obj, context, sw.string)

@sets_swagger_attr(sw.format_)
def get_format(self, obj, context):
Expand All @@ -413,7 +418,7 @@ class UUIDConverter(FieldConverter):

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.string
return self.null_type_determination(obj, context, sw.string)

@sets_swagger_attr(sw.format_)
def get_format(self, obj, context):
Expand All @@ -425,7 +430,7 @@ class DateConverter(FieldConverter):

@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
return sw.string
return self.null_type_determination(obj, context, sw.string)

@sets_swagger_attr(sw.format_)
def get_format(self, obj, context):
Expand All @@ -438,7 +443,9 @@ class MethodConverter(FieldConverter):
@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
if "swagger_type" in obj.metadata:
return obj.metadata["swagger_type"]
return self.null_type_determination(
obj, context, obj.metadata["swagger_type"]
)
else:
raise ValueError(
'Must include "swagger_type" ' "keyword argument in Method field"
Expand All @@ -451,7 +458,9 @@ class FunctionConverter(FieldConverter):
@sets_swagger_attr(sw.type_)
def get_type(self, obj, context):
if "swagger_type" in obj.metadata:
return obj.metadata["swagger_type"]
return self.null_type_determination(
obj, context, obj.metadata["swagger_type"]
)
else:
raise ValueError(
'Must include "swagger_type" ' "keyword argument in Function field"
Expand Down Expand Up @@ -653,13 +662,13 @@ def get_type(self, obj, context):
# I'm going out on a limb and assuming your enum uses same type for all vals, else caveat emptor:
value_type = type(next(iter(obj.enum)).value)
if value_type is int:
return sw.integer
return self.null_type_determination(obj, context, sw.integer)
elif value_type is float:
return sw.number
return self.null_type_determination(obj, context, sw.number)
else:
return sw.string
return self.null_type_determination(obj, context, sw.string)
else:
return sw.string
return self.null_type_determination(obj, context, sw.string)

@sets_swagger_attr(sw.enum)
def get_enum(self, obj, context):
Expand Down
4 changes: 2 additions & 2 deletions flask_rebar/swagger_generation/swagger_generator_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


class SwaggerV3Generator(SwaggerGenerator):
"""Generates a v3.0.2 Swagger specification from a Rebar object.
"""Generates a v3.1.0 Swagger specification from a Rebar object.

Not all things are retrievable from the Rebar object, so this
guy also needs some additional information to complete the job.
Expand All @@ -49,7 +49,7 @@ class SwaggerV3Generator(SwaggerGenerator):
A list of Server Objects to set as the server metadata for the specification.
"""

_open_api_version = "3.0.2"
_open_api_version = "3.1.0"

def __init__(
self,
Expand Down
Binary file modified flask_rebar/swagger_ui/static/favicon-16x16.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified flask_rebar/swagger_ui/static/favicon-32x32.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions flask_rebar/swagger_ui/static/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body {
margin: 0;
background: #fafafa;
}
19 changes: 19 additions & 0 deletions flask_rebar/swagger_ui/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>

<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
40 changes: 26 additions & 14 deletions flask_rebar/swagger_ui/static/oauth2-redirect.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<!doctype html>
<html lang="en-US">
<body onload="run()">
</body>
</html>
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
Expand All @@ -12,31 +13,32 @@
var isValid, qp, arr;

if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}

arr = qp.split("&")
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value)
return key === "" ? value : decodeURIComponent(value);
}
) : {}
) : {};

isValid = qp.state === sentState
isValid = qp.state === sentState;

if ((
oauth2.auth.schema.get("flow") === "accessCode"||
oauth2.auth.schema.get("flow") === "authorizationCode"
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}

Expand All @@ -45,7 +47,7 @@
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
Expand All @@ -56,12 +58,22 @@
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}

if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions flask_rebar/swagger_ui/static/swagger-initializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">

// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});

//</editor-fold>
};
100 changes: 2 additions & 98 deletions flask_rebar/swagger_ui/static/swagger-ui-bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion flask_rebar/swagger_ui/static/swagger-ui-bundle.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions flask_rebar/swagger_ui/static/swagger-ui-es-bundle-core.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions flask_rebar/swagger_ui/static/swagger-ui-es-bundle.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.