Merge branch 'master' of github.com:swagger-api/swagger-ui into ft/performance
This commit is contained in:
@@ -22,7 +22,7 @@ export default {
|
||||
securities.entrySeq().forEach( ([ key, security ]) => {
|
||||
let type = security.getIn(["schema", "type"])
|
||||
|
||||
if ( type === "apiKey" ) {
|
||||
if ( type === "apiKey" || type === "http" ) {
|
||||
map = map.set(key, security)
|
||||
} else if ( type === "basic" ) {
|
||||
let username = security.getIn(["value", "username"])
|
||||
|
||||
@@ -10,7 +10,7 @@ export const shownDefinitions = createSelector(
|
||||
|
||||
export const definitionsToAuthorize = createSelector(
|
||||
state,
|
||||
() =>( { specSelectors } ) => {
|
||||
() => ( { specSelectors } ) => {
|
||||
let definitions = specSelectors.securityDefinitions()
|
||||
let list = List()
|
||||
|
||||
@@ -27,7 +27,7 @@ export const definitionsToAuthorize = createSelector(
|
||||
)
|
||||
|
||||
|
||||
export const getDefinitionsByNames = ( state, securities ) =>( { specSelectors } ) => {
|
||||
export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors } ) => {
|
||||
let securityDefinitions = specSelectors.securityDefinitions()
|
||||
let result = List()
|
||||
|
||||
@@ -64,7 +64,7 @@ export const authorized = createSelector(
|
||||
)
|
||||
|
||||
|
||||
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
||||
export const isAuthorized = ( state, securities ) => ( { authSelectors } ) => {
|
||||
let authorized = authSelectors.authorized()
|
||||
|
||||
if(!List.isList(securities)) {
|
||||
|
||||
@@ -7,13 +7,16 @@ export default function downloadUrlPlugin (toolbox) {
|
||||
let { fn } = toolbox
|
||||
|
||||
const actions = {
|
||||
download: (url)=> ({ errActions, specSelectors, specActions }) => {
|
||||
download: (url)=> ({ errActions, specSelectors, specActions, getConfigs }) => {
|
||||
let { fetch } = fn
|
||||
const config = getConfigs()
|
||||
url = url || specSelectors.url()
|
||||
specActions.updateLoadingStatus("loading")
|
||||
fetch({
|
||||
url,
|
||||
loadSpec: true,
|
||||
requestInterceptor: config.requestInterceptor || (a => a),
|
||||
responseInterceptor: config.responseInterceptor || (a => a),
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"Accept": "application/json,*/*"
|
||||
|
||||
60
src/core/plugins/oas3/auth-extensions/wrap-selectors.js
Normal file
60
src/core/plugins/oas3/auth-extensions/wrap-selectors.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createSelector } from "reselect"
|
||||
import { List, Map, fromJS } from "immutable"
|
||||
import { isOAS3 as isOAS3Helper } from "../helpers"
|
||||
|
||||
|
||||
// Helpers
|
||||
|
||||
const state = state => state
|
||||
|
||||
function onlyOAS3(selector) {
|
||||
return (ori, system) => (state, ...args) => {
|
||||
const spec = system.getSystem().specSelectors.specJson()
|
||||
if(isOAS3Helper(spec)) {
|
||||
return selector(system, ...args)
|
||||
} else {
|
||||
return ori(...args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const definitionsToAuthorize = onlyOAS3(createSelector(
|
||||
state,
|
||||
({ specSelectors }) => {
|
||||
// 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 ]) => {
|
||||
const type = definition.get("type")
|
||||
|
||||
if(type === "oauth2") {
|
||||
definition.get("flows").entrySeq().forEach(([flowKey, flowVal]) => {
|
||||
let translatedDef = fromJS({
|
||||
flow: flowKey,
|
||||
authorizationUrl: flowVal.get("authorizationUrl"),
|
||||
tokenUrl: flowVal.get("tokenUrl"),
|
||||
scopes: flowVal.get("scopes"),
|
||||
type: definition.get("type")
|
||||
})
|
||||
|
||||
list = list.push(new Map({
|
||||
[defName]: translatedDef.filter((v) => {
|
||||
// filter out unset values, sometimes `authorizationUrl`
|
||||
// and `tokenUrl` come out as `undefined` in the data
|
||||
return v !== undefined
|
||||
})
|
||||
}))
|
||||
})
|
||||
}
|
||||
if(type === "http" || type === "apiKey") {
|
||||
list = list.push(new Map({
|
||||
[defName]: definition
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
))
|
||||
134
src/core/plugins/oas3/components/http-auth.jsx
Normal file
134
src/core/plugins/oas3/components/http-auth.jsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
export default class HttpAuth extends React.Component {
|
||||
static propTypes = {
|
||||
authorized: PropTypes.object,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
errSelectors: PropTypes.object.isRequired,
|
||||
schema: PropTypes.object.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
let { name, schema } = this.props
|
||||
let value = this.getValue()
|
||||
|
||||
this.state = {
|
||||
name: name,
|
||||
schema: schema,
|
||||
value: value
|
||||
}
|
||||
}
|
||||
|
||||
getValue () {
|
||||
let { name, authorized } = this.props
|
||||
|
||||
return authorized && authorized.getIn([name, "value"])
|
||||
}
|
||||
|
||||
onChange =(e) => {
|
||||
let { onChange } = this.props
|
||||
let { value, name } = e.target
|
||||
|
||||
let newValue = this.state.value || {}
|
||||
if(name) {
|
||||
newValue[name] = value
|
||||
} else {
|
||||
newValue = value
|
||||
}
|
||||
|
||||
this.setState({ value: newValue }, () => onChange(this.state))
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
let { schema, getComponent, errSelectors, name } = this.props
|
||||
const Input = getComponent("Input")
|
||||
const Row = getComponent("Row")
|
||||
const Col = getComponent("Col")
|
||||
const AuthError = getComponent("authError")
|
||||
const Markdown = getComponent( "Markdown" )
|
||||
const JumpToPath = getComponent("JumpToPath", true)
|
||||
|
||||
const scheme = schema.get("scheme")
|
||||
let value = this.getValue()
|
||||
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
|
||||
|
||||
if(scheme === "basic") {
|
||||
let username = value ? value.get("username") : null
|
||||
return <div>
|
||||
<h4>
|
||||
<code>{ name || schema.get("name") }</code>
|
||||
(http, Basic)
|
||||
<JumpToPath path={[ "securityDefinitions", name ]} />
|
||||
</h4>
|
||||
{ username && <h6>Authorized</h6> }
|
||||
<Row>
|
||||
<Markdown source={ schema.get("description") } />
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Username:</label>
|
||||
{
|
||||
username ? <code> { username } </code>
|
||||
: <Col><Input type="text" required="required" name="username" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Password:</label>
|
||||
{
|
||||
username ? <code> ****** </code>
|
||||
: <Col><Input required="required"
|
||||
autoComplete="new-password"
|
||||
name="password"
|
||||
type="password"
|
||||
onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
return <AuthError error={ error }
|
||||
key={ key }/>
|
||||
} )
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
if(scheme === "bearer") {
|
||||
return (
|
||||
<div>
|
||||
<h4>
|
||||
<code>{ name || schema.get("name") }</code>
|
||||
(http, Bearer)
|
||||
<JumpToPath path={[ "securityDefinitions", name ]} />
|
||||
</h4>
|
||||
{ value && <h6>Authorized</h6>}
|
||||
<Row>
|
||||
<Markdown source={ schema.get("description") } />
|
||||
</Row>
|
||||
<Row>
|
||||
<p>In: <code>{ schema.get("in") }</code></p>
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Value:</label>
|
||||
{
|
||||
value ? <code> ****** </code>
|
||||
: <Col><Input type="text" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
return <AuthError error={ error }
|
||||
key={ key }/>
|
||||
} )
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return <div>
|
||||
<em><b>{name}</b> HTTP authentication: unsupported or missing scheme</em>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ import RequestBody from "./request-body"
|
||||
import OperationLink from "./operation-link.jsx"
|
||||
import Servers from "./servers"
|
||||
import RequestBodyEditor from "./request-body-editor"
|
||||
import HttpAuth from "./http-auth"
|
||||
|
||||
export default {
|
||||
Callbacks,
|
||||
HttpAuth,
|
||||
RequestBody,
|
||||
Servers,
|
||||
RequestBodyEditor,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { OrderedMap } from "immutable"
|
||||
const RequestBody = ({
|
||||
requestBody,
|
||||
getComponent,
|
||||
getConfigs,
|
||||
specSelectors,
|
||||
contentType,
|
||||
isExecute,
|
||||
@@ -27,6 +28,7 @@ const RequestBody = ({
|
||||
}
|
||||
<ModelExample
|
||||
getComponent={ getComponent }
|
||||
getConfigs={ getConfigs }
|
||||
specSelectors={ specSelectors }
|
||||
expandDepth={1}
|
||||
isExecute={isExecute}
|
||||
@@ -46,6 +48,7 @@ const RequestBody = ({
|
||||
RequestBody.propTypes = {
|
||||
requestBody: ImPropTypes.orderedMap.isRequired,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
getConfigs: PropTypes.func.isRequired,
|
||||
specSelectors: PropTypes.object.isRequired,
|
||||
contentType: PropTypes.string.isRequired,
|
||||
isExecute: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// import reducers from "./reducers"
|
||||
// import * as actions from "./actions"
|
||||
import * as specWrapSelectors from "./spec-extensions/wrap-selectors"
|
||||
import * as authWrapSelectors from "./auth-extensions/wrap-selectors"
|
||||
import * as specSelectors from "./spec-extensions/selectors"
|
||||
import components from "./components"
|
||||
import wrapComponents from "./wrap-components"
|
||||
@@ -17,6 +18,9 @@ export default function() {
|
||||
wrapSelectors: specWrapSelectors,
|
||||
selectors: specSelectors
|
||||
},
|
||||
auth: {
|
||||
wrapSelectors: authWrapSelectors
|
||||
},
|
||||
oas3: {
|
||||
actions: oas3Actions,
|
||||
reducers: oas3Reducers,
|
||||
|
||||
@@ -48,6 +48,11 @@ export const definitions = onlyOAS3(createSelector(
|
||||
spec => spec.getIn(["components", "schemas"]) || Map()
|
||||
))
|
||||
|
||||
export const securityDefinitions = onlyOAS3(createSelector(
|
||||
spec,
|
||||
spec => spec.getIn(["components", "securitySchemes"]) || Map()
|
||||
))
|
||||
|
||||
export const host = OAS3NullSelector
|
||||
export const basePath = OAS3NullSelector
|
||||
export const consumes = OAS3NullSelector
|
||||
|
||||
23
src/core/plugins/oas3/wrap-components/auth-item.jsx
Normal file
23
src/core/plugins/oas3/wrap-components/auth-item.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from "react"
|
||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||
|
||||
export default OAS3ComponentWrapFactory(({ Ori, ...props }) => {
|
||||
const {
|
||||
schema, getComponent, errSelectors, authorized, onAuthChange, name
|
||||
} = props
|
||||
|
||||
const HttpAuth = getComponent("HttpAuth")
|
||||
const type = schema.get("type")
|
||||
|
||||
if(type === "http") {
|
||||
return <HttpAuth key={ name }
|
||||
schema={ schema }
|
||||
name={ name }
|
||||
errSelectors={ errSelectors }
|
||||
authorized={ authorized }
|
||||
getComponent={ getComponent }
|
||||
onChange={ onAuthChange }/>
|
||||
} else {
|
||||
return <Ori {...props} />
|
||||
}
|
||||
})
|
||||
@@ -1,4 +1,5 @@
|
||||
import Markdown from "./markdown"
|
||||
import AuthItem from "./auth-item"
|
||||
import parameters from "./parameters"
|
||||
import VersionStamp from "./version-stamp"
|
||||
import OnlineValidatorBadge from "./online-validator-badge"
|
||||
@@ -6,6 +7,7 @@ import Model from "./model"
|
||||
|
||||
export default {
|
||||
Markdown,
|
||||
AuthItem,
|
||||
parameters,
|
||||
VersionStamp,
|
||||
model: Model,
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import ReactMarkdown from "react-markdown"
|
||||
import { Parser, HtmlRenderer } from "commonmark"
|
||||
import { OAS3ComponentWrapFactory } from "../helpers"
|
||||
import { sanitizer } from "core/components/providers/markdown"
|
||||
|
||||
export default OAS3ComponentWrapFactory(({ source }) => { return source ? (
|
||||
<ReactMarkdown
|
||||
source={sanitizer(source)}
|
||||
className={"renderedMarkdown"}
|
||||
/>
|
||||
) : null})
|
||||
export const Markdown = ({ source }) => {
|
||||
if ( source ) {
|
||||
const parser = new Parser()
|
||||
const writer = new HtmlRenderer()
|
||||
const html = writer.render(parser.parse(source || ""))
|
||||
const sanitized = sanitizer(html)
|
||||
|
||||
if ( !source || !html || !sanitized ) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactMarkdown
|
||||
source={sanitized}
|
||||
className={"renderedMarkdown"}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
Markdown.propTypes = {
|
||||
source: PropTypes.string
|
||||
}
|
||||
|
||||
export default OAS3ComponentWrapFactory(Markdown)
|
||||
@@ -49,7 +49,7 @@ class Parameters extends Component {
|
||||
onChangeKey,
|
||||
} = this.props
|
||||
|
||||
changeParam( onChangeKey, param.get("name"), value, isXml)
|
||||
changeParam( onChangeKey, param.get("name"), param.get("in"), value, isXml)
|
||||
}
|
||||
|
||||
onChangeConsumesWrapper = ( val ) => {
|
||||
|
||||
@@ -130,17 +130,20 @@ export const formatIntoYaml = () => ({specActions, specSelectors}) => {
|
||||
}
|
||||
}
|
||||
|
||||
export function changeParam( path, paramName, value, isXml ){
|
||||
export function changeParam( path, paramName, paramIn, value, isXml ){
|
||||
return {
|
||||
type: UPDATE_PARAM,
|
||||
payload:{ path, value, paramName, isXml }
|
||||
payload:{ path, value, paramName, paramIn, isXml }
|
||||
}
|
||||
}
|
||||
|
||||
export function validateParams( payload ){
|
||||
export const validateParams = ( payload, isOAS3 ) =>{
|
||||
return {
|
||||
type: VALIDATE_PARAMS,
|
||||
payload:{ pathMethod: payload }
|
||||
payload:{
|
||||
pathMethod: payload,
|
||||
isOAS3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +209,6 @@ export const executeRequest = (req) =>
|
||||
// if url is relative, parseUrl makes it absolute by inferring from `window.location`
|
||||
req.contextUrl = parseUrl(specSelectors.url()).toString()
|
||||
|
||||
|
||||
if(op && op.operationId) {
|
||||
req.operationId = op.operationId
|
||||
} else if(op && pathName && method) {
|
||||
|
||||
@@ -40,9 +40,10 @@ export default {
|
||||
},
|
||||
|
||||
[UPDATE_PARAM]: ( state, {payload} ) => {
|
||||
let { path, paramName, value, isXml } = payload
|
||||
let { path, paramName, paramIn, value, isXml } = payload
|
||||
|
||||
return state.updateIn( [ "resolved", "paths", ...path, "parameters" ], fromJS([]), parameters => {
|
||||
const index = parameters.findIndex(p => p.get( "name" ) === paramName )
|
||||
const index = parameters.findIndex(p => p.get( "name" ) === paramName && p.get("in") === paramIn )
|
||||
if (!(value instanceof win.File)) {
|
||||
value = fromJSOrdered( value )
|
||||
}
|
||||
@@ -50,14 +51,14 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod } } ) => {
|
||||
[VALIDATE_PARAMS]: ( state, { payload: { pathMethod, isOAS3 } } ) => {
|
||||
let operation = state.getIn( [ "resolved", "paths", ...pathMethod ] )
|
||||
let isXml = /xml/i.test(operation.get("consumes_value"))
|
||||
|
||||
return state.updateIn( [ "resolved", "paths", ...pathMethod, "parameters" ], fromJS([]), parameters => {
|
||||
return parameters.withMutations( parameters => {
|
||||
for ( let i = 0, len = parameters.count(); i < len; i++ ) {
|
||||
let errors = validateParam(parameters.get(i), isXml)
|
||||
let errors = validateParam(parameters.get(i), isXml, isOAS3)
|
||||
parameters.setIn([i, "errors"], fromJS(errors))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -260,10 +260,10 @@ export const allowTryItOutFor = () => {
|
||||
}
|
||||
|
||||
// Get the parameter value by parameter name
|
||||
export function getParameter(state, pathMethod, name) {
|
||||
export function getParameter(state, pathMethod, name, inType) {
|
||||
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([]))
|
||||
return params.filter( (p) => {
|
||||
return Map.isMap(p) && p.get("name") === name
|
||||
return Map.isMap(p) && p.get("name") === name && p.get("in") === inType
|
||||
}).first()
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ export function parameterValues(state, pathMethod, isXml) {
|
||||
let params = spec(state).getIn(["paths", ...pathMethod, "parameters"], fromJS([]))
|
||||
return params.reduce( (hash, p) => {
|
||||
let value = isXml && p.get("in") === "body" ? p.get("value_xml") : p.get("value")
|
||||
return hash.set(p.get("name"), value)
|
||||
return hash.set(`${p.get("in")}.${p.get("name")}`, value)
|
||||
}, fromJS({}))
|
||||
}
|
||||
|
||||
|
||||
@@ -13,3 +13,7 @@ export const executeRequest = (ori, { specActions }) => (req) => {
|
||||
specActions.logRequest(req)
|
||||
return ori(req)
|
||||
}
|
||||
|
||||
export const validateParams = (ori, { specSelectors }) => (req) => {
|
||||
return ori(req, specSelectors.isOAS3())
|
||||
}
|
||||
Reference in New Issue
Block a user