mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-05 04:50:12 +03:00
Docs Authentication (#4926)
* Authentication token modal & licenses * `none` menu item & Fix clear response * Pass authorisation header to coreapi client * Session Authentication * Fix bug with data/raw response both being displayed * Bump coreapi & remove it from static files * Default to session authentication if logged in * Basic Authentication & Favicon * Rename token to header authentication
This commit is contained in:
parent
e6018bbbc3
commit
1ed82aa104
22
licenses/bootstrap.md
Normal file
22
licenses/bootstrap.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
https://github.com/twbs/bootstrap/
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2016 Twitter, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
licenses/jquery.json-view.md
Normal file
22
licenses/jquery.json-view.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
https://github.com/bazh/jquery.json-view/
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 bazh. (http://github.com/bazh)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -801,7 +801,7 @@ class DocumentationRenderer(BaseRenderer):
|
|||
template = 'rest_framework/docs/index.html'
|
||||
code_style = 'emacs'
|
||||
|
||||
def get_context(self, data):
|
||||
def get_context(self, data, request):
|
||||
from pygments.formatters import HtmlFormatter
|
||||
from django.utils.html import mark_safe
|
||||
formatter = HtmlFormatter(style=self.code_style)
|
||||
|
@ -813,12 +813,13 @@ class DocumentationRenderer(BaseRenderer):
|
|||
'document': data,
|
||||
'langs': langs,
|
||||
'code_style': code_style,
|
||||
'schema': schema
|
||||
'schema': schema,
|
||||
'request': request
|
||||
}
|
||||
|
||||
def render(self, data, accepted_media_type=None, renderer_context=None):
|
||||
template = loader.get_template(self.template)
|
||||
context = self.get_context(data)
|
||||
context = self.get_context(data, renderer_context['request'])
|
||||
return template_render(template, context, request=renderer_context['request'])
|
||||
|
||||
|
||||
|
|
|
@ -57,13 +57,13 @@ def field_to_schema(field):
|
|||
return coreschema.String(title=title, description=description)
|
||||
elif isinstance(field, serializers.MultipleChoiceField):
|
||||
return coreschema.Array(
|
||||
items=coreschema.Enum(enum=list(field.choices.values())),
|
||||
items=coreschema.Enum(enum=list(field.choices.keys())),
|
||||
title=title,
|
||||
description=description
|
||||
)
|
||||
elif isinstance(field, serializers.ChoiceField):
|
||||
return coreschema.Enum(
|
||||
enum=list(field.choices.values()),
|
||||
enum=list(field.choices.keys()),
|
||||
title=title,
|
||||
description=description
|
||||
)
|
||||
|
|
|
@ -30,30 +30,28 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sidebar .brand a {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.sidebar .brand a:hover,
|
||||
.sidebar .brand a:active,
|
||||
.sidebar .brand a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar .toggle-btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar .menu-list ul,
|
||||
.sidebar .menu-list li {
|
||||
background: #2e353d;
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
line-height: 35px;
|
||||
cursor: pointer;
|
||||
/*
|
||||
.collapsed{
|
||||
.arrow:before{
|
||||
font-family: FontAwesome;
|
||||
content: "\f053";
|
||||
display: inline-block;
|
||||
padding-left:10px;
|
||||
padding-right: 10px;
|
||||
vertical-align: middle;
|
||||
float:right;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
.sidebar .menu-list ul :not(collapsed) .arrow:before,
|
||||
|
@ -97,8 +95,14 @@
|
|||
background-color: #020203;
|
||||
}
|
||||
|
||||
.sidebar .menu-list ul .sub-menu li:before,
|
||||
.sidebar .menu-list li .sub-menu li:before {
|
||||
|
||||
.sidebar .menu-list ul .sub-menu li a,
|
||||
.sidebar .menu-list li .sub-menu li a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar .menu-list ul .sub-menu li a:before,
|
||||
.sidebar .menu-list li .sub-menu li a:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f105";
|
||||
display: inline-block;
|
||||
|
@ -273,8 +277,9 @@ body {
|
|||
}
|
||||
|
||||
.api-modal .modal-body .request-awaiting {
|
||||
text-align: center;
|
||||
padding: 35px 10px;
|
||||
color: #7F8177;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.api-modal .modal-body .meta {
|
||||
|
|
11
rest_framework/static/rest_framework/docs/css/jquery.json-view.min.css
vendored
Executable file
11
rest_framework/static/rest_framework/docs/css/jquery.json-view.min.css
vendored
Executable file
|
@ -0,0 +1,11 @@
|
|||
.json-view{position:relative}
|
||||
.json-view .collapser{width:20px;height:18px;display:block;position:absolute;left:-1.7em;top:-.2em;z-index:5;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYGBgOADE%2F3Hgw0DM4IRHgSsDFOzFInmMAQnY49ONzZRjDFiADT7dMLALiE8y4AGW6LoBAgwAuIkf%2F%2FB7O9sAAAAASUVORK5CYII%3D);background-repeat:no-repeat;background-position:center center;opacity:.5;cursor:pointer}
|
||||
.json-view .collapsed{-ms-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-khtml-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}
|
||||
.json-view .bl{display:block;padding-left:20px;margin-left:-20px;position:relative}
|
||||
.json-view{font-family:monospace}
|
||||
.json-view ul{list-style-type:none;padding-left:2em;border-left:1px dotted;margin:.3em}
|
||||
.json-view ul li{position:relative}
|
||||
.json-view .comments,.json-view .dots{display:none;-moz-user-select:none;-ms-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}
|
||||
.json-view .comments{padding-left:.8em;font-style:italic;color:#888}
|
||||
.json-view .bool,.json-view .null,.json-view .num,.json-view .undef{font-weight:700;color:#1A01CC}
|
||||
.json-view .str{color:#800}
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 5.3 KiB |
7
rest_framework/static/rest_framework/docs/js/jquery.json-view.min.js
vendored
Executable file
7
rest_framework/static/rest_framework/docs/js/jquery.json-view.min.js
vendored
Executable file
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* jquery.json-view - jQuery collapsible JSON plugin
|
||||
* @version v1.0.0
|
||||
* @link http://github.com/bazh/jquery.json-view
|
||||
* @license MIT
|
||||
*/
|
||||
!function(e){"use strict";var n=function(n){var a=e("<span />",{"class":"collapser",on:{click:function(){var n=e(this);n.toggleClass("collapsed");var a=n.parent().children(".block"),p=a.children("ul");n.hasClass("collapsed")?(p.hide(),a.children(".dots, .comments").show()):(p.show(),a.children(".dots, .comments").hide())}}});return n&&a.addClass("collapsed"),a},a=function(a,p){var t=e.extend({},{nl2br:!0},p),r=function(e){return e.toString()?e.toString().replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">"):""},s=function(n,a){return e("<span />",{"class":a,html:r(n)})},l=function(a,p){switch(e.type(a)){case"object":p||(p=0);var c=e("<span />",{"class":"block"}),d=Object.keys(a).length;if(!d)return c.append(s("{","b")).append(" ").append(s("}","b"));c.append(s("{","b"));var i=e("<ul />",{"class":"obj collapsible level"+p});return e.each(a,function(a,t){d--;var r=e("<li />").append(s('"',"q")).append(a).append(s('"',"q")).append(": ").append(l(t,p+1));-1===["object","array"].indexOf(e.type(t))||e.isEmptyObject(t)||r.prepend(n()),d>0&&r.append(","),i.append(r)}),c.append(i),c.append(s("...","dots")),c.append(s("}","b")),c.append(1===Object.keys(a).length?s("// 1 item","comments"):s("// "+Object.keys(a).length+" items","comments")),c;case"array":p||(p=0);var d=a.length,c=e("<span />",{"class":"block"});if(!d)return c.append(s("[","b")).append(" ").append(s("]","b"));c.append(s("[","b"));var i=e("<ul />",{"class":"obj collapsible level"+p});return e.each(a,function(a,t){d--;var r=e("<li />").append(l(t,p+1));-1===["object","array"].indexOf(e.type(t))||e.isEmptyObject(t)||r.prepend(n()),d>0&&r.append(","),i.append(r)}),c.append(i),c.append(s("...","dots")),c.append(s("]","b")),c.append(1===a.length?s("// 1 item","comments"):s("// "+a.length+" items","comments")),c;case"string":if(a=r(a),/^(http|https|file):\/\/[^\s]+$/i.test(a))return e("<span />").append(s('"',"q")).append(e("<a />",{href:a,text:a})).append(s('"',"q"));if(t.nl2br){var o=/\n/g;o.test(a)&&(a=(a+"").replace(o,"<br />"))}var u=e("<span />",{"class":"str"}).html(a);return e("<span />").append(s('"',"q")).append(u).append(s('"',"q"));case"number":return s(a.toString(),"num");case"undefined":return s("undefined","undef");case"null":return s("null","null");case"boolean":return s(a?"true":"false","bool")}};return l(a)};return e.fn.jsonView=function(n,p){var t=e(this);if(p=e.extend({},{nl2br:!0},p),"string"==typeof n)try{n=JSON.parse(n)}catch(r){}return t.append(e("<div />",{"class":"json-view"}).append(a(n,p))),t}}(jQuery);
|
38
rest_framework/templates/rest_framework/docs/auth/basic.html
Normal file
38
rest_framework/templates/rest_framework/docs/auth/basic.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{% load rest_framework %}
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade auth-modal auth-basic" id="auth_basic_modal" tabindex="-1" role="dialog" aria-labelledby="basic authentication modal">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="fa fa-key"></i> Basic Authentication</h3>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal authentication-basic-form">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="authorization" class="col-sm-2 control-label">Username:</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="username" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="authorization" class="col-sm-2 control-label">Password:</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Use Basic Authentication</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,35 @@
|
|||
{% load rest_framework %}
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade auth-modal auth-session" id="auth_session_modal" tabindex="-1" role="dialog" aria-labelledby="session authentication modal">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="fa fa-key"></i> Session Authentication</h3>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal authentication-session-form">
|
||||
<div class="modal-body">
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<h4 class="text-center">You are logged in as {{ user.username }}.</h4>
|
||||
{% else %}
|
||||
|
||||
<div class="text-center">
|
||||
<h4 class="text-center">You need to {% optional_docs_login request %} to enable Session Authentication.</h4>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
{% if user.is_authenticated %}
|
||||
<button type="submit" class="btn btn-primary">Use Session Authentication</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
31
rest_framework/templates/rest_framework/docs/auth/token.html
Normal file
31
rest_framework/templates/rest_framework/docs/auth/token.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% load rest_framework %}
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade auth-modal auth-token" id="auth_token_modal" tabindex="-1" role="dialog" aria-labelledby="token authentication modal">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="fa fa-key"></i> Authentication Header</h3>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal authentication-token-form">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="authorization" class="col-sm-2 control-label">Authorization:</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="authorization" placeholder="Bearer XXXX-XXXX-XXXX-XXXX" aria-describedby="helpBlock" required>
|
||||
<span id="helpBlock" class="help-block">The value to include for the <code>Authorization</code> header in outgoing HTTP requests.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Use Authentication Header</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -12,6 +12,10 @@
|
|||
<link href="{% static 'rest_framework/docs/css/bootstrap-theme.min.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'rest_framework/docs/css/font-awesome-4.0.3.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'rest_framework/docs/css/base.css' %}" rel="stylesheet">
|
||||
<link href="{% static 'rest_framework/docs/css/jquery.json-view.min.css' %}" rel="stylesheet">
|
||||
|
||||
<link href="{% static 'rest_framework/docs/img/favicon.ico' %}" rel="shortcut icon">
|
||||
|
||||
<style>{{ code_style }}</style>
|
||||
<style>
|
||||
.highlight {background-color: #f7f7f9}
|
||||
|
@ -22,7 +26,7 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
<script src="https://unpkg.com/coreapi@0.0.19/dist/coreapi.js"></script>
|
||||
<script src="https://unpkg.com/coreapi@0.0.20/dist/coreapi.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
|
@ -38,8 +42,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% include "rest_framework/docs/auth/token.html" %}
|
||||
{% include "rest_framework/docs/auth/basic.html" %}
|
||||
{% include "rest_framework/docs/auth/session.html" %}
|
||||
|
||||
<script src="{% static 'rest_framework/docs/js/jquery-1.10.2.min.js' %}"></script>
|
||||
<script src="{% static 'rest_framework/docs/js/bootstrap.min.js' %}"></script>
|
||||
<script src="{% static 'rest_framework/docs/js/jquery.json-view.min.js' %}"></script>
|
||||
<script>
|
||||
function normalizeHTTPHeader(str) {
|
||||
return (str.charAt(0).toUpperCase() + str.substring(1))
|
||||
|
@ -64,13 +73,22 @@
|
|||
}
|
||||
return cookieValue;
|
||||
}
|
||||
const csrf = {'X-CSRFToken': getCookie('csrftoken')}
|
||||
|
||||
let responseDisplay = 'data';
|
||||
const coreapi = window.coreapi
|
||||
const codec = new coreapi.codecs.CoreJSONCodec()
|
||||
const schema = {{ schema }}
|
||||
const doc = codec.decode(schema)
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
window.auth = {
|
||||
'type': 'session',
|
||||
};
|
||||
$('#selected-authentication').text('session');
|
||||
$('#auth-control').children().removeClass('active');
|
||||
$('#auth-control').find("[data-auth='session']").addClass('active');
|
||||
{% endif %}
|
||||
|
||||
// Language Control
|
||||
$('#language-control li').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
@ -89,8 +107,7 @@
|
|||
})
|
||||
|
||||
// API Explorer
|
||||
|
||||
$('form').submit(function(event) {
|
||||
$('form.api-interaction').submit(function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = $(this).closest("form");
|
||||
|
@ -170,25 +187,63 @@
|
|||
form.find(".response-raw-response").text(panelText)
|
||||
}
|
||||
|
||||
const client = new coreapi.Client({csrf: csrf, requestCallback: requestCallback, responseCallback: responseCallback})
|
||||
let options = {
|
||||
requestCallback: requestCallback,
|
||||
responseCallback: responseCallback,
|
||||
}
|
||||
|
||||
if (window.auth && window.auth.type === 'token') {
|
||||
options.headers = {
|
||||
'Authorization': window.auth.value
|
||||
}
|
||||
} else if (window.auth && window.auth.type === 'basic') {
|
||||
const token = window.auth.username + ':' + window.auth.password
|
||||
const hash = window.btoa(token)
|
||||
options.headers = {
|
||||
'Authorization': 'Basic ' + hash
|
||||
}
|
||||
} else if (window.auth && window.auth.type === 'session') {
|
||||
options.csrf = {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const client = new coreapi.Client(options)
|
||||
|
||||
client.action(doc, key, params).then(function (data) {
|
||||
var response = JSON.stringify(data, null, 2);
|
||||
form.find(".request-awaiting").addClass("hide")
|
||||
form.find(".response-data").text(response)
|
||||
form.find(".response-data").removeClass("hide")
|
||||
form.find(".response-raw").addClass("hide")
|
||||
form.find(".response-data").addClass("hide")
|
||||
form.find(".response-data").text('')
|
||||
form.find(".response-data").jsonView(response)
|
||||
|
||||
if (responseDisplay === 'data') {
|
||||
form.find(".response-data").removeClass("hide")
|
||||
} else {
|
||||
form.find(".response-raw").removeClass("hide")
|
||||
}
|
||||
}).catch(function (error) {
|
||||
var response = JSON.stringify(error.content, null, 2);
|
||||
form.find(".request-awaiting").addClass("hide")
|
||||
form.find(".response-data").text(response)
|
||||
form.find(".response-data").removeClass("hide")
|
||||
form.find(".response-raw").addClass("hide")
|
||||
form.find(".response-data").addClass("hide")
|
||||
form.find(".response-data").text('')
|
||||
form.find(".response-data").jsonView(response)
|
||||
|
||||
if (responseDisplay === 'data') {
|
||||
form.find(".response-data").removeClass("hide")
|
||||
} else {
|
||||
form.find(".response-raw").removeClass("hide")
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$('.toggle-view button').click(function() {
|
||||
var selectedView = $(this).data("display-toggle");
|
||||
responseDisplay = $(this).data("display-toggle");
|
||||
$(this).removeClass("btn-default").addClass('btn-info').siblings().removeClass('btn-info');
|
||||
if (selectedView === 'raw') {
|
||||
if (responseDisplay === 'raw') {
|
||||
$(this).closest(".modal-content").find(".response-raw").removeClass("hide");
|
||||
$(this).closest(".modal-content").find(".response-data").addClass("hide");
|
||||
} else {
|
||||
|
@ -196,6 +251,59 @@
|
|||
$(this).closest(".modal-content").find(".response-raw").addClass("hide");
|
||||
}
|
||||
});
|
||||
|
||||
// Authentication: none
|
||||
$('#auth-control').find("[data-auth='none']").click(function (event) {
|
||||
event.preventDefault();
|
||||
window.auth = null;
|
||||
$('#selected-authentication').text('none');
|
||||
$('#auth-control').children().removeClass('active');
|
||||
$('#auth-control').find("[data-auth='none']").addClass('active');
|
||||
})
|
||||
|
||||
// Authentication: token
|
||||
$('form.authentication-token-form').submit(function(event) {
|
||||
event.preventDefault();
|
||||
const form = $(this).closest("form");
|
||||
const value = form.find('input').val();
|
||||
window.auth = {
|
||||
'type': 'token',
|
||||
'value': value,
|
||||
};
|
||||
$('#selected-authentication').text('header');
|
||||
$('#auth-control').children().removeClass('active');
|
||||
$('#auth-control').find("[data-auth='token']").addClass('active');
|
||||
$('#auth_token_modal').modal('hide');
|
||||
});
|
||||
|
||||
// Authentication: basic
|
||||
$('form.authentication-basic-form').submit(function(event) {
|
||||
event.preventDefault();
|
||||
const form = $(this).closest("form");
|
||||
const username = form.find('input#username').val();
|
||||
const password = form.find('input#password').val();
|
||||
window.auth = {
|
||||
'type': 'basic',
|
||||
'username': username,
|
||||
'password': password,
|
||||
};
|
||||
$('#selected-authentication').text('basic');
|
||||
$('#auth-control').children().removeClass('active');
|
||||
$('#auth-control').find("[data-auth='basic']").addClass('active');
|
||||
$('#auth_basic_modal').modal('hide');
|
||||
});
|
||||
|
||||
// Authentication: session
|
||||
$('form.authentication-session-form').submit(function(event) {
|
||||
event.preventDefault();
|
||||
window.auth = {
|
||||
'type': 'session',
|
||||
};
|
||||
$('#selected-authentication').text('session');
|
||||
$('#auth-control').children().removeClass('active');
|
||||
$('#auth-control').find("[data-auth='session']").addClass('active');
|
||||
$('#auth_session_modal').modal('hide');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
<form data-key='["{{ section_key }}", "{{ link_key }}"]'>
|
||||
<form data-key='["{{ section_key }}", "{{ link_key }}"]' class="api-interaction">
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 request">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="sidebar">
|
||||
<h3 class="brand">{{ document.title }}</h3>
|
||||
<h3 class="brand"><a href=".">{{ document.title }}</a></h3>
|
||||
|
||||
<i class="fa fa-bars fa-2x toggle-btn" data-toggle="collapse" data-target="#menu-content"></i>
|
||||
<div class="menu-list">
|
||||
|
@ -8,7 +8,7 @@
|
|||
<li data-toggle="collapse" data-target="#{{ section_key }}-dropdown" class="collapsed">
|
||||
<a><i class="fa fa-dot-circle-o fa-lg"></i> {{ section_key }} <span class="arrow"></span></a>
|
||||
</li>
|
||||
<ul class="sub-menu collapse in" id="{{ section_key }}-dropdown">
|
||||
<ul class="sub-menu collapse" id="{{ section_key }}-dropdown">
|
||||
{% for link_key, link in section.links.items %}
|
||||
<li><a href="#{{ section_key }}-{{ link_key }}">{{ link.title|default:link_key }}</a></li>
|
||||
{% endfor %}
|
||||
|
@ -17,9 +17,16 @@
|
|||
</ul>
|
||||
|
||||
<ul class="menu-list menu-list-bottom">
|
||||
<li>
|
||||
<a><i class="fa fa-user fa-lg"></i> Authentication</a> <span>none</span>
|
||||
<li data-toggle="collapse" data-target="#auth-control" class="collapsed">
|
||||
<a><i class="fa fa-user fa-lg"></i> Authentication</a> <span id="selected-authentication">{% if user.is_authenticated %}session{% else %}none{% endif %}</span>
|
||||
</li>
|
||||
<ul class="sub-menu collapse out" id="auth-control">
|
||||
<li data-auth="none" {% if not user.is_authenticated %}class="active"{% endif %}><a href="#" data-language="none">none</a></li>
|
||||
<li data-auth="token" data-toggle="modal" data-target="#auth_token_modal"><a href="#">header</a></li>
|
||||
<li data-auth="basic" data-toggle="modal" data-target="#auth_basic_modal"><a href="#">basic</a></li>
|
||||
<li data-auth="session" data-toggle="modal" data-target="#auth_session_modal" {% if user.is_authenticated %}class="active"{% endif %}><a href="#">session</a></li>
|
||||
</ul>
|
||||
|
||||
<li data-toggle="collapse" data-target="#language-control" class="collapsed">
|
||||
<a><i class="fa fa-code fa-lg"></i> Source Code</a> <span id="selected-language">shell</span>
|
||||
</li>
|
||||
|
|
|
@ -128,6 +128,22 @@ def optional_login(request):
|
|||
return mark_safe(snippet)
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def optional_docs_login(request):
|
||||
"""
|
||||
Include a login snippet if REST framework's login view is in the URLconf.
|
||||
"""
|
||||
try:
|
||||
login_url = reverse('rest_framework:login')
|
||||
except NoReverseMatch:
|
||||
return 'log in'
|
||||
|
||||
snippet = "<a href='{href}?next={next}'>log in</a>"
|
||||
snippet = format_html(snippet, href=login_url, next=escape(request.path))
|
||||
|
||||
return mark_safe(snippet)
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def optional_logout(request, user):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user