Add swagger-ui auth hooks
Save authorization to local storage, refetch spec on auth, etc.master
parent
d41f0c5ac4
commit
a419eec071
|
|
@ -27,12 +27,14 @@
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3 (drf-yasg)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3 (drf-yasg)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="immutable" level="application" />
|
||||||
</component>
|
</component>
|
||||||
<component name="TemplatesService">
|
<component name="TemplatesService">
|
||||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||||
<option name="TEMPLATE_FOLDERS">
|
<option name="TEMPLATE_FOLDERS">
|
||||||
<list>
|
<list>
|
||||||
<option value="$MODULE_DIR$/src/drf_yasg/templates" />
|
<option value="$MODULE_DIR$/src/drf_yasg/templates" />
|
||||||
|
<option value="$MODULE_DIR$/testproj/testproj/templates" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$" libraries="{immutable}" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -33,7 +33,7 @@ SWAGGER_DEFAULTS = {
|
||||||
|
|
||||||
'USE_SESSION_AUTH': True,
|
'USE_SESSION_AUTH': True,
|
||||||
'SECURITY_DEFINITIONS': {
|
'SECURITY_DEFINITIONS': {
|
||||||
'basic': {
|
'Basic': {
|
||||||
'type': 'basic'
|
'type': 'basic'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -1,27 +1,60 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
var currentPath = window.location.protocol + "//" + window.location.host + window.location.pathname;
|
var currentPath = window.location.protocol + "//" + window.location.host + window.location.pathname;
|
||||||
var specURL = currentPath + '?format=openapi';
|
var defaultSpecUrl = currentPath + '?format=openapi';
|
||||||
|
var savedAuth = Immutable.fromJS({});
|
||||||
|
try {
|
||||||
|
savedAuth = Immutable.fromJS(JSON.parse(localStorage.getItem("drf-yasg-auth")) || {});
|
||||||
|
} catch (e) {
|
||||||
|
localStorage.removeItem("drf-yasg-auth");
|
||||||
|
}
|
||||||
|
var swaggerUiConfig = {
|
||||||
|
url: defaultSpecUrl,
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
displayRequestDuration: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout",
|
||||||
|
filter: true,
|
||||||
|
requestInterceptor: function (request) {
|
||||||
|
var headers = request.headers || {};
|
||||||
|
var csrftoken = document.querySelector("[name=csrfmiddlewaretoken]");
|
||||||
|
if (csrftoken) {
|
||||||
|
headers["X-CSRFToken"] = csrftoken.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.loadSpec) {
|
||||||
|
applyAuth(savedAuth, headers);
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
},
|
||||||
|
onComplete: function () {
|
||||||
|
preauthorizeAny(savedAuth, window.ui);
|
||||||
|
hookAuthActions(window.ui);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
function patchSwaggerUi() {
|
function patchSwaggerUi() {
|
||||||
|
if (document.querySelector('.auth-wrapper #django-session-auth')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var authWrapper = document.querySelector('.auth-wrapper');
|
var authWrapper = document.querySelector('.auth-wrapper');
|
||||||
var authorizeButton = document.querySelector('.auth-wrapper .authorize');
|
var authorizeButton = document.querySelector('.auth-wrapper .authorize');
|
||||||
var djangoSessionAuth = document.querySelector('#django-session-auth');
|
var djangoSessionAuth = document.querySelector('#django-session-auth');
|
||||||
|
|
||||||
if (!djangoSessionAuth) {
|
if (!djangoSessionAuth) {
|
||||||
console.log("WARNING: session auth disabled");
|
console.log("WARNING: session auth disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.querySelector('.auth-wrapper #django-session-auth')) {
|
djangoSessionAuth = djangoSessionAuth.cloneNode(true);
|
||||||
console.log("WARNING: session auth already patched; skipping patchSwaggerUi()");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
authWrapper.insertBefore(djangoSessionAuth, authorizeButton);
|
authWrapper.insertBefore(djangoSessionAuth, authorizeButton);
|
||||||
djangoSessionAuth.classList.remove("hidden");
|
djangoSessionAuth.classList.remove("hidden");
|
||||||
|
|
||||||
var divider = document.createElement("div");
|
|
||||||
divider.classList.add("divider");
|
|
||||||
authWrapper.insertBefore(divider, authorizeButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initSwaggerUi() {
|
function initSwaggerUi() {
|
||||||
|
|
@ -29,28 +62,6 @@ function initSwaggerUi() {
|
||||||
console.log("WARNING: skipping initSwaggerUi() because window.ui is already defined");
|
console.log("WARNING: skipping initSwaggerUi() because window.ui is already defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var swaggerConfig = {
|
|
||||||
url: specURL,
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
displayRequestDuration: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout",
|
|
||||||
filter: true,
|
|
||||||
requestInterceptor: function (request) {
|
|
||||||
var headers = request.headers || {};
|
|
||||||
var csrftoken = document.querySelector("[name=csrfmiddlewaretoken]");
|
|
||||||
if (csrftoken) {
|
|
||||||
headers["X-CSRFToken"] = csrftoken.value;
|
|
||||||
}
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var swaggerSettings = JSON.parse(document.getElementById('swagger-settings').innerHTML);
|
var swaggerSettings = JSON.parse(document.getElementById('swagger-settings').innerHTML);
|
||||||
if (!('oauth2RedirectUrl' in swaggerSettings)) {
|
if (!('oauth2RedirectUrl' in swaggerSettings)) {
|
||||||
|
|
@ -64,23 +75,82 @@ function initSwaggerUi() {
|
||||||
console.log('swaggerSettings', swaggerSettings);
|
console.log('swaggerSettings', swaggerSettings);
|
||||||
for (var p in swaggerSettings) {
|
for (var p in swaggerSettings) {
|
||||||
if (swaggerSettings.hasOwnProperty(p)) {
|
if (swaggerSettings.hasOwnProperty(p)) {
|
||||||
swaggerConfig[p] = swaggerSettings[p];
|
swaggerUiConfig[p] = swaggerSettings[p];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.ui = SwaggerUIBundle(swaggerConfig);
|
|
||||||
|
|
||||||
var oauth2Config = JSON.parse(document.getElementById('oauth2-config').innerHTML);
|
var oauth2Config = JSON.parse(document.getElementById('oauth2-config').innerHTML);
|
||||||
console.log('oauth2Config', oauth2Config);
|
console.log('oauth2Config', oauth2Config);
|
||||||
|
window.ui = SwaggerUIBundle(swaggerUiConfig);
|
||||||
window.ui.initOAuth(oauth2Config);
|
window.ui.initOAuth(oauth2Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = function () {
|
function preauthorizeAny(savedAuth, sui) {
|
||||||
initSwaggerUi();
|
var schemeName = savedAuth.get("name"), schemeType = savedAuth.getIn(["schema", "type"]);
|
||||||
};
|
if (schemeType === "basic" && schemeName) {
|
||||||
|
var username = savedAuth.getIn(["value", "username"]);
|
||||||
|
var password = savedAuth.getIn(["value", "password"]);
|
||||||
|
if (username && password) {
|
||||||
|
sui.preauthorizeBasic(schemeName, username, password);
|
||||||
|
}
|
||||||
|
} else if (schemeType === "apiKey" && schemeName) {
|
||||||
|
var key = savedAuth.get("value");
|
||||||
|
if (key) {
|
||||||
|
sui.preauthorizeApiKey(schemeName, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (document.querySelector('.auth-wrapper .authorize')) {
|
function applyAuth(savedAuth, requestHeaders) {
|
||||||
patchSwaggerUi();
|
var schemeName = savedAuth.get("name"), schemeType = savedAuth.getIn(["schema", "type"]);
|
||||||
|
if (schemeType === "basic" && schemeName) {
|
||||||
|
var username = savedAuth.getIn(["value", "username"]);
|
||||||
|
var password = savedAuth.getIn(["value", "password"]);
|
||||||
|
if (username && password) {
|
||||||
|
requestHeaders["Authorization"] = "Basic " + btoa(username + ":" + password);
|
||||||
|
}
|
||||||
|
} else if (schemeType === "apiKey" && schemeName) {
|
||||||
|
var key = savedAuth.get("value"), _in = savedAuth.getIn(["schema", "in"]);
|
||||||
|
var paramName = savedAuth.getIn(["schema", "name"]);
|
||||||
|
if (key && paramName && _in === "header") {
|
||||||
|
requestHeaders[paramName] = key;
|
||||||
|
}
|
||||||
|
if (_in === "query") {
|
||||||
|
console.warn("WARNING: cannot apply apiKey query parameter via interceptor");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
insertionQ('.auth-wrapper .authorize').every(patchSwaggerUi);
|
function hookAuthActions(sui) {
|
||||||
|
var originalAuthorize = sui.authActions.authorize;
|
||||||
|
sui.authActions.authorize = function (authorization) {
|
||||||
|
originalAuthorize(authorization);
|
||||||
|
// authorization is map of scheme name to scheme object
|
||||||
|
// need to use ImmutableJS because schema is already an ImmutableJS object
|
||||||
|
var schemes = Immutable.fromJS(authorization);
|
||||||
|
var auth = schemes.valueSeq().first();
|
||||||
|
localStorage.setItem("drf-yasg-auth", JSON.stringify(auth.toJSON()));
|
||||||
|
savedAuth = auth;
|
||||||
|
sui.specActions.download();
|
||||||
|
};
|
||||||
|
|
||||||
|
var originalLogout = sui.authActions.logout;
|
||||||
|
sui.authActions.logout = function (authorization) {
|
||||||
|
if (savedAuth.get("name") === authorization[0]) {
|
||||||
|
localStorage.removeItem("drf-yasg-auth");
|
||||||
|
savedAuth = Immutable.fromJS({});
|
||||||
|
}
|
||||||
|
originalLogout(authorization);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
initSwaggerUi();
|
||||||
|
|
||||||
|
if (document.querySelector('.auth-wrapper .authorize')) {
|
||||||
|
patchSwaggerUi();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
insertionQ('.auth-wrapper .authorize').every(patchSwaggerUi);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
<script src="{% static 'drf-yasg/swagger-ui-dist/swagger-ui-bundle.js' %}"></script>
|
<script src="{% static 'drf-yasg/swagger-ui-dist/swagger-ui-bundle.js' %}"></script>
|
||||||
<script src="{% static 'drf-yasg/swagger-ui-dist/swagger-ui-standalone-preset.js' %}"></script>
|
<script src="{% static 'drf-yasg/swagger-ui-dist/swagger-ui-standalone-preset.js' %}"></script>
|
||||||
<script src="{% static 'drf-yasg/insQ.min.js' %}"></script>
|
<script src="{% static 'drf-yasg/insQ.min.js' %}"></script>
|
||||||
|
<script src="{% static 'drf-yasg/immutable.js' %}"></script>
|
||||||
<script src="{% static 'drf-yasg/swagger-ui-init.js' %}"></script>
|
<script src="{% static 'drf-yasg/swagger-ui-init.js' %}"></script>
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{# -- Add any additional scripts here -- #}
|
{# -- Add any additional scripts here -- #}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ ROOT_URLCONF = 'testproj.urls'
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [],
|
'DIRS': [os.path.join(BASE_DIR, 'testproj', 'templates')],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
|
|
@ -132,6 +132,9 @@ USE_TZ = True
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
os.path.join(BASE_DIR, 'testproj', 'static'),
|
||||||
|
]
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ wget https://rebilly.github.io/ReDoc/releases/v1.x.x/redoc.min.js -O src/drf_yas
|
||||||
|
|
||||||
cp -r node_modules/swagger-ui-dist src/drf_yasg/static/drf-yasg/
|
cp -r node_modules/swagger-ui-dist src/drf_yasg/static/drf-yasg/
|
||||||
pushd src/drf_yasg/static/drf-yasg/swagger-ui-dist/ >/dev/null
|
pushd src/drf_yasg/static/drf-yasg/swagger-ui-dist/ >/dev/null
|
||||||
|
rm -f swagger-ui.js
|
||||||
rm -f package.json .npmignore README.md
|
rm -f package.json .npmignore README.md
|
||||||
rm -f index.html *.map
|
rm -f index.html *.map
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue