diff --git a/src/core/components/auth/oauth2.jsx b/src/core/components/auth/oauth2.jsx
index 0632c2594e9..e6dbe6a5938 100644
--- a/src/core/components/auth/oauth2.jsx
+++ b/src/core/components/auth/oauth2.jsx
@@ -2,11 +2,6 @@ import React from "react"
import PropTypes from "prop-types"
import oauth2Authorize from "core/oauth2-authorize"
-const IMPLICIT = "implicit"
-const ACCESS_CODE = "accessCode"
-const PASSWORD = "password"
-const APPLICATION = "application"
-
export default class Oauth2 extends React.Component {
static propTypes = {
name: PropTypes.string,
@@ -16,6 +11,7 @@ export default class Oauth2 extends React.Component {
authSelectors: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired,
errSelectors: PropTypes.object.isRequired,
+ specSelectors: PropTypes.object.isRequired,
errActions: PropTypes.object.isRequired,
getConfigs: PropTypes.any
}
@@ -83,7 +79,9 @@ export default class Oauth2 extends React.Component {
}
render() {
- let { schema, getComponent, authSelectors, errSelectors, name } = this.props
+ let {
+ schema, getComponent, authSelectors, errSelectors, name, specSelectors
+ } = this.props
const Input = getComponent("Input")
const Row = getComponent("Row")
const Col = getComponent("Col")
@@ -92,6 +90,14 @@ export default class Oauth2 extends React.Component {
const JumpToPath = getComponent("JumpToPath", true)
const Markdown = getComponent( "Markdown" )
+ const { isOAS3 } = specSelectors
+
+ // Auth type consts
+ const IMPLICIT = "implicit"
+ const PASSWORD = "password"
+ const ACCESS_CODE = isOAS3() ? "authorizationCode" : "accessCode"
+ const APPLICATION = isOAS3() ? "clientCredentials" : "application"
+
let flow = schema.get("flow")
let scopes = schema.get("allowedScopes") || schema.get("scopes")
let authorizedAuth = authSelectors.authorized().get(name)
@@ -102,7 +108,7 @@ export default class Oauth2 extends React.Component {
return (
-
OAuth2.0
+
{name} (OAuth2, { schema.get("flow") })
{ !this.state.appName ? null :
Application: { this.state.appName }
}
{ description &&
}
diff --git a/src/core/oauth2-authorize.js b/src/core/oauth2-authorize.js
index fd3a4afc646..c5521aaf5d4 100644
--- a/src/core/oauth2-authorize.js
+++ b/src/core/oauth2-authorize.js
@@ -22,6 +22,16 @@ export default function authorize ( { auth, authActions, errActions, configs, au
case "implicit":
query.push("response_type=token")
break
+
+ case "clientCredentials":
+ // OAS3
+ authActions.authorizeApplication(auth)
+ return
+
+ case "authorizationCode":
+ // OAS3
+ query.push("response_type=code")
+ break
}
if (typeof clientId === "string") {
diff --git a/src/core/plugins/auth/reducers.js b/src/core/plugins/auth/reducers.js
index 2eca5c08f25..ae28347702a 100644
--- a/src/core/plugins/auth/reducers.js
+++ b/src/core/plugins/auth/reducers.js
@@ -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"])
diff --git a/src/core/plugins/oas3/auth-extensions/wrap-selectors.js b/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
index 973b208148e..838e2dcd526 100644
--- a/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
+++ b/src/core/plugins/oas3/auth-extensions/wrap-selectors.js
@@ -1,29 +1,60 @@
import { createSelector } from "reselect"
-import { List } from "immutable"
+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(...args)
+ return selector(system, ...args)
} else {
return ori(...args)
}
}
}
-const nullSelector = createSelector(() => null)
+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")
-const OAS3NullSelector = onlyOAS3(nullSelector)
+ 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")
+ })
-// Hasta la vista, authorization!
-export const shownDefinitions = OAS3NullSelector
-export const definitionsToAuthorize = OAS3NullSelector
-export const getDefinitionsByNames = OAS3NullSelector
-export const authorized = onlyOAS3(() => List())
-export const isAuthorized = OAS3NullSelector
-export const getConfigs = OAS3NullSelector
+ 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
+ }
+))
\ No newline at end of file
diff --git a/src/core/plugins/oas3/components/http-auth.jsx b/src/core/plugins/oas3/components/http-auth.jsx
new file mode 100644
index 00000000000..bb4727eea7b
--- /dev/null
+++ b/src/core/plugins/oas3/components/http-auth.jsx
@@ -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
+
+ { name || schema.get("name") }
+ (http, Basic)
+
+
+ { username &&
Authorized
}
+
+
+
+
+
+ {
+ username ? { username }
+ :
+ }
+
+
+
+ {
+ username ? ******
+ :
+ }
+
+ {
+ errors.valueSeq().map( (error, key) => {
+ return
+ } )
+ }
+
+ }
+
+ if(scheme === "bearer") {
+ return (
+
+
+ { name || schema.get("name") }
+ (http, Bearer)
+
+
+ { value &&
Authorized
}
+
+
+
+
+ In: { schema.get("in") }
+
+
+
+ {
+ value ? ******
+ :
+ }
+
+ {
+ errors.valueSeq().map( (error, key) => {
+ return
+ } )
+ }
+
+ )
+ }
+ return
+ {name} HTTP authentication: unsupported or missing scheme
+
+ }
+}
diff --git a/src/core/plugins/oas3/components/index.js b/src/core/plugins/oas3/components/index.js
index 642c6689b92..edd409a14ed 100644
--- a/src/core/plugins/oas3/components/index.js
+++ b/src/core/plugins/oas3/components/index.js
@@ -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,
diff --git a/src/core/plugins/oas3/spec-extensions/wrap-selectors.js b/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
index ff892b4f963..78ab05a8496 100644
--- a/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
+++ b/src/core/plugins/oas3/spec-extensions/wrap-selectors.js
@@ -48,12 +48,16 @@ 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
export const produces = OAS3NullSelector
export const schemes = OAS3NullSelector
-export const securityDefinitions = OAS3NullSelector
// New selectors
diff --git a/src/core/plugins/oas3/wrap-components/auth-item.jsx b/src/core/plugins/oas3/wrap-components/auth-item.jsx
new file mode 100644
index 00000000000..bd6df5cb881
--- /dev/null
+++ b/src/core/plugins/oas3/wrap-components/auth-item.jsx
@@ -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
+ } else {
+ return
+ }
+})
diff --git a/src/core/plugins/oas3/wrap-components/index.js b/src/core/plugins/oas3/wrap-components/index.js
index 8b105b38286..910dcf29ca9 100644
--- a/src/core/plugins/oas3/wrap-components/index.js
+++ b/src/core/plugins/oas3/wrap-components/index.js
@@ -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,
diff --git a/src/core/presets/base.js b/src/core/presets/base.js
index 10a12645aaa..ec005b37f42 100644
--- a/src/core/presets/base.js
+++ b/src/core/presets/base.js
@@ -17,6 +17,7 @@ import AuthorizationPopup from "core/components/auth/authorization-popup"
import AuthorizeBtn from "core/components/auth/authorize-btn"
import AuthorizeOperationBtn from "core/components/auth/authorize-operation-btn"
import Auths from "core/components/auth/auths"
+import AuthItem from "core/components/auth/auth-item"
import AuthError from "core/components/auth/error"
import ApiKeyAuth from "core/components/auth/api-key-auth"
import BasicAuth from "core/components/auth/basic-auth"
@@ -70,6 +71,7 @@ export default function() {
authorizeBtn: AuthorizeBtn,
authorizeOperationBtn: AuthorizeOperationBtn,
auths: Auths,
+ AuthItem: AuthItem,
authError: AuthError,
oauth2: Oauth2,
apiKeyAuth: ApiKeyAuth,
diff --git a/test/core/plugins/oas3/wrap-auth-selectors.js b/test/core/plugins/oas3/wrap-auth-selectors.js
new file mode 100644
index 00000000000..1687d767b32
--- /dev/null
+++ b/test/core/plugins/oas3/wrap-auth-selectors.js
@@ -0,0 +1,116 @@
+/* eslint-env mocha */
+import expect, { createSpy } from "expect"
+import { Map, fromJS } from "immutable"
+import {
+ definitionsToAuthorize
+} from "corePlugins/oas3/auth-extensions/wrap-selectors"
+
+describe.only("oas3 plugin - auth extensions - wrapSelectors", function(){
+
+ describe("execute", function(){
+
+ it("should add `securities` to the oriAction call", function(){
+ // Given
+ const system = {
+ getSystem: () => system,
+ specSelectors: {
+ specJson: () => fromJS({
+ openapi: "3.0.0"
+ }),
+ securityDefinitions: () => {
+ return fromJS({
+ "oauth2AuthorizationCode": {
+ "type": "oauth2",
+ "flows": {
+ "authorizationCode": {
+ "authorizationUrl": "http://google.com/",
+ "tokenUrl": "http://google.com/",
+ "scopes": {
+ "myScope": "our only scope"
+ }
+ }
+ }
+ },
+ "oauth2Multiflow": {
+ "type": "oauth2",
+ "flows": {
+ "clientCredentials": {
+ "tokenUrl": "http://google.com/",
+ "scopes": {
+ "myScope": "our only scope"
+ }
+ },
+ "password": {
+ "tokenUrl": "http://google.com/",
+ "scopes": {
+ "myScope": "our only scope"
+ }
+ },
+ "authorizationCode": {
+ "authorizationUrl": "http://google.com/",
+ "tokenUrl": "http://google.com/",
+ "scopes": {
+ "myScope": "our only scope"
+ }
+ }
+ }
+ }
+ })
+ }
+ }
+ }
+
+ // When
+ let res = definitionsToAuthorize(() => null, system)()
+
+ // Then
+ expect(res.toJS()).toEqual([
+ {
+ oauth2AuthorizationCode: {
+ flow: "authorizationCode",
+ authorizationUrl: "http://google.com/",
+ tokenUrl: "http://google.com/",
+ scopes: {
+ "myScope": "our only scope"
+ },
+ type: "oauth2"
+ }
+ },
+ {
+ oauth2Multiflow: {
+ flow: "clientCredentials",
+ tokenUrl: "http://google.com/",
+ scopes: {
+ "myScope": "our only scope"
+ },
+ type: "oauth2"
+ }
+ },
+ {
+ oauth2Multiflow: {
+ flow: "password",
+ tokenUrl: "http://google.com/",
+ scopes: {
+ "myScope": "our only scope"
+ },
+ type: "oauth2"
+ }
+ },
+ {
+ oauth2Multiflow: {
+ flow: "authorizationCode",
+ authorizationUrl: "http://google.com/",
+ tokenUrl: "http://google.com/",
+ scopes: {
+ "myScope": "our only scope"
+ },
+ type: "oauth2"
+ }
+ },
+ ])
+
+ })
+
+ })
+
+})