131 lines
3.7 KiB
JavaScript
131 lines
3.7 KiB
JavaScript
import PropTypes from 'prop-types';
|
|
import React from 'react';
|
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
import { connect } from 'react-redux';
|
|
import { Redirect, Route } from 'react-router-dom';
|
|
|
|
import { getSettings } from 'soapbox/actions/settings';
|
|
|
|
import BundleColumnError from '../components/bundle_column_error';
|
|
import ColumnForbidden from '../components/column_forbidden';
|
|
import ColumnLoading from '../components/column_loading';
|
|
import BundleContainer from '../containers/bundle_container';
|
|
import ColumnsAreaContainer from '../containers/columns_area_container';
|
|
|
|
const mapStateToProps = state => {
|
|
const me = state.get('me');
|
|
|
|
return {
|
|
account: state.getIn(['accounts', me]),
|
|
settings: getSettings(state),
|
|
};
|
|
};
|
|
|
|
class WrappedRoute extends React.Component {
|
|
|
|
static propTypes = {
|
|
component: PropTypes.func.isRequired,
|
|
page: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
|
content: PropTypes.node,
|
|
componentParams: PropTypes.object,
|
|
layout: PropTypes.object,
|
|
account: ImmutablePropTypes.record,
|
|
settings: ImmutablePropTypes.map.isRequired,
|
|
publicRoute: PropTypes.bool,
|
|
staffOnly: PropTypes.bool,
|
|
adminOnly: PropTypes.bool,
|
|
developerOnly: PropTypes.bool,
|
|
};
|
|
|
|
static defaultProps = {
|
|
componentParams: {},
|
|
};
|
|
|
|
renderComponent = ({ match }) => {
|
|
const { component, content, componentParams, layout, page: Page } = this.props;
|
|
|
|
if (Page) {
|
|
return (
|
|
<BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}>
|
|
{Component =>
|
|
(
|
|
<Page params={match.params} layout={layout} {...componentParams}>
|
|
<Component params={match.params} {...componentParams}>
|
|
{content}
|
|
</Component>
|
|
</Page>
|
|
)
|
|
}
|
|
</BundleContainer>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}>
|
|
{Component =>
|
|
(
|
|
<ColumnsAreaContainer layout={layout}>
|
|
<Component params={match.params} {...componentParams}>
|
|
{content}
|
|
</Component>
|
|
</ColumnsAreaContainer>
|
|
)
|
|
}
|
|
</BundleContainer>
|
|
);
|
|
}
|
|
|
|
renderLoading = () => {
|
|
return (
|
|
<ColumnsAreaContainer layout={this.props.layout}>
|
|
<ColumnLoading />
|
|
</ColumnsAreaContainer>
|
|
);
|
|
}
|
|
|
|
renderForbidden = () => {
|
|
return (
|
|
<ColumnsAreaContainer layout={this.props.layout}>
|
|
<ColumnForbidden />
|
|
</ColumnsAreaContainer>
|
|
);
|
|
}
|
|
|
|
renderError = (props) => {
|
|
return (
|
|
<ColumnsAreaContainer layout={this.props.layout}>
|
|
<BundleColumnError {...props} />
|
|
</ColumnsAreaContainer>
|
|
);
|
|
}
|
|
|
|
loginRedirect = () => {
|
|
const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types
|
|
return <Redirect to={`/login?redirect_uri=${actualUrl}`} />;
|
|
}
|
|
|
|
render() {
|
|
const { component: Component, content, account, settings, publicRoute, developerOnly, staffOnly, adminOnly, ...rest } = this.props;
|
|
|
|
const authorized = [
|
|
account || publicRoute,
|
|
developerOnly ? settings.get('isDeveloper') : true,
|
|
staffOnly ? account && account.staff : true,
|
|
adminOnly ? account && account.admin : true,
|
|
].every(c => c);
|
|
|
|
if (!authorized) {
|
|
if (!account) {
|
|
return this.loginRedirect();
|
|
} else {
|
|
return this.renderForbidden();
|
|
}
|
|
}
|
|
|
|
return <Route {...rest} render={this.renderComponent} />;
|
|
}
|
|
|
|
}
|
|
|
|
const wrappedRoute = connect(mapStateToProps)(WrappedRoute);
|
|
export { wrappedRoute as WrappedRoute };
|