Merge branch 'master' into ft/react_15_6_2
This commit is contained in:
3
.github/issue_template.md
vendored
3
.github/issue_template.md
vendored
@@ -1,6 +1,9 @@
|
||||
<!---
|
||||
Thanks for filing an issue 😄 ! Before you submit, please read the following:
|
||||
|
||||
If you're here to report a security issue, please STOP writing an issue and contact us
|
||||
at security@swagger.io instead!
|
||||
|
||||
Search open/closed issues before submitting since someone might have asked the same thing before!
|
||||
|
||||
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try to offer support
|
||||
|
||||
42
.github/pull_request_template.md
vendored
Normal file
42
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
|
||||
### Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
|
||||
|
||||
### Motivation and Context
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
<!--- Use the magic "Fixes #1234" format, so the issues are -->
|
||||
<!--- automatically closed when this PR is merged. -->
|
||||
|
||||
|
||||
|
||||
### How Has This Been Tested?
|
||||
<!--- Please describe in detail how you manually tested your changes. -->
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
|
||||
|
||||
|
||||
### Screenshots (if appropriate):
|
||||
|
||||
|
||||
|
||||
### Types of changes
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
- [ ] No code changes (changes to documentation, CI, metadata, etc)
|
||||
- [ ] Dependency changes (any modification to dependencies in `package.json`)
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
### Checklist:
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
- [ ] My code follows the code style of this project.
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20
|
||||
|
||||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
|
||||
------------------ | ------------ | -------------------------- | -----
|
||||
3.4.0 | 2017-10-20 | 2.0, 3.0 | [tag v3.4.0](https://github.com/swagger-api/swagger-ui/tree/v3.4.0)
|
||||
3.4.2 | 2017-10-30 | 2.0, 3.0 | [tag v3.4.2](https://github.com/swagger-api/swagger-ui/tree/v3.4.2)
|
||||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
|
||||
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10)
|
||||
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5)
|
||||
|
||||
26
dist/swagger-ui-bundle.js
vendored
26
dist/swagger-ui-bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-bundle.js.map
vendored
2
dist/swagger-ui-bundle.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-standalone-preset.js
vendored
2
dist/swagger-ui-standalone-preset.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui-standalone-preset.js.map
vendored
2
dist/swagger-ui-standalone-preset.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/swagger-ui.js
vendored
4
dist/swagger-ui.js
vendored
File diff suppressed because one or more lines are too long
2
dist/swagger-ui.js.map
vendored
2
dist/swagger-ui.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -32,7 +32,7 @@ fi
|
||||
|
||||
if [[ -f $SWAGGER_JSON ]]; then
|
||||
cp $SWAGGER_JSON $NGINX_ROOT
|
||||
REL_PATH="/$(basename $SWAGGER_JSON)"
|
||||
REL_PATH="./$(basename $SWAGGER_JSON)"
|
||||
sed -i "s|http://petstore.swagger.io/v2/swagger.json|$REL_PATH|g" $INDEX_FILE
|
||||
sed -i "s|http://example.com/api|$REL_PATH|g" $INDEX_FILE
|
||||
else
|
||||
|
||||
@@ -20,8 +20,8 @@ Some distinct identifiers to Swagger-UI 3.X:
|
||||
|
||||
If you've determined this is the version you have, to find the exact version:
|
||||
- Open your browser's web console (changes between browsers)
|
||||
- Type `versions` in the console and execute the call.
|
||||
- You might need to expand the result, until you get a string similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`.
|
||||
- Type `JSON.stringify(versions)` in the console and execute the call.
|
||||
- The result should look similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`.
|
||||
- The version taken from that example would be `3.1.6`.
|
||||
|
||||
Note: This functionality was added in 3.0.8. If you're unable to execute it, you're likely to use an older version, and in that case the first step would be to upgrade.
|
||||
@@ -51,4 +51,4 @@ If you've determined this is the version you have, to find the exact version:
|
||||
* @link http://swagger.io
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.2",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -39,6 +39,7 @@
|
||||
"e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e"
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^2.0.2",
|
||||
"base64-js": "^1.2.0",
|
||||
"brace": "0.7.0",
|
||||
"classnames": "^2.2.5",
|
||||
@@ -78,7 +79,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.3.0",
|
||||
"swagger-client": "^3.3.1",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { fromJS } from "immutable"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
import { sanitizeUrl } from "core/utils"
|
||||
|
||||
|
||||
class Path extends React.Component {
|
||||
@@ -35,9 +36,9 @@ class Contact extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ url && <div><a href={ url } target="_blank">{ name } - Website</a></div> }
|
||||
{ url && <div><a href={ sanitizeUrl(url) } target="_blank">{ name } - Website</a></div> }
|
||||
{ email &&
|
||||
<a href={`mailto:${email}`}>
|
||||
<a href={sanitizeUrl(`mailto:${email}`)}>
|
||||
{ url ? `Send email to ${name}` : `Contact ${name}`}
|
||||
</a>
|
||||
}
|
||||
@@ -59,7 +60,7 @@ class License extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
url ? <a target="_blank" href={ url }>{ name }</a>
|
||||
url ? <a target="_blank" href={ sanitizeUrl(url) }>{ name }</a>
|
||||
: <span>{ name }</span>
|
||||
}
|
||||
</div>
|
||||
@@ -97,7 +98,7 @@ export default class Info extends React.Component {
|
||||
{ version && <VersionStamp version={version}></VersionStamp> }
|
||||
</h2>
|
||||
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
|
||||
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> }
|
||||
{ url && <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a> }
|
||||
</hgroup>
|
||||
|
||||
<div className="description">
|
||||
@@ -106,14 +107,14 @@ export default class Info extends React.Component {
|
||||
|
||||
{
|
||||
termsOfService && <div>
|
||||
<a target="_blank" href={ termsOfService }>Terms of service</a>
|
||||
<a target="_blank" href={ sanitizeUrl(termsOfService) }>Terms of service</a>
|
||||
</div>
|
||||
}
|
||||
|
||||
{ contact && contact.size ? <Contact data={ contact } /> : null }
|
||||
{ license && license.size ? <License license={ license } /> : null }
|
||||
{ externalDocsUrl ?
|
||||
<a target="_blank" href={externalDocsUrl}>{externalDocsDescription || externalDocsUrl}</a>
|
||||
<a target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</a>
|
||||
: null }
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { sanitizeUrl } from "core/utils"
|
||||
|
||||
export default class OnlineValidatorBadge extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -32,6 +33,8 @@ export default class OnlineValidatorBadge extends React.Component {
|
||||
let { getConfigs } = this.props
|
||||
let { spec } = getConfigs()
|
||||
|
||||
let sanitizedValidatorUrl = sanitizeUrl(this.state.validatorUrl)
|
||||
|
||||
if ( typeof spec === "object" && Object.keys(spec).length) return null
|
||||
|
||||
if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0
|
||||
@@ -40,8 +43,8 @@ export default class OnlineValidatorBadge extends React.Component {
|
||||
}
|
||||
|
||||
return (<span style={{ float: "right"}}>
|
||||
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
|
||||
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
|
||||
<a target="_blank" href={`${ sanitizedValidatorUrl }/debug?url=${ this.state.url }`}>
|
||||
<ValidatorImage src={`${ sanitizedValidatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
|
||||
</a>
|
||||
</span>)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { PureComponent } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { getList } from "core/utils"
|
||||
import * as CustomPropTypes from "core/proptypes"
|
||||
import { sanitizeUrl } from "core/utils"
|
||||
|
||||
//import "less/opblock"
|
||||
|
||||
@@ -206,7 +207,7 @@ export default class Operation extends PureComponent {
|
||||
<span className="opblock-external-docs__description">
|
||||
<Markdown source={ externalDocs.get("description") } />
|
||||
</span>
|
||||
<a className="opblock-external-docs__link" href={ externalDocs.get("url") }>{ externalDocs.get("url") }</a>
|
||||
<a className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.get("url")) }>{ externalDocs.get("url") }</a>
|
||||
</div>
|
||||
</div> : null
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { helpers } from "swagger-client"
|
||||
import { createDeepLinkPath } from "core/utils"
|
||||
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
|
||||
const { opId } = helpers
|
||||
|
||||
export default class Operations extends React.Component {
|
||||
@@ -101,7 +101,7 @@ export default class Operations extends React.Component {
|
||||
{ tagExternalDocsUrl ? ": " : null }
|
||||
{ tagExternalDocsUrl ?
|
||||
<a
|
||||
href={tagExternalDocsUrl}
|
||||
href={sanitizeUrl(tagExternalDocsUrl)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
target={"_blank"}
|
||||
>{tagExternalDocsUrl}</a> : null
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { Component } from "react"
|
||||
import { Map } from "immutable"
|
||||
import PropTypes from "prop-types"
|
||||
import win from "core/window"
|
||||
|
||||
@@ -29,11 +30,21 @@ export default class ParameterRow extends Component {
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
let { specSelectors, pathMethod, param } = props
|
||||
let { isOAS3 } = specSelectors
|
||||
|
||||
let example = param.get("example")
|
||||
let defaultValue = param.get("default")
|
||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
|
||||
let enumValue
|
||||
|
||||
if(isOAS3()) {
|
||||
let schema = param.get("schema") || Map()
|
||||
enumValue = schema.get("enum")
|
||||
} else {
|
||||
enumValue = parameter ? parameter.get("enum") : undefined
|
||||
}
|
||||
let paramValue = parameter ? parameter.get("value") : undefined
|
||||
let enumValue = parameter ? parameter.get("enum") : undefined
|
||||
|
||||
let value
|
||||
|
||||
if ( paramValue !== undefined ) {
|
||||
|
||||
@@ -20,10 +20,10 @@ function onlyOAS3(selector) {
|
||||
|
||||
export const definitionsToAuthorize = onlyOAS3(createSelector(
|
||||
state,
|
||||
({ specSelectors }) => {
|
||||
({specSelectors}) => specSelectors.securityDefinitions(),
|
||||
(system, definitions) => {
|
||||
// Coerce our OpenAPI 3.0 definitions into monoflow definitions
|
||||
// that look like Swagger2 definitions.
|
||||
let definitions = specSelectors.securityDefinitions()
|
||||
let list = List()
|
||||
|
||||
definitions.entrySeq().forEach( ([ defName, definition ]) => {
|
||||
@@ -57,4 +57,4 @@ export const definitionsToAuthorize = onlyOAS3(createSelector(
|
||||
|
||||
return list
|
||||
}
|
||||
))
|
||||
))
|
||||
|
||||
@@ -50,7 +50,7 @@ export const definitions = onlyOAS3(createSelector(
|
||||
|
||||
export const securityDefinitions = onlyOAS3(createSelector(
|
||||
spec,
|
||||
spec => spec.getIn(["components", "securitySchemes"]) || Map()
|
||||
spec => spec.getIn(["components", "securitySchemes"]) || null
|
||||
))
|
||||
|
||||
export const host = OAS3NullSelector
|
||||
|
||||
@@ -80,7 +80,12 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) =
|
||||
}
|
||||
|
||||
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => {
|
||||
const { modelPropertyMacro, parameterMacro } = getConfigs()
|
||||
const {
|
||||
modelPropertyMacro,
|
||||
parameterMacro,
|
||||
requestInterceptor,
|
||||
responseInterceptor
|
||||
} = getConfigs()
|
||||
|
||||
if(typeof(json) === "undefined") {
|
||||
json = specSelectors.specJson()
|
||||
@@ -93,8 +98,15 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
|
||||
|
||||
let specStr = specSelectors.specStr()
|
||||
|
||||
return resolve({fetch, spec: json, baseDoc: url, modelPropertyMacro, parameterMacro })
|
||||
.then( ({spec, errors}) => {
|
||||
return resolve({
|
||||
fetch,
|
||||
spec: json,
|
||||
baseDoc: url,
|
||||
modelPropertyMacro,
|
||||
parameterMacro,
|
||||
requestInterceptor,
|
||||
responseInterceptor
|
||||
}).then( ({spec, errors}) => {
|
||||
errActions.clear({
|
||||
type: "thrown"
|
||||
})
|
||||
@@ -140,7 +152,7 @@ export function changeParam( path, paramName, paramIn, value, isXml ){
|
||||
export const validateParams = ( payload, isOAS3 ) =>{
|
||||
return {
|
||||
type: VALIDATE_PARAMS,
|
||||
payload:{
|
||||
payload:{
|
||||
pathMethod: payload,
|
||||
isOAS3
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Im from "immutable"
|
||||
|
||||
import { sanitizeUrl as braintreeSanitizeUrl } from "@braintree/sanitize-url"
|
||||
import camelCase from "lodash/camelCase"
|
||||
import upperFirst from "lodash/upperFirst"
|
||||
import _memoize from "lodash/memoize"
|
||||
@@ -722,6 +722,14 @@ export const shallowEqualKeys = (a,b, keys) => {
|
||||
})
|
||||
}
|
||||
|
||||
export function sanitizeUrl(url) {
|
||||
if(typeof url !== "string" || url === "") {
|
||||
return ""
|
||||
}
|
||||
|
||||
return braintreeSanitizeUrl(url)
|
||||
}
|
||||
|
||||
export function getAcceptControllingResponse(responses) {
|
||||
if(!Im.OrderedMap.isOrderedMap(responses)) {
|
||||
// wrong type!
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Add a plugin
|
||||
|
||||
### Swagger-UX relies on plugins for all the good stuff.
|
||||
### Swagger-UI relies on plugins for all the good stuff.
|
||||
|
||||
Plugins allow you to add
|
||||
- `statePlugins`
|
||||
|
||||
@@ -129,7 +129,7 @@ export default class Topbar extends React.Component {
|
||||
<div className="topbar">
|
||||
<div className="wrapper">
|
||||
<div className="topbar-wrapper">
|
||||
<Link href="#" title="Swagger UX">
|
||||
<Link href="#">
|
||||
<img height="30" width="30" src={ Logo } alt="Swagger UI"/>
|
||||
<span>swagger</span>
|
||||
</Link>
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
fromJSOrdered,
|
||||
getAcceptControllingResponse,
|
||||
createDeepLinkPath,
|
||||
escapeDeepLinkPath
|
||||
escapeDeepLinkPath,
|
||||
sanitizeUrl
|
||||
} from "core/utils"
|
||||
import win from "core/window"
|
||||
|
||||
@@ -885,4 +886,43 @@ describe("utils", function() {
|
||||
expect(result).toEqual("hello\\#world")
|
||||
})
|
||||
})
|
||||
|
||||
describe("sanitizeUrl", function() {
|
||||
it("should sanitize a `javascript:` url", function() {
|
||||
const res = sanitizeUrl("javascript:alert('bam!')")
|
||||
|
||||
expect(res).toEqual("about:blank")
|
||||
})
|
||||
|
||||
it("should sanitize a `data:` url", function() {
|
||||
const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGV
|
||||
sbG8iKTs8L3NjcmlwdD4=`)
|
||||
|
||||
expect(res).toEqual("about:blank")
|
||||
})
|
||||
|
||||
it("should not modify a `http:` url", function() {
|
||||
const res = sanitizeUrl(`http://swagger.io/`)
|
||||
|
||||
expect(res).toEqual("http://swagger.io/")
|
||||
})
|
||||
|
||||
it("should not modify a `https:` url", function() {
|
||||
const res = sanitizeUrl(`https://swagger.io/`)
|
||||
|
||||
expect(res).toEqual("https://swagger.io/")
|
||||
})
|
||||
|
||||
it("should gracefully handle empty strings", function() {
|
||||
expect(sanitizeUrl("")).toEqual("")
|
||||
})
|
||||
|
||||
it("should gracefully handle non-string values", function() {
|
||||
expect(sanitizeUrl(123)).toEqual("")
|
||||
expect(sanitizeUrl(null)).toEqual("")
|
||||
expect(sanitizeUrl(undefined)).toEqual("")
|
||||
expect(sanitizeUrl([])).toEqual("")
|
||||
expect(sanitizeUrl({})).toEqual("")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user