Add support for forbidden status in server rendering

This commit is contained in:
Kimmo Puputti 2017-02-16 14:04:10 +02:00
parent 2863f9dbef
commit 48d6b3a3bd
3 changed files with 23 additions and 7 deletions

View file

@ -150,7 +150,15 @@ app.get('*', (req, res) => {
.then(preloadedState => {
const html = render(req.url, context, preloadedState);
if (context.url) {
if (context.forbidden) {
// Routes component injects the context.forbidden when the
// user isn't logged in to view the page that requires
// authentication.
//
// TODO: separate 401 and 403 cases when authorization is done
// as well.
res.status(403).send(html);
} else if (context.url) {
// React Router injects the context.url if a redirect was rendered
res.redirect(context.url);
} else if (context.notfound) {

View file

@ -1,17 +1,22 @@
import React, { PropTypes } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { Switch, Route } from 'react-router-dom';
import { Switch, Route, withRouter } from 'react-router-dom';
import { NotFoundPage } from './containers';
import { NamedRedirect } from './components';
import { withFlattenedRoutes } from './util/routes';
import * as propTypes from './util/propTypes';
const Routes = props => {
const { isAuthenticated, flattenedRoutes } = props;
const { isAuthenticated, flattenedRoutes, staticContext } = props;
const renderComponent = (route, matchProps) => {
const { auth, component: RouteComponent } = route;
const { match, location } = matchProps;
const canShowComponent = !auth || isAuthenticated;
if (!canShowComponent) {
staticContext.forbidden = true;
}
return canShowComponent
? <RouteComponent params={match.params} location={location} />
: <NamedRedirect name="LogInPage" state={{ from: match.url }} />;
@ -34,13 +39,16 @@ const Routes = props => {
);
};
const { bool, arrayOf } = PropTypes;
Routes.defaultProps = { staticContext: {} };
const { bool, arrayOf, object } = PropTypes;
Routes.propTypes = {
isAuthenticated: bool.isRequired,
flattenedRoutes: arrayOf(propTypes.route).isRequired,
staticContext: object,
};
const mapStateToProps = state => ({ isAuthenticated: state.Auth.isAuthenticated });
export default connect(mapStateToProps)(Routes);
export default compose(connect(mapStateToProps), withRouter, withFlattenedRoutes)(Routes);

View file

@ -21,7 +21,7 @@ export const ClientApp = props => {
<Provider store={store}>
<RoutesProvider flattenedRoutes={flattenedRoutes}>
<BrowserRouter>
<Routes flattenedRoutes={flattenedRoutes} />
<Routes />
</BrowserRouter>
</RoutesProvider>
</Provider>
@ -42,7 +42,7 @@ export const ServerApp = props => {
<Provider store={store}>
<RoutesProvider flattenedRoutes={flattenedRoutes}>
<StaticRouter location={url} context={context}>
<Routes flattenedRoutes={flattenedRoutes} />
<Routes />
</StaticRouter>
</RoutesProvider>
</Provider>