@@ -51,14 +51,15 @@ export default class ApiKeyAuth extends React.Component { | |||||
return ( | return ( | ||||
<div> | <div> | ||||
<h4>Api key authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4> | |||||
<h4> | |||||
<code>{ name || schema.get("name") }</code> | |||||
(apiKey) | |||||
<JumpToPath path={[ "securityDefinitions", name ]} /> | |||||
</h4> | |||||
{ value && <h6>Authorized</h6>} | { value && <h6>Authorized</h6>} | ||||
<Row> | <Row> | ||||
<Markdown source={ schema.get("description") } /> | <Markdown source={ schema.get("description") } /> | ||||
</Row> | </Row> | ||||
<Row> | |||||
<p>Name: <code>{ schema.get("name") }</code></p> | |||||
</Row> | |||||
<Row> | <Row> | ||||
<p>In: <code>{ schema.get("in") }</code></p> | <p>In: <code>{ schema.get("in") }</code></p> | ||||
</Row> | </Row> | ||||
@@ -0,0 +1,59 @@ | |||||
import React from "react" | |||||
import PropTypes from "prop-types" | |||||
import ImPropTypes from "react-immutable-proptypes" | |||||
export default class Auths extends React.Component { | |||||
static propTypes = { | |||||
} | |||||
render() { | |||||
let { | |||||
schema, | |||||
name, | |||||
getComponent, | |||||
onAuthChange, | |||||
authorized, | |||||
errSelectors | |||||
} = this.props | |||||
const ApiKeyAuth = getComponent("apiKeyAuth") | |||||
const BasicAuth = getComponent("basicAuth") | |||||
let authEl | |||||
const type = schema.get("type") | |||||
switch(type) { | |||||
case "apiKey": authEl = <ApiKeyAuth key={ name } | |||||
schema={ schema } | |||||
name={ name } | |||||
errSelectors={ errSelectors } | |||||
authorized={ authorized } | |||||
getComponent={ getComponent } | |||||
onChange={ onAuthChange } /> | |||||
break | |||||
case "basic": authEl = <BasicAuth key={ name } | |||||
schema={ schema } | |||||
name={ name } | |||||
errSelectors={ errSelectors } | |||||
authorized={ authorized } | |||||
getComponent={ getComponent } | |||||
onChange={ onAuthChange } /> | |||||
break | |||||
default: authEl = <div key={ name }>Unknown security definition type { type }</div> | |||||
} | |||||
return (<div key={`${name}-jump`}> | |||||
{ authEl } | |||||
</div>) | |||||
} | |||||
static propTypes = { | |||||
errSelectors: PropTypes.object.isRequired, | |||||
getComponent: PropTypes.func.isRequired, | |||||
authSelectors: PropTypes.object.isRequired, | |||||
specSelectors: PropTypes.object.isRequired, | |||||
authActions: PropTypes.object.isRequired, | |||||
definitions: ImPropTypes.iterable.isRequired | |||||
} | |||||
} |
@@ -27,7 +27,6 @@ export default class Auths extends React.Component { | |||||
e.preventDefault() | e.preventDefault() | ||||
let { authActions } = this.props | let { authActions } = this.props | ||||
authActions.authorize(this.state) | authActions.authorize(this.state) | ||||
} | } | ||||
@@ -44,8 +43,7 @@ export default class Auths extends React.Component { | |||||
render() { | render() { | ||||
let { definitions, getComponent, authSelectors, errSelectors } = this.props | let { definitions, getComponent, authSelectors, errSelectors } = this.props | ||||
const ApiKeyAuth = getComponent("apiKeyAuth") | |||||
const BasicAuth = getComponent("basicAuth") | |||||
const AuthItem = getComponent("AuthItem") | |||||
const Oauth2 = getComponent("oauth2", true) | const Oauth2 = getComponent("oauth2", true) | ||||
const Button = getComponent("Button") | const Button = getComponent("Button") | ||||
@@ -64,33 +62,15 @@ export default class Auths extends React.Component { | |||||
!!nonOauthDefinitions.size && <form onSubmit={ this.submitAuth }> | !!nonOauthDefinitions.size && <form onSubmit={ this.submitAuth }> | ||||
{ | { | ||||
nonOauthDefinitions.map( (schema, name) => { | nonOauthDefinitions.map( (schema, name) => { | ||||
let type = schema.get("type") | |||||
let authEl | |||||
switch(type) { | |||||
case "apiKey": authEl = <ApiKeyAuth key={ name } | |||||
schema={ schema } | |||||
name={ name } | |||||
errSelectors={ errSelectors } | |||||
authorized={ authorized } | |||||
getComponent={ getComponent } | |||||
onChange={ this.onAuthChange } /> | |||||
break | |||||
case "basic": authEl = <BasicAuth key={ name } | |||||
schema={ schema } | |||||
name={ name } | |||||
errSelectors={ errSelectors } | |||||
authorized={ authorized } | |||||
getComponent={ getComponent } | |||||
onChange={ this.onAuthChange } /> | |||||
break | |||||
default: authEl = <div key={ name }>Unknown security definition type { type }</div> | |||||
} | |||||
return (<div key={`${name}-jump`}> | |||||
{ authEl } | |||||
</div>) | |||||
return <AuthItem | |||||
key={name} | |||||
schema={schema} | |||||
name={name} | |||||
getComponent={getComponent} | |||||
onAuthChange={this.onAuthChange} | |||||
authorized={authorized} | |||||
errSelectors={errSelectors} | |||||
/> | |||||
}).toArray() | }).toArray() | ||||
} | } | ||||
<div className="auth-btn-wrapper"> | <div className="auth-btn-wrapper"> | ||||
@@ -22,7 +22,7 @@ export default { | |||||
securities.entrySeq().forEach( ([ key, security ]) => { | securities.entrySeq().forEach( ([ key, security ]) => { | ||||
let type = security.getIn(["schema", "type"]) | let type = security.getIn(["schema", "type"]) | ||||
if ( type === "apiKey" ) { | |||||
if ( type === "apiKey" || type === "http" ) { | |||||
map = map.set(key, security) | map = map.set(key, security) | ||||
} else if ( type === "basic" ) { | } else if ( type === "basic" ) { | ||||
let username = security.getIn(["value", "username"]) | let username = security.getIn(["value", "username"]) | ||||
@@ -27,23 +27,32 @@ export const definitionsToAuthorize = onlyOAS3(createSelector( | |||||
let list = List() | let list = List() | ||||
definitions.entrySeq().forEach( ([ defName, definition ]) => { | definitions.entrySeq().forEach( ([ defName, definition ]) => { | ||||
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") | |||||
}) | |||||
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({ | 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 | |||||
}) | |||||
[defName]: definition | |||||
})) | })) | ||||
}) | |||||
} | |||||
}) | }) | ||||
return list | return list | ||||
@@ -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 OperationLink from "./operation-link.jsx" | ||||
import Servers from "./servers" | import Servers from "./servers" | ||||
import RequestBodyEditor from "./request-body-editor" | import RequestBodyEditor from "./request-body-editor" | ||||
import HttpAuth from "./http-auth" | |||||
export default { | export default { | ||||
Callbacks, | Callbacks, | ||||
HttpAuth, | |||||
RequestBody, | RequestBody, | ||||
Servers, | Servers, | ||||
RequestBodyEditor, | RequestBodyEditor, | ||||
@@ -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 Markdown from "./markdown" | ||||
import AuthItem from "./auth-item" | |||||
import parameters from "./parameters" | import parameters from "./parameters" | ||||
import VersionStamp from "./version-stamp" | import VersionStamp from "./version-stamp" | ||||
import OnlineValidatorBadge from "./online-validator-badge" | import OnlineValidatorBadge from "./online-validator-badge" | ||||
@@ -6,6 +7,7 @@ import Model from "./model" | |||||
export default { | export default { | ||||
Markdown, | Markdown, | ||||
AuthItem, | |||||
parameters, | parameters, | ||||
VersionStamp, | VersionStamp, | ||||
model: Model, | model: Model, | ||||
@@ -17,6 +17,7 @@ import AuthorizationPopup from "core/components/auth/authorization-popup" | |||||
import AuthorizeBtn from "core/components/auth/authorize-btn" | import AuthorizeBtn from "core/components/auth/authorize-btn" | ||||
import AuthorizeOperationBtn from "core/components/auth/authorize-operation-btn" | import AuthorizeOperationBtn from "core/components/auth/authorize-operation-btn" | ||||
import Auths from "core/components/auth/auths" | import Auths from "core/components/auth/auths" | ||||
import AuthItem from "core/components/auth/auth-item" | |||||
import AuthError from "core/components/auth/error" | import AuthError from "core/components/auth/error" | ||||
import ApiKeyAuth from "core/components/auth/api-key-auth" | import ApiKeyAuth from "core/components/auth/api-key-auth" | ||||
import BasicAuth from "core/components/auth/basic-auth" | import BasicAuth from "core/components/auth/basic-auth" | ||||
@@ -70,6 +71,7 @@ export default function() { | |||||
authorizeBtn: AuthorizeBtn, | authorizeBtn: AuthorizeBtn, | ||||
authorizeOperationBtn: AuthorizeOperationBtn, | authorizeOperationBtn: AuthorizeOperationBtn, | ||||
auths: Auths, | auths: Auths, | ||||
AuthItem: AuthItem, | |||||
authError: AuthError, | authError: AuthError, | ||||
oauth2: Oauth2, | oauth2: Oauth2, | ||||
apiKeyAuth: ApiKeyAuth, | apiKeyAuth: ApiKeyAuth, | ||||