mirror of
https://github.com/status-im/embark-area-51.git
synced 2025-02-01 18:06:11 +00:00
Add ability to logout
This commit is contained in:
parent
609ba0f1a1
commit
94aae19e0c
45
embark-ui/package-lock.json
generated
45
embark-ui/package-lock.json
generated
@ -155,6 +155,14 @@
|
|||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ansi-to-html": {
|
||||||
|
"version": "0.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.6.tgz",
|
||||||
|
"integrity": "sha512-90M/2sZna3OsoOEbSyXK46poFnlClBC53Rx6etNKQK7iShsX5fI5E/M9Ld6FurtLaxAWLuAPi0Jp8p3y5oAkxg==",
|
||||||
|
"requires": {
|
||||||
|
"entities": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"anymatch": {
|
"anymatch": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
|
||||||
@ -434,6 +442,11 @@
|
|||||||
"postcss-value-parser": "^3.2.3"
|
"postcss-value-parser": "^3.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"autoscroll-react": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/autoscroll-react/-/autoscroll-react-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-HOiwy9GGTSk9WZwEPd+FwNLLZ17o5wkjAtAb+RtQUr/2J1PT2KRG+OI6LoGtfY5EwWvQKAbSsjkgLvLhItscSg=="
|
||||||
|
},
|
||||||
"aws-sign2": {
|
"aws-sign2": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
@ -7106,6 +7119,22 @@
|
|||||||
"prepend-http": "^1.0.0",
|
"prepend-http": "^1.0.0",
|
||||||
"query-string": "^4.1.0",
|
"query-string": "^4.1.0",
|
||||||
"sort-keys": "^1.0.0"
|
"sort-keys": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"query-string": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||||
|
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"strict-uri-encode": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strict-uri-encode": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm-run-path": {
|
"npm-run-path": {
|
||||||
@ -8826,12 +8855,12 @@
|
|||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||||
},
|
},
|
||||||
"query-string": {
|
"query-string": {
|
||||||
"version": "4.3.4",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz",
|
||||||
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
"integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"object-assign": "^4.1.0",
|
"decode-uri-component": "^0.2.0",
|
||||||
"strict-uri-encode": "^1.0.0"
|
"strict-uri-encode": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"querystring": {
|
"querystring": {
|
||||||
@ -10235,9 +10264,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strict-uri-encode": {
|
"strict-uri-encode": {
|
||||||
"version": "1.1.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
|
||||||
},
|
},
|
||||||
"string-length": {
|
"string-length": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -13,11 +13,32 @@ function action(type, payload = {}) {
|
|||||||
return {type, ...payload};
|
return {type, ...payload};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AUTHORIZE = createRequestTypes('AUTHORIZE');
|
export const AUTHENTICATE = createRequestTypes('AUTHENTICATE');
|
||||||
export const authorize = {
|
export const authenticate = {
|
||||||
request: (token, callback) => action(AUTHORIZE[REQUEST], {token, callback}),
|
request: (token) => action(AUTHENTICATE[REQUEST], {token}),
|
||||||
success: () => action(AUTHORIZE[SUCCESS]),
|
success: (_result, payload) => action(AUTHENTICATE[SUCCESS], {token: payload.token}),
|
||||||
failure: (error) => action(AUTHORIZE[FAILURE], {error})
|
failure: (error) => action(AUTHENTICATE[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FETCH_TOKEN = createRequestTypes('FETCH_TOKEN');
|
||||||
|
export const fetchToken = {
|
||||||
|
request: () => action(FETCH_TOKEN[REQUEST]),
|
||||||
|
success: (token) => action(FETCH_TOKEN[SUCCESS], {token}),
|
||||||
|
failure: () => action(FETCH_TOKEN[FAILURE])
|
||||||
|
};
|
||||||
|
|
||||||
|
export const POST_TOKEN = createRequestTypes('POST_TOKEN');
|
||||||
|
export const postToken = {
|
||||||
|
request: (token) => action(POST_TOKEN[REQUEST], {token}),
|
||||||
|
success: (token) => action(POST_TOKEN[SUCCESS], {token}),
|
||||||
|
failure: () => action(POST_TOKEN[FAILURE])
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LOGOUT = createRequestTypes('LOGOUT');
|
||||||
|
export const logout = {
|
||||||
|
request: () => action(LOGOUT[REQUEST]),
|
||||||
|
success: () => action(LOGOUT[SUCCESS]),
|
||||||
|
failure: () => action(LOGOUT[FAILURE])
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ACCOUNTS = createRequestTypes('ACCOUNTS');
|
export const ACCOUNTS = createRequestTypes('ACCOUNTS');
|
||||||
@ -226,20 +247,6 @@ export const saveCurrentFile = {
|
|||||||
failure: () => action(SAVE_CURRENT_FILE[FAILURE])
|
failure: () => action(SAVE_CURRENT_FILE[FAILURE])
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GET_TOKEN = createRequestTypes('TOKEN');
|
|
||||||
export const getToken = {
|
|
||||||
request: (callback) => action(GET_TOKEN[REQUEST], {callback}),
|
|
||||||
success: (token) => action(GET_TOKEN[SUCCESS], {token}),
|
|
||||||
failure: () => action(GET_TOKEN[FAILURE])
|
|
||||||
};
|
|
||||||
|
|
||||||
export const POST_TOKEN = createRequestTypes('POST_TOKEN');
|
|
||||||
export const postToken = {
|
|
||||||
request: (token) => action(POST_TOKEN[REQUEST], {token}),
|
|
||||||
success: (token) => action(POST_TOKEN[SUCCESS], {token}),
|
|
||||||
failure: () => action(POST_TOKEN[FAILURE])
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GAS_ORACLE = createRequestTypes('GAS_ORACLE');
|
export const GAS_ORACLE = createRequestTypes('GAS_ORACLE');
|
||||||
export const gasOracle = {
|
export const gasOracle = {
|
||||||
request: () => action(GAS_ORACLE[REQUEST]),
|
request: () => action(GAS_ORACLE[REQUEST]),
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
import PropTypes from "prop-types";
|
|
||||||
import React from 'react';
|
|
||||||
import {Page, Alert, Form, Button} from "tabler-react";
|
|
||||||
|
|
||||||
const AuthError = ({error}) => {
|
|
||||||
return <Page.Content>
|
|
||||||
<Alert type="danger">
|
|
||||||
{error}
|
|
||||||
</Alert>
|
|
||||||
<Form>
|
|
||||||
<Form.Input name="token" label="Token" placeholder="Enter Token"/>
|
|
||||||
<Button type="submit" color="primary">
|
|
||||||
Authorize
|
|
||||||
</Button>
|
|
||||||
</Form>
|
|
||||||
</Page.Content>;
|
|
||||||
};
|
|
||||||
|
|
||||||
AuthError.propTypes = {
|
|
||||||
error: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthError;
|
|
||||||
|
|
@ -13,37 +13,49 @@ const navBarItems = [
|
|||||||
{value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: NavLink}
|
{value: "Documentation", to: "/embark/documentation", icon: "file-text", LinkComponent: NavLink}
|
||||||
];
|
];
|
||||||
|
|
||||||
const Layout = (props) => (
|
const Layout = ({children, logout}) => (
|
||||||
<Site.Wrapper
|
<Site.Wrapper
|
||||||
headerProps={{
|
headerProps={{
|
||||||
href: "/embark",
|
href: "/embark",
|
||||||
alt: "Embark",
|
alt: "Embark",
|
||||||
imageURL: logo,
|
imageURL: logo,
|
||||||
navItems: (
|
navItems: (
|
||||||
<Nav.Item type="div" className="d-none d-md-flex">
|
<React.Fragment>
|
||||||
<Button
|
<Nav.Item type="div" className="d-none d-md-flex">
|
||||||
href="https://github.com/embark-framework/embark"
|
<Button
|
||||||
target="_blank"
|
href="https://github.com/embark-framework/embark"
|
||||||
outline
|
target="_blank"
|
||||||
size="sm"
|
outline
|
||||||
RootComponent="a"
|
size="sm"
|
||||||
color="primary"
|
RootComponent="a"
|
||||||
>
|
color="primary"
|
||||||
Source code
|
>
|
||||||
</Button>
|
Source code
|
||||||
</Nav.Item>
|
</Button>
|
||||||
|
</Nav.Item>
|
||||||
|
<Nav.Item type="div" className="d-none d-md-flex">
|
||||||
|
<Button
|
||||||
|
outline
|
||||||
|
onClick={logout}
|
||||||
|
size="sm"
|
||||||
|
color="danger">
|
||||||
|
Logout
|
||||||
|
</Button>
|
||||||
|
</Nav.Item>
|
||||||
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
navProps={{itemsObjects: navBarItems}}
|
navProps={{itemsObjects: navBarItems}}
|
||||||
>
|
>
|
||||||
<Container>
|
<Container>
|
||||||
{props.children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</Site.Wrapper>
|
</Site.Wrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
Layout.propTypes = {
|
Layout.propTypes = {
|
||||||
children: PropTypes.element
|
children: PropTypes.element,
|
||||||
|
logout: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Layout;
|
export default Layout;
|
||||||
|
47
embark-ui/src/components/Unauthenticated.js
Normal file
47
embark-ui/src/components/Unauthenticated.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
import React from 'react';
|
||||||
|
import {Page, Alert, Form, Button} from "tabler-react";
|
||||||
|
|
||||||
|
class Unauthenticated extends React.Component {
|
||||||
|
constructor(props){
|
||||||
|
super(props);
|
||||||
|
this.state = { token: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTokenChange(event){
|
||||||
|
this.setState({token: event.target.value});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.props.authenticate(this.state.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Page.Content>
|
||||||
|
{this.props.error && <Alert type="danger">
|
||||||
|
{this.props.error}
|
||||||
|
</Alert>}
|
||||||
|
<Form onSubmit={(e) => this.handleSubmit(e)}>
|
||||||
|
<Form.Input name="token"
|
||||||
|
label="Token"
|
||||||
|
value={this.state.token}
|
||||||
|
onChange={(e) => this.handleTokenChange(e)}
|
||||||
|
placeholder="Enter Token"/>
|
||||||
|
<Button type="submit" color="primary">
|
||||||
|
Authenticate
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
</Page.Content>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unauthenticated.propTypes = {
|
||||||
|
authenticate: PropTypes.func,
|
||||||
|
error: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Unauthenticated;
|
||||||
|
|
@ -4,64 +4,72 @@ import React, {Component} from 'react';
|
|||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
|
|
||||||
import routes from '../routes';
|
import routes from '../routes';
|
||||||
import AuthError from '../components/AuthError';
|
import Unauthenticated from '../components/Unauthenticated';
|
||||||
|
import Layout from "../components/Layout";
|
||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
initBlockHeader,
|
initBlockHeader,
|
||||||
authorize, getToken, postToken,
|
authenticate, fetchToken, logout,
|
||||||
processes as processesAction,
|
processes as processesAction,
|
||||||
versions as versionsAction,
|
versions as versionsAction,
|
||||||
plugins as pluginsAction
|
plugins as pluginsAction
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
|
|
||||||
|
import { getToken, getAuthenticationError } from '../reducers/selectors';
|
||||||
|
|
||||||
class AppContainer extends Component {
|
class AppContainer extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
authenticateError: null
|
|
||||||
};
|
|
||||||
|
|
||||||
this.checkToken();
|
this.queryStringAuthenticate();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkToken() {
|
queryStringAuthenticate() {
|
||||||
if (this.props.location.search) {
|
if (!this.props.location.search) {
|
||||||
const token = queryString.parse(this.props.location.search).token;
|
return;
|
||||||
this.props.postToken(token);
|
|
||||||
return this.props.authorize(token, this.authCallback.bind(this));
|
|
||||||
}
|
}
|
||||||
this.props.getToken((err, token) => {
|
const token = queryString.parse(this.props.location.search).token;
|
||||||
this.props.authorize(token, this.authCallback.bind(this));
|
if (token === this.props.token) {
|
||||||
});
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
authCallback(err) {
|
|
||||||
if (err) {
|
|
||||||
return this.setState({authenticateError: err});
|
|
||||||
}
|
}
|
||||||
this.setState({authenticateError: null});
|
this.props.authenticate(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.initBlockHeader();
|
this.props.fetchToken();
|
||||||
this.props.fetchProcesses();
|
}
|
||||||
this.props.fetchVersions();
|
|
||||||
this.props.fetchPlugins();
|
componentDidUpdate(){
|
||||||
|
if (this.props.token) {
|
||||||
|
this.props.authenticate(this.props.token);
|
||||||
|
this.props.initBlockHeader();
|
||||||
|
this.props.fetchProcesses();
|
||||||
|
this.props.fetchVersions();
|
||||||
|
this.props.fetchPlugins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldRenderUnauthenticated() {
|
||||||
|
return this.props.authenticationError || !this.props.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.authenticateError) {
|
return (
|
||||||
return <AuthError error={this.state.authenticateError}/>;
|
<Layout logout={this.props.logout}>
|
||||||
}
|
{this.shouldRenderUnauthenticated() ? <Unauthenticated authenticate={this.props.authenticate}
|
||||||
return (<React.Fragment>{routes}</React.Fragment>);
|
error={this.props.authenticationError} /> : <React.Fragment>{routes}</React.Fragment>}
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppContainer.propTypes = {
|
AppContainer.propTypes = {
|
||||||
authorize: PropTypes.func,
|
token: PropTypes.string,
|
||||||
getToken: PropTypes.func,
|
authenticationError: PropTypes.string,
|
||||||
postToken: PropTypes.func,
|
authenticate: PropTypes.func,
|
||||||
|
logout: PropTypes.func,
|
||||||
|
fetchToken: PropTypes.func,
|
||||||
initBlockHeader: PropTypes.func,
|
initBlockHeader: PropTypes.func,
|
||||||
fetchProcesses: PropTypes.func,
|
fetchProcesses: PropTypes.func,
|
||||||
fetchPlugins: PropTypes.func,
|
fetchPlugins: PropTypes.func,
|
||||||
@ -69,13 +77,20 @@ AppContainer.propTypes = {
|
|||||||
location: PropTypes.object
|
location: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
token: getToken(state),
|
||||||
|
authenticationError: getAuthenticationError(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default withRouter(connect(
|
export default withRouter(connect(
|
||||||
null,
|
mapStateToProps,
|
||||||
{
|
{
|
||||||
initBlockHeader,
|
initBlockHeader,
|
||||||
authorize: authorize.request,
|
authenticate: authenticate.request,
|
||||||
getToken: getToken.request,
|
logout: logout.request,
|
||||||
postToken: postToken.request,
|
fetchToken: fetchToken.request,
|
||||||
fetchProcesses: processesAction.request,
|
fetchProcesses: processesAction.request,
|
||||||
fetchVersions: versionsAction.request,
|
fetchVersions: versionsAction.request,
|
||||||
fetchPlugins: pluginsAction.request
|
fetchPlugins: pluginsAction.request
|
||||||
|
@ -6,7 +6,6 @@ import {Provider} from 'react-redux';
|
|||||||
import "tabler-react/dist/Tabler.css";
|
import "tabler-react/dist/Tabler.css";
|
||||||
import "./general.css";
|
import "./general.css";
|
||||||
import "./slider.css";
|
import "./slider.css";
|
||||||
import Layout from "./components/Layout";
|
|
||||||
|
|
||||||
import AppContainer from './containers/AppContainer';
|
import AppContainer from './containers/AppContainer';
|
||||||
import history from "./history";
|
import history from "./history";
|
||||||
@ -18,9 +17,7 @@ const store = configureStore();
|
|||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
<Layout>
|
<AppContainer/>
|
||||||
<AppContainer/>
|
|
||||||
</Layout>
|
|
||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {combineReducers} from 'redux';
|
import {combineReducers} from 'redux';
|
||||||
import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES} from "../actions";
|
import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES, LOGOUT, AUTHENTICATE} from "../actions";
|
||||||
|
|
||||||
const BN_FACTOR = 10000;
|
const BN_FACTOR = 10000;
|
||||||
const voidAddress = '0x0000000000000000000000000000000000000000';
|
const voidAddress = '0x0000000000000000000000000000000000000000';
|
||||||
@ -83,6 +83,9 @@ const filtrer = {
|
|||||||
},
|
},
|
||||||
gasOracleStats: function(stat, index, _self) {
|
gasOracleStats: function(stat, index, _self) {
|
||||||
return index === 0; // Only keep last one
|
return index === 0; // Only keep last one
|
||||||
|
},
|
||||||
|
versions: function(version, index, self) {
|
||||||
|
return index === self.findIndex((v) => v.value === version.value && v.name === version.name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,8 +118,8 @@ function entities(state = entitiesDefaultState, action) {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorMessage(state = null, action) {
|
function errorMessage(_state = null, action) {
|
||||||
return action.error || state;
|
return action.error || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorEntities(state = {}, action) {
|
function errorEntities(state = {}, action) {
|
||||||
@ -146,8 +149,16 @@ function compilingContract(state = false, action) {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function token(state = null, action) {
|
function authentication(state = {}, action) {
|
||||||
return (action.token) ? action.token : state;
|
if (action.type === LOGOUT[SUCCESS]) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === AUTHENTICATE[FAILURE]) {
|
||||||
|
return {error: action.error};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (action.token) ? {token: action.token} : state;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
@ -156,7 +167,7 @@ const rootReducer = combineReducers({
|
|||||||
compilingContract,
|
compilingContract,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
errorEntities,
|
errorEntities,
|
||||||
token
|
authentication
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
import {last} from '../utils/utils';
|
import {last} from '../utils/utils';
|
||||||
|
|
||||||
|
export function getToken(state) {
|
||||||
|
return state.authentication.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAuthenticationError(state) {
|
||||||
|
return state.authentication.error;
|
||||||
|
}
|
||||||
|
|
||||||
export function getAccounts(state) {
|
export function getAccounts(state) {
|
||||||
return state.entities.accounts;
|
return state.entities.accounts;
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,10 @@ import * as api from '../services/api';
|
|||||||
import * as storage from '../services/storage';
|
import * as storage from '../services/storage';
|
||||||
import {eventChannel} from 'redux-saga';
|
import {eventChannel} from 'redux-saga';
|
||||||
import {all, call, fork, put, takeEvery, take, select} from 'redux-saga/effects';
|
import {all, call, fork, put, takeEvery, take, select} from 'redux-saga/effects';
|
||||||
|
import {getToken} from '../reducers/selectors';
|
||||||
|
|
||||||
function *doRequest(entity, serviceFn, payload) {
|
function *doRequest(entity, serviceFn, payload) {
|
||||||
payload.token = yield select(function (state) {
|
payload.token = yield select(getToken);
|
||||||
return state.token;
|
|
||||||
});
|
|
||||||
const {response, error} = yield call(serviceFn, payload);
|
const {response, error} = yield call(serviceFn, payload);
|
||||||
if(response) {
|
if(response) {
|
||||||
yield put(entity.success(response.data, payload));
|
yield put(entity.success(response.data, payload));
|
||||||
@ -42,13 +41,14 @@ export const fetchFile = doRequest.bind(null, actions.file, api.fetchFile);
|
|||||||
export const postFile = doRequest.bind(null, actions.saveFile, api.postFile);
|
export const postFile = doRequest.bind(null, actions.saveFile, api.postFile);
|
||||||
export const deleteFile = doRequest.bind(null, actions.removeFile, api.deleteFile);
|
export const deleteFile = doRequest.bind(null, actions.removeFile, api.deleteFile);
|
||||||
export const fetchEthGas = doRequest.bind(null, actions.gasOracle, api.getEthGasAPI);
|
export const fetchEthGas = doRequest.bind(null, actions.gasOracle, api.getEthGasAPI);
|
||||||
export const authorize = doRequest.bind(null, actions.authorize, api.authorize);
|
export const authenticate = doRequest.bind(null, actions.authenticate, api.authenticate);
|
||||||
|
|
||||||
export const fetchCurrentFile = doRequest.bind(null, actions.currentFile, storage.fetchCurrentFile);
|
export const fetchCurrentFile = doRequest.bind(null, actions.currentFile, storage.fetchCurrentFile);
|
||||||
export const postCurrentFile = doRequest.bind(null, actions.saveCurrentFile, storage.postCurrentFile);
|
export const postCurrentFile = doRequest.bind(null, actions.saveCurrentFile, storage.postCurrentFile);
|
||||||
export const deleteCurrentFile = doRequest.bind(null, null, storage.deleteCurrentFile);
|
export const deleteCurrentFile = doRequest.bind(null, null, storage.deleteCurrentFile);
|
||||||
export const fetchToken = doRequest.bind(null, actions.getToken, storage.fetchToken);
|
export const fetchToken = doRequest.bind(null, actions.fetchToken, storage.fetchToken);
|
||||||
export const postToken = doRequest.bind(null, actions.postToken, storage.postToken);
|
export const postToken = doRequest.bind(null, actions.postToken, storage.postToken);
|
||||||
|
export const logout = doRequest.bind(null, actions.logout, storage.logout);
|
||||||
|
|
||||||
|
|
||||||
export function *watchFetchTransaction() {
|
export function *watchFetchTransaction() {
|
||||||
@ -172,20 +172,24 @@ export function *watchPostCurrentFile() {
|
|||||||
yield takeEvery(actions.SAVE_CURRENT_FILE[actions.REQUEST], postCurrentFile);
|
yield takeEvery(actions.SAVE_CURRENT_FILE[actions.REQUEST], postCurrentFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchFetchToken() {
|
|
||||||
yield takeEvery(actions.GET_TOKEN[actions.REQUEST], fetchToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function *watchPostToken() {
|
|
||||||
yield takeEvery(actions.POST_TOKEN[actions.REQUEST], postToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function *watchFetchEthGas() {
|
export function *watchFetchEthGas() {
|
||||||
yield takeEvery(actions.GAS_ORACLE[actions.REQUEST], fetchEthGas);
|
yield takeEvery(actions.GAS_ORACLE[actions.REQUEST], fetchEthGas);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchAuthenticate() {
|
export function *watchAuthenticate() {
|
||||||
yield takeEvery(actions.AUTHORIZE[actions.REQUEST], authorize);
|
yield takeEvery(actions.AUTHENTICATE[actions.REQUEST], authenticate);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchAuthenticateSuccess() {
|
||||||
|
yield takeEvery(actions.AUTHENTICATE[actions.SUCCESS], postToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchFetchToken() {
|
||||||
|
yield takeEvery(actions.FETCH_TOKEN[actions.REQUEST], fetchToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchLogout() {
|
||||||
|
yield takeEvery(actions.LOGOUT[actions.REQUEST], logout);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createChannel(socket) {
|
function createChannel(socket) {
|
||||||
@ -297,9 +301,10 @@ export default function *root() {
|
|||||||
fork(watchFetchCurrentFile),
|
fork(watchFetchCurrentFile),
|
||||||
fork(watchPostCurrentFile),
|
fork(watchPostCurrentFile),
|
||||||
fork(watchFetchToken),
|
fork(watchFetchToken),
|
||||||
fork(watchPostToken),
|
|
||||||
fork(watchFetchEthGas),
|
fork(watchFetchEthGas),
|
||||||
fork(watchAuthenticate),
|
fork(watchAuthenticate),
|
||||||
|
fork(watchAuthenticateSuccess),
|
||||||
|
fork(watchLogout),
|
||||||
fork(watchListenGasOracle)
|
fork(watchListenGasOracle)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -137,8 +137,8 @@ export function deleteFile(payload) {
|
|||||||
return destroy('/file', {params: payload, token: payload.token});
|
return destroy('/file', {params: payload, token: payload.token});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function authorize() {
|
export function authenticate() {
|
||||||
return post('/authorize', ...arguments);
|
return post('/authenticate', ...arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO token for WS?
|
// TODO token for WS?
|
||||||
|
@ -18,18 +18,23 @@ export function deleteCurrentFile() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function postToken(data) {
|
export function postToken({token}) {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
localStorage.setItem('token', data.token);
|
localStorage.setItem('token', token);
|
||||||
resolve({response: {data: data.token}});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fetchToken({callback}) {
|
|
||||||
callback = callback || function(){};
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
const token = localStorage.getItem('token');
|
|
||||||
callback(null, token);
|
|
||||||
resolve({response: {data: token}});
|
resolve({response: {data: token}});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchToken() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
resolve({response: {data: token}});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logout() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
localStorage.clear();
|
||||||
|
resolve({response: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -16,10 +16,10 @@ class Authenticator {
|
|||||||
registerCalls() {
|
registerCalls() {
|
||||||
this.embark.registerAPICall(
|
this.embark.registerAPICall(
|
||||||
'post',
|
'post',
|
||||||
'/embark-api/authorize',
|
'/embark-api/authenticate',
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
if (req.body.token !== this.authToken) {
|
if (req.body.token !== this.authToken) {
|
||||||
this.logger.warn(__('Someone tried and failed to authorize to the backend'));
|
this.logger.warn(__('Someone tried and failed to authenticate to the backend'));
|
||||||
this.logger.warn(__('- User-Agent: %s', req.headers['user-agent']));
|
this.logger.warn(__('- User-Agent: %s', req.headers['user-agent']));
|
||||||
this.logger.warn(__('- Referer: %s', req.headers.referer));
|
this.logger.warn(__('- Referer: %s', req.headers.referer));
|
||||||
return res.send(ERROR_OBJ);
|
return res.send(ERROR_OBJ);
|
||||||
@ -32,7 +32,7 @@ class Authenticator {
|
|||||||
return {
|
return {
|
||||||
match: () => cmd === "token",
|
match: () => cmd === "token",
|
||||||
process: (callback) => {
|
process: (callback) => {
|
||||||
callback(null, __('Your authorisation token: %s', this.authToken));
|
callback(null, __('Your authentication token: %s', this.authToken));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user