diff --git a/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.jsx b/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.jsx index 151e9ffdb0..7f4ad1d5d4 100644 --- a/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.jsx +++ b/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.jsx @@ -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); diff --git a/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.tests.jsx b/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.tests.jsx index 85fa8e100a..55dccfa839 100644 --- a/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.tests.jsx +++ b/frontend/components/AuthenticatedRoutes/AuthenticatedRoutes.tests.jsx @@ -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', () => { ); + 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( + + +
{renderedText}
+
+
+ ); + + expect(mockStore.getActions()).toNotInclude(redirectToLoginAction); expect(component.html()).toNotExist(); }); }); diff --git a/frontend/redux/middlewares/auth.js b/frontend/redux/middlewares/auth.js index 1d5cb2f538..e84fe8268c 100644 --- a/frontend/redux/middlewares/auth.js +++ b/frontend/redux/middlewares/auth.js @@ -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(); diff --git a/frontend/router/index.jsx b/frontend/router/index.jsx index f0cb0d886d..1a786edfcc 100644 --- a/frontend/router/index.jsx +++ b/frontend/router/index.jsx @@ -20,7 +20,6 @@ const routes = ( - @@ -30,6 +29,9 @@ const routes = ( + + +