mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 01:18:42 +00:00
Authenticated routes (#207)
* Redirects authenticated routes to /login when user not authenticated or loading * Redirect to login when call to get user fails
This commit is contained in:
parent
d2f1e749ab
commit
2f5ee8607d
4 changed files with 80 additions and 9 deletions
|
|
@ -1,12 +1,44 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { isEqual } from 'lodash';
|
||||
import { push } from 'react-router-redux';
|
||||
import paths from '../../router/paths';
|
||||
|
||||
export class AuthenticatedRoutes extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.element,
|
||||
dispatch: PropTypes.func,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
user: PropTypes.object,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
const { loading, user } = this.props;
|
||||
const { redirectToLogin } = this;
|
||||
|
||||
if (!loading && !user) return redirectToLogin();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (isEqual(this.props, nextProps)) return false;
|
||||
|
||||
const { loading, user } = nextProps;
|
||||
const { redirectToLogin } = this;
|
||||
|
||||
if (!loading && !user) return redirectToLogin();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
redirectToLogin = () => {
|
||||
const { dispatch } = this.props;
|
||||
const { LOGIN } = paths;
|
||||
|
||||
return dispatch(push(LOGIN));
|
||||
}
|
||||
|
||||
render () {
|
||||
const { children, user } = this.props;
|
||||
|
||||
|
|
@ -21,9 +53,9 @@ export class AuthenticatedRoutes extends Component {
|
|||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const { user } = state.auth;
|
||||
const { loading, user } = state.auth;
|
||||
|
||||
return { user };
|
||||
return { loading, user };
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(AuthenticatedRoutes);
|
||||
|
|
|
|||
|
|
@ -6,16 +6,35 @@ import AuthenticatedRoutes from './index';
|
|||
import helpers from '../../test/helpers';
|
||||
|
||||
describe('AuthenticatedRoutes - component', () => {
|
||||
const redirectToLoginAction = {
|
||||
type: '@@router/CALL_HISTORY_METHOD',
|
||||
payload: {
|
||||
method: 'push',
|
||||
args: ['/login'],
|
||||
},
|
||||
};
|
||||
const renderedText = 'This text was rendered';
|
||||
const storeWithUser = {
|
||||
auth: {
|
||||
loading: false,
|
||||
user: {
|
||||
id: 1,
|
||||
email: 'hi@thegnar.co',
|
||||
},
|
||||
},
|
||||
};
|
||||
const storeWithoutUser = { auth: {} };
|
||||
const storeWithoutUser = {
|
||||
auth: {
|
||||
loading: false,
|
||||
user: null,
|
||||
},
|
||||
};
|
||||
const storeLoadingUser = {
|
||||
auth: {
|
||||
loading: true,
|
||||
user: null,
|
||||
},
|
||||
};
|
||||
|
||||
it('renders if there is a user in state', () => {
|
||||
const { reduxMockStore } = helpers;
|
||||
|
|
@ -31,7 +50,7 @@ describe('AuthenticatedRoutes - component', () => {
|
|||
expect(component.text()).toEqual(renderedText);
|
||||
});
|
||||
|
||||
it('does not render without a user in state', () => {
|
||||
it('redirects to login without a user', () => {
|
||||
const { reduxMockStore } = helpers;
|
||||
const mockStore = reduxMockStore(storeWithoutUser);
|
||||
const component = mount(
|
||||
|
|
@ -42,6 +61,22 @@ describe('AuthenticatedRoutes - component', () => {
|
|||
</Provider>
|
||||
);
|
||||
|
||||
expect(mockStore.getActions()).toInclude(redirectToLoginAction);
|
||||
expect(component.html()).toNotExist();
|
||||
});
|
||||
|
||||
it('does not redirect to login if the user is loading', () => {
|
||||
const { reduxMockStore } = helpers;
|
||||
const mockStore = reduxMockStore(storeLoadingUser);
|
||||
const component = mount(
|
||||
<Provider store={mockStore}>
|
||||
<AuthenticatedRoutes>
|
||||
<div>{renderedText}</div>
|
||||
</AuthenticatedRoutes>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
expect(mockStore.getActions()).toNotInclude(redirectToLoginAction);
|
||||
expect(component.html()).toNotExist();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
import { push } from 'react-router-redux';
|
||||
import kolide from '../../kolide';
|
||||
import { LOGIN_SUCCESS, LOGOUT_SUCCESS } from '../nodes/auth/actions';
|
||||
import { LOGIN_FAILURE, LOGIN_SUCCESS, LOGOUT_SUCCESS } from '../nodes/auth/actions';
|
||||
import local from '../../utilities/local';
|
||||
import paths from '../../router/paths';
|
||||
|
||||
const authMiddleware = store => next => action => {
|
||||
if (action.type === LOGIN_SUCCESS) {
|
||||
const { token } = action.payload.data;
|
||||
const { type, payload } = action;
|
||||
|
||||
if (type === LOGIN_SUCCESS) {
|
||||
const { token } = payload.data;
|
||||
|
||||
if (token) {
|
||||
local.setItem('auth_token', token);
|
||||
|
|
@ -15,7 +17,7 @@ const authMiddleware = store => next => action => {
|
|||
}
|
||||
}
|
||||
|
||||
if (action.type === LOGOUT_SUCCESS) {
|
||||
if (type === LOGOUT_SUCCESS || type === LOGIN_FAILURE) {
|
||||
const { LOGIN } = paths;
|
||||
|
||||
local.clear();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ const routes = (
|
|||
<Provider store={store}>
|
||||
<Router history={history}>
|
||||
<Route path="/" component={radium(App)}>
|
||||
<IndexRoute component={radium(HomePage)} />
|
||||
<Route component={radium(LoginRoutes)}>
|
||||
<Route path="forgot_password" component={radium(ForgotPasswordPage)} />
|
||||
<Route path="login" component={radium(LoginPage)} />
|
||||
|
|
@ -30,6 +29,9 @@ const routes = (
|
|||
<Route path="logout" component={radium(LogoutPage)} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route component={AuthenticatedRoutes}>
|
||||
<IndexRoute component={radium(HomePage)} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Router>
|
||||
</Provider>
|
||||
|
|
|
|||
Loading…
Reference in a new issue