in with the new
This commit is contained in:
118
src/core/plugins/auth/actions.js
Normal file
118
src/core/plugins/auth/actions.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import win from "core/window"
|
||||
import btoa from "btoa"
|
||||
|
||||
export const SHOW_AUTH_POPUP = "show_popup"
|
||||
export const AUTHORIZE = "authorize"
|
||||
export const LOGOUT = "logout"
|
||||
export const PRE_AUTHORIZE_OAUTH2 = "pre_authorize_oauth2"
|
||||
export const AUTHORIZE_OAUTH2 = "authorize_oauth2"
|
||||
export const VALIDATE = "validate"
|
||||
|
||||
export function showDefinitions(payload) {
|
||||
return {
|
||||
type: SHOW_AUTH_POPUP,
|
||||
payload: payload
|
||||
}
|
||||
}
|
||||
|
||||
export function authorize(payload) {
|
||||
return {
|
||||
type: AUTHORIZE,
|
||||
payload: payload
|
||||
}
|
||||
}
|
||||
|
||||
export function logout(payload) {
|
||||
return {
|
||||
type: LOGOUT,
|
||||
payload: payload
|
||||
}
|
||||
}
|
||||
|
||||
export const preAuthorizeOauth2 = (payload) => ( { authActions, errActions } ) => {
|
||||
let { auth , token, isValid } = payload
|
||||
let { schema, name } = auth
|
||||
let flow = schema.get("flow")
|
||||
|
||||
// remove oauth2 property from window after redirect from authentication
|
||||
delete win.swaggerUIRedirectOauth2
|
||||
|
||||
if ( flow !== "accessCode" && !isValid ) {
|
||||
errActions.newAuthErr( {
|
||||
authId: name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
})
|
||||
}
|
||||
|
||||
if ( token.error ) {
|
||||
errActions.newAuthErr({
|
||||
authId: name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: JSON.stringify(token)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
authActions.authorizeOauth2({ auth, token })
|
||||
}
|
||||
|
||||
export function authorizeOauth2(payload) {
|
||||
return {
|
||||
type: AUTHORIZE_OAUTH2,
|
||||
payload: payload
|
||||
}
|
||||
}
|
||||
|
||||
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 fn.fetch(req)
|
||||
.then(( response ) => {
|
||||
let token = JSON.parse(response.data)
|
||||
let error = token && ( token.error || "" )
|
||||
let parseError = token && ( token.parseError || "" )
|
||||
|
||||
if ( !response.ok ) {
|
||||
errActions.newAuthErr( {
|
||||
authId: name,
|
||||
level: "error",
|
||||
source: "auth",
|
||||
message: response.statusText
|
||||
} )
|
||||
return
|
||||
}
|
||||
|
||||
if ( error || parseError ) {
|
||||
errActions.newAuthErr({
|
||||
authId: name,
|
||||
level: "error",
|
||||
source: "auth",
|
||||
message: JSON.stringify(token)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
authActions.authorizeOauth2({ auth, token })
|
||||
})
|
||||
.catch(err => { errActions.newAuthErr( err ) })
|
||||
}
|
||||
19
src/core/plugins/auth/index.js
Normal file
19
src/core/plugins/auth/index.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import reducers from "./reducers"
|
||||
import * as actions from "./actions"
|
||||
import * as selectors from "./selectors"
|
||||
import * as specWrapActionReplacements from "./spec-wrap-actions"
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
statePlugins: {
|
||||
auth: {
|
||||
reducers,
|
||||
actions,
|
||||
selectors
|
||||
},
|
||||
spec: {
|
||||
wrapActions: specWrapActionReplacements
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/core/plugins/auth/reducers.js
Normal file
63
src/core/plugins/auth/reducers.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { fromJS, Map } from "immutable"
|
||||
import btoa from "btoa"
|
||||
|
||||
import {
|
||||
SHOW_AUTH_POPUP,
|
||||
AUTHORIZE,
|
||||
PRE_AUTHORIZE_OAUTH2,
|
||||
AUTHORIZE_OAUTH2,
|
||||
LOGOUT
|
||||
} from "./actions"
|
||||
|
||||
export default {
|
||||
[SHOW_AUTH_POPUP]: (state, { payload } ) =>{
|
||||
return state.set( "showDefinitions", payload )
|
||||
},
|
||||
|
||||
[AUTHORIZE]: (state, { payload } ) =>{
|
||||
let securities = fromJS(payload)
|
||||
let map = state.get("authorized") || Map()
|
||||
|
||||
// refactor withMutations
|
||||
securities.entrySeq().forEach( ([ key, security ]) => {
|
||||
let type = security.getIn(["schema", "type"])
|
||||
let name = security.get("name")
|
||||
|
||||
if ( type === "apiKey" ) {
|
||||
map = map.set(key, security)
|
||||
} else if ( type === "basic" ) {
|
||||
let username = security.getIn(["value", "username"])
|
||||
let password = security.getIn(["value", "password"])
|
||||
|
||||
map = map.setIn([key, "value"], {
|
||||
username: username,
|
||||
header: "Basic " + btoa(username + ":" + password)
|
||||
})
|
||||
|
||||
map = map.setIn([key, "schema"], security.get("schema"))
|
||||
}
|
||||
})
|
||||
|
||||
return state.set( "authorized", map )
|
||||
},
|
||||
|
||||
[AUTHORIZE_OAUTH2]: (state, { payload } ) =>{
|
||||
let { auth, token } = payload
|
||||
let parsedAuth
|
||||
|
||||
auth.token = token
|
||||
parsedAuth = fromJS(auth)
|
||||
|
||||
return state.setIn( [ "authorized", parsedAuth.get("name") ], parsedAuth )
|
||||
},
|
||||
|
||||
[LOGOUT]: (state, { payload } ) =>{
|
||||
let result = state.get("authorized").withMutations((authorized) => {
|
||||
payload.forEach((auth) => {
|
||||
authorized.delete(auth)
|
||||
})
|
||||
})
|
||||
|
||||
return state.set("authorized", result)
|
||||
}
|
||||
}
|
||||
78
src/core/plugins/auth/selectors.js
Normal file
78
src/core/plugins/auth/selectors.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { createSelector } from "reselect"
|
||||
import { List, Map } from "immutable"
|
||||
|
||||
const state = state => state
|
||||
|
||||
export const shownDefinitions = createSelector(
|
||||
state,
|
||||
auth => auth.get( "showDefinitions" )
|
||||
)
|
||||
|
||||
export const definitionsToAuthorize = createSelector(
|
||||
state,
|
||||
auth =>( { specSelectors } ) => {
|
||||
let definitions = specSelectors.securityDefinitions()
|
||||
let list = List()
|
||||
|
||||
//todo refactor
|
||||
definitions.entrySeq().forEach( ([ key, val ]) => {
|
||||
let map = Map()
|
||||
|
||||
map = map.set(key, val)
|
||||
list = list.push(map)
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
export const getDefinitionsByNames = ( state, securities ) =>( { specSelectors } ) => {
|
||||
let securityDefinitions = specSelectors.securityDefinitions()
|
||||
let result = List()
|
||||
|
||||
securities.valueSeq().forEach( (names) => {
|
||||
let map = Map()
|
||||
names.entrySeq().forEach( ([name, scopes]) => {
|
||||
let definition = securityDefinitions.get(name)
|
||||
let allowedScopes
|
||||
|
||||
if ( definition.get("type") === "oauth2" && scopes.size ) {
|
||||
allowedScopes = definition.get("scopes")
|
||||
|
||||
allowedScopes.keySeq().forEach( (key) => {
|
||||
if ( !scopes.contains(key) ) {
|
||||
allowedScopes = allowedScopes.delete(key)
|
||||
}
|
||||
})
|
||||
|
||||
definition = definition.set("allowedScopes", allowedScopes)
|
||||
}
|
||||
|
||||
map = map.set(name, definition)
|
||||
})
|
||||
|
||||
result = result.push(map)
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export const authorized = createSelector(
|
||||
state,
|
||||
auth => auth.get("authorized") || Map()
|
||||
)
|
||||
|
||||
|
||||
export const isAuthorized = ( state, securities ) =>( { authSelectors } ) => {
|
||||
let authorized = authSelectors.authorized()
|
||||
let isAuth = false
|
||||
|
||||
return !!securities.toJS().filter( ( security ) => {
|
||||
let isAuthorized = true
|
||||
|
||||
return Object.keys(security).map((key) => {
|
||||
return !isAuthorized || !!authorized.get(key)
|
||||
}).indexOf(false) === -1
|
||||
}).length
|
||||
}
|
||||
13
src/core/plugins/auth/spec-wrap-actions.js
Normal file
13
src/core/plugins/auth/spec-wrap-actions.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Map } from "immutable"
|
||||
|
||||
// Add security to the final `execute` call ( via `extras` )
|
||||
export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path, method, operation, extras }) => {
|
||||
let securities = {
|
||||
authorized: authSelectors.authorized() && authSelectors.authorized().toJS(),
|
||||
definitions: specSelectors.securityDefinitions() && specSelectors.securityDefinitions().toJS(),
|
||||
specSecurity: specSelectors.security() && specSelectors.security().toJS()
|
||||
}
|
||||
|
||||
return oriAction({ path, method, operation, securities, ...extras })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user