location forward after authentication (#90)
This commit is contained in:
parent
9829f3f1ea
commit
c8ab0d0f37
|
@ -64,7 +64,6 @@ const routeConfigs: RouteConfig[] = [
|
|||
},
|
||||
template: {
|
||||
title: 'Create a Proposal',
|
||||
requiresAuth: true,
|
||||
},
|
||||
onlyLoggedIn: true,
|
||||
},
|
||||
|
@ -77,7 +76,6 @@ const routeConfigs: RouteConfig[] = [
|
|||
},
|
||||
template: {
|
||||
title: 'Browse proposals',
|
||||
requiresAuth: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -90,7 +88,6 @@ const routeConfigs: RouteConfig[] = [
|
|||
title: 'Edit proposal',
|
||||
isFullScreen: true,
|
||||
hideFooter: true,
|
||||
requiresAuth: true,
|
||||
},
|
||||
onlyLoggedIn: true,
|
||||
},
|
||||
|
@ -102,7 +99,6 @@ const routeConfigs: RouteConfig[] = [
|
|||
},
|
||||
template: {
|
||||
title: 'Proposal',
|
||||
requiresAuth: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,38 +1,81 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Route, Redirect, RouteProps } from 'react-router-dom';
|
||||
import { Spin } from 'antd';
|
||||
import { Spin, message } from 'antd';
|
||||
import { AppState } from 'store/reducers';
|
||||
|
||||
interface StateProps {
|
||||
user: AppState['auth']['user'];
|
||||
isCheckingUser: AppState['auth']['isCheckingUser'];
|
||||
}
|
||||
import { authActions } from 'modules/auth';
|
||||
|
||||
interface OwnProps {
|
||||
onlyLoggedOut?: boolean;
|
||||
}
|
||||
|
||||
type Props = RouteProps & StateProps & OwnProps;
|
||||
interface StateProps {
|
||||
user: AppState['auth']['user'];
|
||||
isCheckingUser: AppState['auth']['isCheckingUser'];
|
||||
hasCheckedUser: AppState['auth']['hasCheckedUser'];
|
||||
authForwardLocation: AppState['auth']['authForwardLocation'];
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
setAuthForwardLocation: typeof authActions['setAuthForwardLocation'];
|
||||
}
|
||||
|
||||
type Props = RouteProps & StateProps & OwnProps & DispatchProps;
|
||||
|
||||
class AuthRoute extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
this.setAuthForward();
|
||||
}
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const { hasCheckedUser } = this.props;
|
||||
// in case we mounted before having checked user
|
||||
if (!prevProps.hasCheckedUser && hasCheckedUser) {
|
||||
this.setAuthForward();
|
||||
}
|
||||
}
|
||||
public render() {
|
||||
const { user, onlyLoggedOut, isCheckingUser, location, ...routeProps } = this.props;
|
||||
const {
|
||||
user,
|
||||
onlyLoggedOut,
|
||||
isCheckingUser,
|
||||
location,
|
||||
authForwardLocation,
|
||||
...routeProps
|
||||
} = this.props;
|
||||
if (isCheckingUser) {
|
||||
return <Spin />;
|
||||
return <Spin tip="Checking authentication status" />;
|
||||
}
|
||||
if ((user && !onlyLoggedOut) || (!user && onlyLoggedOut)) {
|
||||
return <Route {...routeProps} />;
|
||||
} else {
|
||||
// TODO: redirect to desired destination after auth
|
||||
// TODO: Show alert that claims they need to be logged in
|
||||
const pathname = onlyLoggedOut ? '/profile' : '/auth';
|
||||
return <Redirect to={{ ...location, pathname }} />;
|
||||
let newLocation = { ...location, pathname: '/auth' };
|
||||
if (onlyLoggedOut) {
|
||||
newLocation = authForwardLocation || { ...location, pathname: '/profile' };
|
||||
}
|
||||
return <Redirect to={{ ...newLocation }} />;
|
||||
}
|
||||
}
|
||||
private setAuthForward = () => {
|
||||
const {
|
||||
setAuthForwardLocation,
|
||||
location,
|
||||
hasCheckedUser,
|
||||
user,
|
||||
onlyLoggedOut,
|
||||
} = this.props;
|
||||
if (hasCheckedUser && !user && !onlyLoggedOut) {
|
||||
message.warn('Authorization required.');
|
||||
setAuthForwardLocation(location);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect((state: AppState) => ({
|
||||
user: state.auth.user,
|
||||
isCheckingUser: state.auth.isCheckingUser,
|
||||
}))(AuthRoute);
|
||||
export default connect<StateProps, DispatchProps, OwnProps, AppState>(
|
||||
(state: AppState) => ({
|
||||
user: state.auth.user,
|
||||
isCheckingUser: state.auth.isCheckingUser,
|
||||
hasCheckedUser: state.auth.hasCheckedUser,
|
||||
authForwardLocation: state.auth.authForwardLocation,
|
||||
}),
|
||||
{ setAuthForwardLocation: authActions.setAuthForwardLocation },
|
||||
)(AuthRoute);
|
||||
|
|
|
@ -1,51 +1,26 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Layout } from 'antd';
|
||||
import classnames from 'classnames';
|
||||
import BasicHead from 'components/BasicHead';
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
import { AppState } from 'store/reducers';
|
||||
import './index.less';
|
||||
|
||||
interface StateProps {
|
||||
authUser: AppState['auth']['user'];
|
||||
}
|
||||
|
||||
export interface TemplateProps {
|
||||
title: string;
|
||||
isHeaderTransparent?: boolean;
|
||||
isFullScreen?: boolean;
|
||||
hideFooter?: boolean;
|
||||
requiresAuth?: boolean;
|
||||
}
|
||||
|
||||
type Props = StateProps & TemplateProps;
|
||||
type Props = TemplateProps;
|
||||
|
||||
class Template extends React.PureComponent<Props> {
|
||||
export default class Template extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
title,
|
||||
isHeaderTransparent,
|
||||
isFullScreen,
|
||||
hideFooter,
|
||||
requiresAuth,
|
||||
authUser,
|
||||
} = this.props;
|
||||
const { children, title, isHeaderTransparent, isFullScreen, hideFooter } = this.props;
|
||||
|
||||
let content = children;
|
||||
let isCentered = false;
|
||||
if (requiresAuth) {
|
||||
if (!authUser) {
|
||||
isCentered = true;
|
||||
content = (
|
||||
<div>
|
||||
Login required. <br /> TODO: links or redirect
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
const content = children;
|
||||
const isCentered = false;
|
||||
|
||||
const className = classnames(
|
||||
'Template',
|
||||
|
@ -65,9 +40,3 @@ class Template extends React.PureComponent<Props> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect<StateProps, {}, TemplateProps, AppState>(state => {
|
||||
return {
|
||||
authUser: state.auth.user,
|
||||
};
|
||||
})(Template);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import types from './types';
|
||||
import { Dispatch } from 'redux';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { RouteProps } from 'react-router-dom';
|
||||
import {
|
||||
createUser as apiCreateUser,
|
||||
checkUserAuth,
|
||||
|
@ -96,3 +97,10 @@ export function logout() {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function setAuthForwardLocation(location: RouteProps['location']) {
|
||||
return {
|
||||
type: types.SET_AUTH_FORWARD_LOCATION,
|
||||
payload: { location },
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import types from './types';
|
||||
import usersTypes from 'modules/users/types';
|
||||
import { User, AuthSignatureData } from 'types';
|
||||
import { RouteProps } from 'react-router-dom';
|
||||
|
||||
export interface AuthState {
|
||||
user: User | null;
|
||||
isAuthingUser: boolean;
|
||||
authUserError: string | null;
|
||||
|
||||
authForwardLocation: RouteProps['location'];
|
||||
|
||||
isCheckingUser: boolean;
|
||||
hasCheckedUser: boolean;
|
||||
|
||||
|
@ -24,6 +27,8 @@ export const INITIAL_STATE: AuthState = {
|
|||
isAuthingUser: false,
|
||||
authUserError: null,
|
||||
|
||||
authForwardLocation: undefined,
|
||||
|
||||
isCreatingUser: false,
|
||||
createUserError: null,
|
||||
|
||||
|
@ -135,6 +140,12 @@ export default function createReducer(
|
|||
...state,
|
||||
user: null,
|
||||
};
|
||||
|
||||
case types.SET_AUTH_FORWARD_LOCATION:
|
||||
return {
|
||||
...state,
|
||||
authForwardLocation: action.payload.location,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ enum AuthTypes {
|
|||
LOGOUT_PENDING = 'LOGOUT_PENDING',
|
||||
LOGOUT_FULFILLED = 'LOGOUT_FULFILLED',
|
||||
LOGOUT_REJECTED = 'LOGOUT_REJECTED',
|
||||
|
||||
SET_AUTH_FORWARD_LOCATION = 'SET_AUTH_FORWARD_LOCATION',
|
||||
}
|
||||
|
||||
export default AuthTypes;
|
||||
|
|
Loading…
Reference in New Issue