2015-10-06 18:28:15 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
import React from 'react';
|
|
|
|
|
2015-12-08 10:23:37 +01:00
|
|
|
import UserStore from '../../stores/user_store';
|
2015-10-06 18:28:15 +02:00
|
|
|
|
2016-06-08 13:11:16 +02:00
|
|
|
import withContext from '../context/with_context';
|
2016-06-08 14:54:05 +02:00
|
|
|
import { currentUserShape, locationShape, routerShape, whitelabelShape } from '../prop_types';
|
2016-06-06 18:52:05 +02:00
|
|
|
|
2015-12-08 10:23:37 +01:00
|
|
|
import AppConstants from '../../constants/application_constants';
|
2015-10-09 13:51:21 +02:00
|
|
|
|
|
|
|
|
2016-06-07 14:55:04 +02:00
|
|
|
const { bool, object } = React.PropTypes;
|
2015-10-12 17:57:23 +02:00
|
|
|
const WHEN_ENUM = ['loggedIn', 'loggedOut'];
|
2015-10-06 18:28:15 +02:00
|
|
|
|
2015-10-09 15:51:03 +02:00
|
|
|
/**
|
2015-12-08 11:17:04 +01:00
|
|
|
* Redirects the user conditionally according to his authentication
|
2015-10-09 15:51:03 +02:00
|
|
|
*
|
|
|
|
* @param {enum/string} options.when ('loggedIn' || 'loggedOut')
|
|
|
|
*/
|
2016-02-08 10:41:36 +01:00
|
|
|
export function AuthRedirect({ to, when }) {
|
2015-10-12 17:57:23 +02:00
|
|
|
// validate `when`, must be contained in `WHEN_ENUM`.
|
|
|
|
// Throw an error otherwise.
|
2016-01-11 17:52:32 +01:00
|
|
|
if (WHEN_ENUM.indexOf(when) === -1) {
|
|
|
|
const whenValues = WHEN_ENUM.join(', ');
|
2015-10-12 17:57:23 +02:00
|
|
|
throw new Error(`"when" must be one of: [${whenValues}] got "${when}" instead`);
|
|
|
|
}
|
|
|
|
|
2016-06-07 14:55:04 +02:00
|
|
|
return function redirectRoute(router, { query }, { isLoggedIn }) {
|
2015-12-08 11:17:04 +01:00
|
|
|
const { redirectAuthenticated, redirect } = query;
|
|
|
|
|
|
|
|
// The user of this handler specifies with `when`, what kind of status
|
|
|
|
// needs to be checked to conditionally do - if that state is `true` -
|
|
|
|
// a redirect.
|
|
|
|
//
|
|
|
|
// So if when === 'loggedIn', we're checking if the user is logged in (and
|
|
|
|
// vice versa)
|
2016-01-13 16:03:08 +01:00
|
|
|
const exprToValidate = when === 'loggedIn' ? isLoggedIn : !isLoggedIn;
|
2015-12-08 11:17:04 +01:00
|
|
|
|
|
|
|
// and redirect if `true`.
|
2016-01-11 12:54:15 +01:00
|
|
|
if (exprToValidate) {
|
2016-06-06 15:40:26 +02:00
|
|
|
window.setTimeout(() => router.replace({ query, pathname: to }));
|
2015-12-08 15:21:20 +01:00
|
|
|
return true;
|
2015-12-08 11:17:04 +01:00
|
|
|
|
|
|
|
// Otherwise there can also be the case that the backend
|
|
|
|
// wants to redirect the user to a specific route when the user is logged out already
|
2016-01-11 12:54:15 +01:00
|
|
|
} else if (!exprToValidate && when === 'loggedIn' && redirect) {
|
2015-12-08 11:17:04 +01:00
|
|
|
delete query.redirect;
|
2016-06-06 15:40:26 +02:00
|
|
|
window.setTimeout(() => router.replace({ query, pathname: `/${redirect}` }));
|
2015-12-08 15:21:20 +01:00
|
|
|
return true;
|
2015-12-08 11:17:04 +01:00
|
|
|
|
2016-01-11 12:54:15 +01:00
|
|
|
} else if (!exprToValidate && when === 'loggedOut' && redirectAuthenticated) {
|
2015-12-08 11:17:04 +01:00
|
|
|
/*
|
|
|
|
* redirectAuthenticated contains an arbitrary path
|
|
|
|
* eg pieces/<id>, editions/<bitcoin_id>, collection, settings, ...
|
|
|
|
* hence transitionTo cannot be used directly.
|
|
|
|
*
|
|
|
|
* While we're getting rid of `query.redirect` explicitly in the
|
2016-06-02 15:31:21 +02:00
|
|
|
* above `else if` statement, here it's sufficient to just set the
|
|
|
|
* location to `${baseUrl}/${redirectAuthenticated}`, as this will
|
|
|
|
* get rid of queries as well.
|
2015-12-08 11:17:04 +01:00
|
|
|
*/
|
2016-06-02 15:31:21 +02:00
|
|
|
window.location = `${AppConstants.baseUrl}/${redirectAuthenticated}`;
|
2015-12-08 15:21:20 +01:00
|
|
|
return true;
|
2015-12-08 11:17:04 +01:00
|
|
|
}
|
2016-01-11 12:54:15 +01:00
|
|
|
|
2015-12-08 15:21:20 +01:00
|
|
|
return false;
|
2015-12-08 11:17:04 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Can be used in combination with `Route` as an intermediate Handler
|
|
|
|
* between the actual component we want to display dependent on a certain state
|
|
|
|
* that is required to display that component.
|
|
|
|
*
|
|
|
|
* @param {[function]} redirectFn A function that conditionally redirects
|
|
|
|
*/
|
2015-12-08 15:21:20 +01:00
|
|
|
export function ProxyHandler(...redirectFunctions) {
|
2016-06-06 18:52:05 +02:00
|
|
|
return (Component) => {
|
2016-06-10 10:22:04 +02:00
|
|
|
// Don't worry about shadowing the HOC here; using a declaration like this allows
|
|
|
|
// babel-plugin-react-display-name to automatically generate the displayName.
|
|
|
|
// eslint-disable-next-line no-shadow
|
|
|
|
const ProxyHandler = React.createClass({
|
2015-10-09 13:51:21 +02:00
|
|
|
propTypes: {
|
2016-06-06 18:52:05 +02:00
|
|
|
// Injected through HOCs
|
2016-06-07 14:55:04 +02:00
|
|
|
currentUser: currentUserShape.isRequired,
|
|
|
|
isLoggedIn: bool.isRequired,
|
2016-06-08 14:54:05 +02:00
|
|
|
location: locationShape.isRequired,
|
2016-06-08 13:52:24 +02:00
|
|
|
router: routerShape.isRequired,
|
2016-06-08 15:10:58 +02:00
|
|
|
whitelabel: whitelabelShape.isRequired
|
2016-01-25 17:53:28 +01:00
|
|
|
},
|
2015-10-06 18:28:15 +02:00
|
|
|
|
2016-01-13 16:03:08 +01:00
|
|
|
componentDidMount() {
|
|
|
|
this.evaluateRedirectFunctions();
|
|
|
|
},
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
this.evaluateRedirectFunctions(nextProps);
|
|
|
|
},
|
|
|
|
|
|
|
|
evaluateRedirectFunctions(props = this.props) {
|
2016-06-07 14:55:04 +02:00
|
|
|
const { currentUser, isLoggedIn, location, router, whitelabel } = props;
|
2015-12-08 15:44:46 +01:00
|
|
|
|
2016-01-13 16:03:08 +01:00
|
|
|
if (UserStore.hasLoaded() && !UserStore.isLoading()) {
|
2016-06-07 14:55:04 +02:00
|
|
|
const context = { currentUser, isLoggedIn, whitelabel };
|
|
|
|
|
2016-01-11 12:54:15 +01:00
|
|
|
for (let i = 0; i < redirectFunctions.length; i++) {
|
2016-06-07 14:55:04 +02:00
|
|
|
// if a redirectFunction redirects the user, it should return `true` and
|
|
|
|
// therefore stop/avoid the execution of all functions that follow
|
|
|
|
if (redirectFunctions[i](router, location, context)) {
|
2015-12-08 15:21:20 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-11-02 11:31:02 +01:00
|
|
|
}
|
2015-10-06 18:28:15 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
2016-01-13 16:03:08 +01:00
|
|
|
<Component {...this.props} />
|
2015-10-06 18:28:15 +02:00
|
|
|
);
|
|
|
|
}
|
2016-06-06 18:52:05 +02:00
|
|
|
});
|
|
|
|
|
2016-06-10 10:22:04 +02:00
|
|
|
return withContext(ProxyHandler,
|
2016-06-08 14:54:05 +02:00
|
|
|
'currentUser',
|
|
|
|
'isLoggedIn',
|
|
|
|
'location',
|
|
|
|
'router',
|
|
|
|
'whitelabel');
|
2016-06-06 18:52:05 +02:00
|
|
|
};
|
2015-10-12 16:51:03 +02:00
|
|
|
}
|