diff --git a/src/actions/index.js b/src/actions/index.js index bb4af8eadefe78ba51db8f1fc25b9b20104d30a0..04fefbdcd8be7d25e7b27b6d3f3027c86d339531 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,4 +1,13 @@ -import { createAction, createActions, handleActions, combineActions } from 'redux-actions' -import promiseMiddleware from 'redux-promise'; +import { createActions} from 'redux-actions' -export const discoveryStart = createAction('discoveryStart') +const actionCreators = createActions({ + discovery: { + start: hostname => (hostname), + completed: payload => (payload) + }, + serverConfig: { + save: config => (config) + } +}); + +export default actionCreators diff --git a/src/components/HostnameInput.jsx b/src/components/HostnameInput.jsx index 763b2d358d241f81e48cd91dcdedb10d8025498c..ffd555e3d6bfce7eab74570ad605c7dc52261a06 100644 --- a/src/components/HostnameInput.jsx +++ b/src/components/HostnameInput.jsx @@ -1,15 +1,10 @@ import React, { PureComponent } from 'react' -import {Navbar, Nav, NavItem, NavDropdown, MenuItem, Glyphicon, Jumbotron, Button} from 'react-bootstrap' -import {Row, Col, Collapse, FormControl, FormGroup, ControlLabel, HelpBlock} from 'react-bootstrap' +import {Alert, Navbar, Nav, NavItem, NavDropdown, MenuItem, Glyphicon, Jumbotron, Button} from 'react-bootstrap' +import {Panel, Row, Col, Collapse, FormControl, FormGroup, ControlLabel, HelpBlock} from 'react-bootstrap' import FontAwesome from 'react-fontawesome' - -const foo = () => { - console.log("AYA") -} - -const defaultHost = "https://auth.dataporten.no/" +const defaultHost = "https://auth.dataporten.no" class Component extends PureComponent { @@ -21,7 +16,8 @@ class Component extends PureComponent { } discoveryStart(e) { - console.log("Setting hostname") + console.log("Setting hostname", this.state.hostname) + console.log(this.props) this.props.discoveryStart(this.state.hostname) } @@ -30,9 +26,43 @@ class Component extends PureComponent { this.setState({hostname: e.target.value}) } + handleAlertDismiss() { + console.error("TODO: Dismiss alert.") + // this.setState({hostname: e.target.value}) + } + + getErrorMessage() { + if (this.props.serverError) { + console.log(typeof this.props.serverError) + console.error(this.props.serverError) + return ( + +

Error performing OAuth Discovery

+

{this.props.serverError.toString()}

+

+ or + +

+
+ ) + } + return null + } + render() { + console.log("This state", this.props) + let errorMessage = null + if (this.props.serverError) { + errorMessage = ( +
+

Error performing OAuth Discovery

+

{this.props.serverError}

+
+ ) + } + return ( -
+ - Fill out the hostname of your OAuth server. Will only work if your OAuth server support OAuth Discovery. If not, please enter configuration manually. + Fill out the hostname of your OAuth server. Will only work if your OAuth server support OpenID Connect Discovery. If not, please enter configuration manually. - -
-
+ {this.getErrorMessage()} +
+ +
+ ) } diff --git a/src/components/MainContent.jsx b/src/components/MainContent.jsx index 5697fe73d64f3296c1d7a19b9962e27720064a6b..7c12f00fc0bfe457025e4b349e32162090936662 100644 --- a/src/components/MainContent.jsx +++ b/src/components/MainContent.jsx @@ -1,26 +1,36 @@ import React from 'react' import {Navbar, Nav, NavItem, NavDropdown, MenuItem, Glyphicon, Jumbotron, Button} from 'react-bootstrap' -import {Row, Col, Collapse, FormControl, FormGroup, ControlLabel, HelpBlock} from 'react-bootstrap' +import {Row, Col, Collapse, FormControl, FormGroup, ControlLabel, HelpBlock, PanelGroup, Panel} from 'react-bootstrap' import HostnameController from '../containers/HostnameController' +import ServerConfigController from '../containers/ServerConfigController' +import WhiteBox from './WhiteBox' + + const MainContent = () => (
-

Play with OAuth 2.0

+

Play with OAuth 2.0

Learn more about how OAuth 2.0 works, and explore OAuth protected APIs without entering any code.

- -

Navigate the library of prepared applications, deploy and start using it within few minutes. This application platform is fully automated.

-

- - -

+ + + + + + + + + + + +
diff --git a/src/components/ServerConfigInput.jsx b/src/components/ServerConfigInput.jsx new file mode 100644 index 0000000000000000000000000000000000000000..efa5c743ebaf4043d1446e44a224063f06a0c315 --- /dev/null +++ b/src/components/ServerConfigInput.jsx @@ -0,0 +1,93 @@ +import React, { PureComponent } from 'react' +import {Alert, InputGroup, Navbar, Nav, NavItem, NavDropdown, MenuItem, Glyphicon, Jumbotron, Button} from 'react-bootstrap' +import {Panel, Row, Col, Collapse, FormControl, FormGroup, ControlLabel, HelpBlock} from 'react-bootstrap' +import FontAwesome from 'react-fontawesome' + +import WhiteBox from './WhiteBox' + +class Component extends PureComponent { + + constructor(props) { + super(props) + console.log("--- props", this.props) + this.state = { + clientId: "6233aedf-f08a-4112-9a1b-f33c3cd9b396", + clientSecret: "af85a0f0-2c68-421d-8228-a6c83628de19" + } + } + + authenticateStart() { + console.error("Authenticate") + let config = Object.assign({}, this.props.serverConfig, this.state) + this.props.authenticateStart(config) + } + + updateFieldHandler(field) { + return (e) => { + this.setState({ + [field]: e.target.value + }) + } + } + + + render() { + console.log("X This state", this.props) + console.log("X This state", this.state) + + let authorizationEndpoint = '' + if (this.state.authorizationEndpoint) { + authorizationEndpoint = this.state.authorizationEndpoint + } else if (this.props.serverConfig) { + authorizationEndpoint = this.props.serverConfig.authorization_endpoint + } + + let tokenEndpoint = '' + if (this.state.tokenEndpoint) { + tokenEndpoint = this.state.tokenEndpoint + } else if (this.props.serverConfig) { + tokenEndpoint = this.props.serverConfig.token_endpoint + } + + + let expanded = !!this.props.serverConfig + return ( + +
+

OAuth Authorization endpoint

+ + + + +

OAuth Token endpoint

+ + + + +

Client ID

+ + + + +

Client secret

+ + + + +

Redirect URI

+

When you configure your client, please register the following redirect uri:

+

http://localhost:8080/callback

+ +
+ +
+
+
+ ) + } + +} + +export default Component diff --git a/src/containers/HostnameController.js b/src/containers/HostnameController.js index 871be138dde9c70813ee455fa324f9c9a9b903d2..06c1cef66ce68b7bba80520dbfcd7c5d8cd2dced 100644 --- a/src/containers/HostnameController.js +++ b/src/containers/HostnameController.js @@ -1,11 +1,14 @@ import { connect } from 'react-redux' import HostnameInput from '../components/HostnameInput' -import { discoveryStart } from '../actions/' +// import { discoveryStart } from '../actions/' +import API from '../utils/API' -const mapStateToProps = (state, ownProps) => (state) +const mapStateToProps = (state) => ({ + serverError: state.serverError +}) const mapDispatchToProps = { - discoveryStart + discoveryStart: API.discovery, } const Controller = connect( diff --git a/src/containers/ServerConfigController.js b/src/containers/ServerConfigController.js new file mode 100644 index 0000000000000000000000000000000000000000..fa98b9727b764319d7566779dc753f9d310057e7 --- /dev/null +++ b/src/containers/ServerConfigController.js @@ -0,0 +1,19 @@ +import { connect } from 'react-redux' +import ServerConfigInput from '../components/ServerConfigInput' +// import { discoveryStart } from '../actions/' +import API from '../utils/API' + +const mapStateToProps = (state) => ({ + serverConfig: state.serverConfig +}) + +const mapDispatchToProps = { + authenticateStart: API.authenticate, +} + +const Controller = connect( + mapStateToProps, + mapDispatchToProps +)(ServerConfigInput) + +export default Controller diff --git a/src/index.js b/src/index.js index 80bacede2e5ee43e7f19a06c1d9bfa66344631da..67b12247f4f163cfb3d50a55079c7961b659fe2c 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,9 @@ import React from 'react' import ReactDOM from 'react-dom' import { combineReducers, createStore, applyMiddleware, compose } from 'redux' import { Provider } from 'react-redux' -import thunkMiddleware from 'redux-thunk' +// import promiseMiddleware from 'redux-promise'; +import thunk from 'redux-thunk' + // import { connectRoutes } from 'redux-first-router' // import createHistory from 'history/createBrowserHistory' import reducers from './reducers/' @@ -20,19 +22,15 @@ import '../node_modules/uninett-bootstrap-theme/css/uninett.css' import './css/style.css' // import {packageInstallStart, packageInstallFailed} from './actions/packages' - // const history = createHistory() - // const routerSetup = connectRoutes(history, routesMap, options) let store = createStore( reducers, compose( - // routerSetup.enhancer, applyMiddleware( - // routerSetup.middleware, - thunkMiddleware, + thunk, logger ) ) diff --git a/src/reducers/index.js b/src/reducers/index.js index 8182d2d4360afad05ee650b512968df47d24f18b..2195f70cffc7d51999187a105c7864973dbc80e4 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -2,16 +2,26 @@ import { handleActions } from 'redux-actions'; const reducer = handleActions({ - discoveryStart: (state, action) => ({ - hostname: action.payload - }), - - DECREMENT: (state, action) => ({ - counter: state.counter - action.payload - }) + discovery: { + start: (state, action) => ({ + hostname: action.payload + }), + completed: (state, action) => { + if (action.error) { + return { + serverConfig: null, + serverError: action.payload + } + } + return { + serverConfig: action.payload + } + } + } }, { - hostname: "https://auth.dataporten" + hostname: "https://auth.dataporten.no", + serverConfig: null }); diff --git a/src/routesMap.js b/src/routesMap.js deleted file mode 100644 index ea4ab4333d61e48affdd1be34fdfed18603007e8..0000000000000000000000000000000000000000 --- a/src/routesMap.js +++ /dev/null @@ -1,30 +0,0 @@ -// import { getAllPackages, getPackage } from './actions/packages' -// import { prepareApplication, getAllApplications } from './actions/applications' -// import { login, isAuthenticated, loginAndRedirect } from './actions/auth' - -const routesMap = { - HOME: '/', - // LOGIN: { path: '/login', thunk: login() }, - // PACKAGES: { path: '/', thunk: getAllPackages() }, - // PACKAGE: { path: '/packages/:repo/:packageName/:version', thunk: getPackage() }, - // APPLICATIONS: { path: '/applications', thunk: getAllApplications(), requiresAuth: true }, - // APPLICATION: { path: '/applications/:id', thunk: prepareApplication(), requiresAuth: true }, - // INSTALLATION: { path: '/installation', requiresAuth: true }, -} - -const options = { - onBeforeChange: (dispatch, getState, action) => { - if (!routesMap.hasOwnProperty(action.type)) { - throw new Error("Cannot find routesMap for action type ", action.type) - } - const requiresAuth = routesMap[action.type].requiresAuth - window.scrollTo(0, 0) - // if (requiresAuth) { - // if (!isAuthenticated(getState())) { - // dispatch(loginAndRedirect(action)) - // } - // } - } -} - -export { routesMap, options } diff --git a/src/utils/API.js b/src/utils/API.js index 8b137891791fe96927ad78e64b0aad7bded08bdc..6454873ae1201022eb381825c24b38e9249e0cd1 100644 --- a/src/utils/API.js +++ b/src/utils/API.js @@ -1 +1,49 @@ +import actions from '../actions/' + +// console.error("actions", actions) + +const API = { + + "discovery": function(hostname) { + return dispatch => { + dispatch(actions.discovery.start(hostname)) + + let url = hostname + '/.well-known/openid-configuration' + let config = {"headers": {}} + // config.headers.Authorization = 'Bearer ' + token.access_token + // config.headers["original-token"] = token.access_token + config.method = "GET" + config.mode = "cors" + console.log("About to fetch", config) + + return fetch(url, config).then((response) => { + if (response.ok) { + return response.json() + } + throw Error(response.statusText) + }) + .then((data) => { + console.log("DATA", data) + dispatch(actions.discovery.completed(data)) + }) + .catch((err) => { + console.error("ERROR Fetching API Discovery", err) + dispatch(actions.discovery.completed(err)) + }) + } + }, + + "authenticate": function(config) { + return dispatch => { + console.error("About to save config", config) + dispatch(actions.serverConfig.save(config)) + + console.error("About to authentication") + } + } + + + +} +export default API