Merge branch 'master' into Minasokoni-container-name-change

This commit is contained in:
Kyle Shockey
2017-04-27 19:57:29 -07:00
18 changed files with 218 additions and 183 deletions

3
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,3 @@
When reporting an issue, please provide the following details:
- swagger-ui version
- a swagger file reproducing the issue

View File

@@ -75,7 +75,7 @@ To use swagger-ui's bundles, you should take a look at the [source of swagger-ui
})
```
If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` package](npmjs.com/package/swagger-ui-dist).
If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` package](https://www.npmjs.com/package/swagger-ui-dist).
#### Parameters
@@ -86,6 +86,7 @@ spec | A JSON object describing the OpenAPI Specification. When used, the `url`
validatorUrl | By default, Swagger-UI attempts to validate specs against swagger.io's online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators ([Validator Badge](https://github.com/swagger-api/validator-badge)). Setting it to `null` will disable validation.
dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger.
oauth2RedirectUrl | OAuth redirect URL
operationsSorter | Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged.

View File

@@ -33,51 +33,19 @@
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
createForm(oauth2.auth, qp).submit();
oauth2.callback(oauth2.auth);
} else {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: "Authorization failed: no accessCode came from the server"
message: "Authorization failed: no accessCode received from the server"
});
window.close();
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid});
window.close();
}
}
function createForm(auth, qp) {
var form = document.createElement("form");
var schema = auth.schema;
var action = schema.get("tokenUrl");
var name, input;
var fields = {
code: qp.code,
"redirect_uri": location.protocol + "//" + location.host + location.pathname,
"grant_type": "authorization_code",
"client_secret": auth.clientSecret,
"client_id": auth.clientId
}
for ( name in fields ) {
input = document.createElement("input");
input.name = name;
input.value = fields[name];
input.type = "hidden";
form.appendChild(input);
}
form.method = "POST";
form.action = action;
document.body.appendChild(form);
return form;
window.close();
}
</script>

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA++FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAgeA;;;;;;AAoIA;AAk7FA;AAmtCA;;;;;AA0uIA;AA+4IA;AAm9FA;AA2rGA;AA8lFA;AA2nFA;AAu9CA;AAyhDA;AAqrCA;AAy4EA;AA8/GA;;;;;;;;;;;;;;AA+mJA;AA4mIA;AAquJA;AAwsHA;AA2mGA;AAiiEA;AAq4DA;AA+2DA;AA4lBA;;;;;;AA0kFA;AAk0FA;;;;;AA23CA;AA2qFA;AAw2CA;AAglCA;AA0/CA;AAykFA;AA+1FA;;;;;;;;;AAk4CA;AA2zIA;AAk4DA;AAolDA","sourceRoot":""}
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA++FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAgeA;;;;;;AAoIA;AAk7FA;AAmtCA;;;;;AA0uIA;AAg2IA;AA64FA;AAiyGA;AA2mFA;AA4nFA;AA+9CA;AA+gDA;AAwrCA;AA60EA;AA66HA;;;;;;;;;;;;;;AA0wIA;AA4mIA;AAquJA;AAwsHA;AA2mGA;AAiiEA;AAq4DA;AA+2DA;AA4lBA;;;;;;AA0kFA;AA80FA;;;;;AAy3CA;AA2qFA;AAw2CA;AAwkCA;AAs/CA;AA4kFA;AAy1FA;;;;;;;;;AAm5CA;AA2zIA;AAk4DA;AAolDA","sourceRoot":""}

File diff suppressed because one or more lines are too long

2
dist/swagger-ui.css vendored

File diff suppressed because one or more lines are too long

18
dist/swagger-ui.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA4wCA;AAoyHA;AAuxHA;AAy4FA;AA8rCA;AAugCA;AA+hCA;AA24BA","sourceRoot":""}
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0xCA;AAoyHA;AAuxHA;AAy4FA;AAmsCA;AAmgCA;AA0iCA;AA+3BA","sourceRoot":""}

View File

@@ -36,10 +36,12 @@
},
"dependencies": {
"babel-polyfill": "^6.23.0",
"base64-js": "^1.2.0",
"brace": "0.7.0",
"deep-extend": "0.4.1",
"expect": "1.20.2",
"getbase": "^2.8.2",
"ieee754": "^1.1.8",
"immutable": "^3.x.x",
"js-yaml": "^3.5.5",
"less": "2.7.1",

28
snapcraft.yaml Normal file
View File

@@ -0,0 +1,28 @@
name: swagger-ui
version: master
summary: The World's Most Popular API Framework
description: |
Swagger UI is part of the Swagger project. The Swagger project allows you to
produce, visualize and consume your OWN RESTful services. No proxy or 3rd
party services required. Do it your own way.
Swagger UI is a dependency-free collection of HTML, Javascript, and CSS
assets that dynamically generate beautiful documentation and sandbox from a
Swagger-compliant API. Because Swagger UI has no dependencies, you can host
it in any server environment, or on your local machine.
grade: devel
confinement: strict
apps:
swagger-ui:
command: sh -c \"cd $SNAP/lib/node_modules/swagger-ui/dist && http-server -a localhost -p 8080\"
daemon: simple
plugs: [network, network-bind]
parts:
swagger-ui:
source: .
plugin: nodejs
npm-run: [build]
node-packages: [handlebars, http-server]

View File

@@ -26,7 +26,7 @@ export default class Oauth2 extends React.Component {
let username = auth && auth.get("username") || ""
let clientId = auth && auth.get("clientId") || ""
let clientSecret = auth && auth.get("clientSecret") || ""
let passwordType = auth && auth.get("passwordType") || "none"
let passwordType = auth && auth.get("passwordType") || "basic"
this.state = {
name: name,
@@ -108,44 +108,46 @@ export default class Oauth2 extends React.Component {
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
{
flow === PASSWORD && ( !isAuthorized || isAuthorized && this.state.username) && <Row>
<Col tablet={2} desktop={2}>username:</Col>
<Col tablet={10} desktop={10}>
flow !== PASSWORD ? null
: <Row>
<Row>
<label htmlFor="oauth_username">username:</label>
{
isAuthorized ? <code> { this.state.username } </code>
: <Col tablet={10} desktop={10}>
<input id="oauth_username" type="text" data-name="username" onChange={ this.onInputChange }/>
</Col>
}
</Row>
{
isAuthorized ? <span>{ this.state.username }</span>
: <input type="text" data-name="username" onChange={ this.onInputChange }/>
}
</Col>
</Row>
<Row>
<label htmlFor="oauth_password">password:</label>
{
isAuthorized ? <code> ****** </code>
: <Col tablet={10} desktop={10}>
<input id="oauth_password" type="password" data-name="password" onChange={ this.onInputChange }/>
</Col>
}
</Row>
<Row>
<label htmlFor="password_type">type:</label>
{
isAuthorized ? <code> { this.state.passwordType } </code>
: <Col tablet={10} desktop={10}>
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }>
<option value="basic">Basic auth</option>
<option value="request-body">Request body</option>
<option value="query">Query parameters</option>
</select>
</Col>
}
</Row>
</Row>
}
{
flow === PASSWORD && !isAuthorized && <Row>
<Col tablet={2} desktop={2}>password:</Col>
<Col tablet={10} desktop={10}>
<input type="password" data-name="password" onChange={ this.onInputChange }/>
</Col>
</Row>
}
{
flow === PASSWORD && <Row>
<Col tablet={2} desktop={2}>type:</Col>
<Col tablet={10} desktop={10}>
{
isAuthorized ? <span>{ this.state.passwordType }</span>
: <select data-name="passwordType" onChange={ this.onInputChange }>
<option value="none">None or other</option>
<option value="basic">Basic auth</option>
<option value="request">Request body</option>
</select>
}
</Col>
</Row>
}
{
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) &&
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) &&
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
<label htmlFor="client_id">client_id:</label>
{
@@ -159,7 +161,7 @@ export default class Oauth2 extends React.Component {
}
{
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) && <Row>
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row>
<label htmlFor="client_secret">client_secret:</label>
{
isAuthorized ? <code> ****** </code>

View File

@@ -16,7 +16,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
}
if (flow === "application") {
authActions.authorizeOauth2Application(auth)
authActions.authorizeApplication(auth)
return
}
@@ -45,7 +45,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
win.swaggerUIRedirectOauth2 = {
auth: auth,
state: state,
callback: authActions.preAuthorizeOauth2,
callback: flow === "implicit" ? authActions.preAuthorizeImplicit : authActions.authorizeAccessCode,
errCb: errActions.newAuthErr
}

View File

@@ -1,5 +1,5 @@
import win from "core/window"
import { btoa } from "core/utils"
import { btoa, buildFormData } from "core/utils"
export const SHOW_AUTH_POPUP = "show_popup"
export const AUTHORIZE = "authorize"
@@ -31,7 +31,7 @@ export function logout(payload) {
}
}
export const preAuthorizeOauth2 = (payload) => ( { authActions, errActions } ) => {
export const preAuthorizeImplicit = (payload) => ( { authActions, errActions } ) => {
let { auth , token, isValid } = payload
let { schema, name } = auth
let flow = schema.get("flow")
@@ -68,29 +68,71 @@ export function authorizeOauth2(payload) {
}
}
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
export const authorizePassword = ( auth ) => ( { authActions } ) => {
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
let req = {
url: schema.get("tokenUrl"),
method: "post",
headers: {
"content-type": "application/x-www-form-urlencoded"
},
query: {
grant_type: "password",
username,
password,
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
let form = {
grant_type: "password",
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
}
let query = {}
let headers = {}
if ( passwordType === "basic") {
headers.Authorization = "Basic " + btoa(username + ":" + password)
} else {
Object.assign(form, {username}, {password})
if ( passwordType === "query") {
if ( clientId ) { query.client_id = clientId }
if ( clientSecret ) { query.client_secret = clientSecret }
} else {
Object.assign(form, {client_id: clientId}, {client_secret: clientSecret})
}
}
if ( passwordType === "basic") {
req.headers.authorization = "Basic " + btoa(clientId + ":" + clientSecret)
} else if ( passwordType === "request") {
req.query = Object.assign(req.query, { client_id: clientId, client_secret: clientSecret })
return authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth})
}
export const authorizeApplication = ( auth ) => ( { authActions } ) => {
let { schema, scopes, name, clientId, clientSecret } = auth
let form = {
grant_type: "client_credentials",
client_id: clientId,
client_secret: clientSecret,
scope: scopes.join(scopeSeparator)
}
return fn.fetch(req)
.then(( response ) => {
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth })
}
export const authorizeAccessCode = ( auth ) => ( { authActions } ) => {
let { schema, name, clientId, clientSecret } = auth
let form = {
grant_type: "authorization_code",
code: auth.code,
client_id: clientId,
client_secret: clientSecret
}
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth})
}
export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) => {
let { body, query={}, headers={}, name, url, auth } = data
let _headers = Object.assign({
"Accept":"application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded"
}, headers)
fn.fetch({
url: url,
method: "post",
headers: _headers,
query: query,
body: body
})
.then(function (response) {
let token = JSON.parse(response.data)
let error = token && ( token.error || "" )
let parseError = token && ( token.parseError || "" )
@@ -115,39 +157,7 @@ export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } )
return
}
authActions.authorizeOauth2({ auth, token })
authActions.authorizeOauth2({ auth, token})
})
.catch(err => { errActions.newAuthErr( err ) })
}
export const authorizeOauth2Application = ( auth ) => ( { fn, authActions, errActions } ) => {
let { schema, scopes, name, clientId, clientSecret } = auth
fn.fetch(schema.get("tokenUrl"), {
method: "post", headers: {
"Accept":"application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded"
},
body: "grant_type=client_credentials" +
"&client_id=" + encodeURIComponent(clientId) +
"&client_secret=" + encodeURIComponent(clientSecret) +
"&scope=" + encodeURIComponent(scopes.join(scopeSeparator))
})
.then(function (response) {
if ( !response.ok ) {
errActions.newAuthErr( {
authId: name,
level: "error",
source: "auth",
message: response.statusText
} )
return
} else {
response.json()
.then(function (json){
authActions.authorizeOauth2({ auth, token: json})
})
}
})
.catch(err => { errActions.newAuthErr( err ) })
}

View File

@@ -566,3 +566,15 @@ export const sorters = {
method: (a, b) => a.get("method").localeCompare(b.get("method"))
}
}
export const buildFormData = (data) => {
let formArr = []
for (let name in data) {
let val = data[name]
if (val !== undefined && val !== "") {
formArr.push([name, "=", encodeURIComponent(val).replace(/%20/g,"+")].join(""))
}
}
return formArr.join("&")
}

View File

@@ -502,6 +502,11 @@ body
{
color: #fff !important;
}
.headerline
{
display: block;
}
}
.scheme-container

View File

@@ -1,3 +1,3 @@
This directory is used to build the `swagger-ui-dist` npm package.
This module, `swagger-ui-dist`, exposes Swagger-UI's entire dist folder as a dependency-free npm module.
For anything else, check the [Swagger-UI](https://github.com/swagger-api/swagger-ui) repository.
Use `swagger-ui` instead, if you'd like to have npm install dependencies for you.

View File

@@ -22,7 +22,11 @@ module.exports = require('./make-webpack-config.js')({
},
externals: function(context, request, cb) {
if(node_modules.indexOf(request) !== -1) {
// webpack injects some stuff into the resulting file,
// these libs need to be pulled in to keep that working.
var exceptionsForWebpack = ["ieee754", "base64-js"]
if(node_modules.indexOf(request) !== -1 || exceptionsForWebpack.indexOf(request) !== -1) {
console.log(request)
cb(null, 'commonjs ' + request)
return;
}