Use HOCs for access control

This commit is contained in:
2018-10-08 22:30:11 +03:00
parent 7fe6e954d6
commit b60b66644d
10 changed files with 171 additions and 152 deletions

View File

@@ -4393,7 +4393,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@@ -4758,7 +4759,8 @@
},
"safe-buffer": {
"version": "5.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -4806,6 +4808,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -4844,11 +4847,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
"bundled": true,
"optional": true
}
}
},

View File

@@ -4,12 +4,18 @@ import { BrowserRouter as Router, Route } from 'react-router-dom';
import CssBaseline from '@material-ui/core/CssBaseline';
import Loadable from 'react-loadable';
import Protected from './Protected';
import OnlyUnauth from './OnlyUnauth';
import './Container.css';
import './App.css';
function Loading(props) {
if (props.error) {
return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
return (
<div>
Error! <button onClick={props.retry}>Retry</button>
</div>
);
} else if (props.pastDelay) {
return <div>Loading...</div>;
} else {
@@ -17,29 +23,37 @@ function Loading(props) {
}
}
const LoadableTodosView = Loadable({
loader: () => import('./todolist/TodosView'),
loading: () => Loading,
delay: 1000,
});
const LoadableTodosView = Protected(
Loadable({
loader: () => import('./todolist/TodosView'),
loading: () => Loading,
delay: 1000,
}),
);
const LoadableLoginForm = Loadable({
loader: () => import('./user/LoginForm'),
loading: () => Loading,
delay: 1000,
});
const LoadableLoginForm = OnlyUnauth(
Loadable({
loader: () => import('./user/LoginForm'),
loading: () => Loading,
delay: 1000,
}),
);
const LoadableSignupForm = Loadable({
loader: () => import('./user/SignupForm'),
loading: () => Loading,
delay: 1000,
});
const LoadableSignupForm = OnlyUnauth(
Loadable({
loader: () => import('./user/SignupForm'),
loading: () => Loading,
delay: 1000,
}),
);
const LoadableEditView = Loadable({
loader: () => import('./user/EditForm'),
loading: () => Loading,
delay: 1000,
});
const LoadableEditView = Protected(
Loadable({
loader: () => import('./user/EditForm'),
loading: () => Loading,
delay: 1000,
}),
);
export default class App extends React.PureComponent {
componentDidMount() {

View File

@@ -0,0 +1,25 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
export default function OnlyUnauth(WrappedComponent) {
function Component({ loggedIn }) {
return loggedIn ? <Redirect to="/" /> : <WrappedComponent />;
}
Component.propTypes = {
loggedIn: PropTypes.bool.isRequired,
};
function mapStateToProps(state) {
return {
loggedIn: state.user.user !== undefined && state.user.user !== null,
};
}
return connect(
mapStateToProps,
null,
)(Component);
}

View File

@@ -0,0 +1,25 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
export default function Protected(WrappedComponent) {
function Component({ loggedIn }) {
return loggedIn ? <WrappedComponent /> : <Redirect to="/login" />;
}
Component.propTypes = {
loggedIn: PropTypes.bool.isRequired,
};
function mapStateToProps(state) {
return {
loggedIn: state.user.user !== undefined && state.user.user !== null,
};
}
return connect(
mapStateToProps,
null,
)(Component);
}

View File

@@ -11,23 +11,6 @@ import Header from '../Header';
import Filters from '../filters/Filters';
class Todos extends React.PureComponent {
componentDidMount() {
this.checkLogin();
}
componentDidUpdate() {
this.checkLogin();
}
checkLogin() {
const { user, history } = this.props;
//If user isn't logged in
//and isn't in progress of logging in
//show login page
if (!user.user && !user.dirty) {
history.replace('/login');
}
}
render() {
const { list } = this.props;
return (

View File

@@ -28,9 +28,6 @@ function EditForm({
history,
reset,
}) {
if (!user.user) {
history.push('/');
}
if (user.user && user.editSuccess) {
reset();
history.push('/');

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import { ButtonBase, Button } from '@material-ui/core';
@@ -22,13 +21,6 @@ class LoginForm extends React.PureComponent {
}
}
componentDidUpdate() {
const { user, history } = this.props;
if (user.user) {
history.push('/');
}
}
render() {
const { resetUser, history, handleSubmit, user, onLogin } = this.props;
return (
@@ -123,10 +115,8 @@ export default reduxForm({
password: '',
},
})(
withRouter(
connect(
mapStateToProps,
mapDispatchToProps,
)(LoginForm),
),
connect(
mapStateToProps,
mapDispatchToProps,
)(LoginForm),
);

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import { ButtonBase, Button } from '@material-ui/core';
@@ -21,9 +20,6 @@ function validate(values) {
}
function SignupForm({ handleSubmit, onSignup, user, history, resetUser }) {
if (user.user) {
history.push('/');
}
return (
<React.Fragment>
<div id="user-header">
@@ -112,10 +108,8 @@ export default reduxForm({
},
validate,
})(
withRouter(
connect(
mapStateToProps,
mapDispatchToProps,
)(SignupForm),
),
connect(
mapStateToProps,
mapDispatchToProps,
)(SignupForm),
);