Restrict pages access by unauthorized users
This commit is contained in:
parent
d91cbb3f56
commit
52a857d296
3 changed files with 76 additions and 18 deletions
34
app/soapbox/features/ui/components/column_forbidden.js
Normal file
34
app/soapbox/features/ui/components/column_forbidden.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import Column from './column';
|
||||||
|
import ColumnHeader from './column_header';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'column_forbidden.title', defaultMessage: 'Forbidden' },
|
||||||
|
body: { id: 'column_forbidden.body', defaultMessage: 'You do not have permission to access this page.' },
|
||||||
|
});
|
||||||
|
|
||||||
|
class ColumnForbidden extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl: { formatMessage } } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column>
|
||||||
|
<ColumnHeader icon='exclamation-circle' type={formatMessage(messages.title)} />
|
||||||
|
<div className='error-column'>
|
||||||
|
{formatMessage(messages.body)}
|
||||||
|
</div>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default injectIntl(ColumnForbidden);
|
|
@ -317,14 +317,14 @@ class SwitchingColumnsArea extends React.PureComponent {
|
||||||
<WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />
|
<WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />
|
||||||
<WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />
|
<WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />
|
||||||
<WrappedRoute path='/backups' page={DefaultPage} component={Backups} content={children} />
|
<WrappedRoute path='/backups' page={DefaultPage} component={Backups} content={children} />
|
||||||
<WrappedRoute path='/soapbox/config' page={DefaultPage} component={SoapboxConfig} content={children} />
|
<WrappedRoute path='/soapbox/config' adminOnly page={DefaultPage} component={SoapboxConfig} content={children} />
|
||||||
|
|
||||||
<Redirect from='/admin/dashboard' to='/admin' exact />
|
<Redirect from='/admin/dashboard' to='/admin' exact />
|
||||||
<WrappedRoute path='/admin' page={AdminPage} component={Dashboard} content={children} exact />
|
<WrappedRoute path='/admin' staffOnly page={AdminPage} component={Dashboard} content={children} exact />
|
||||||
<WrappedRoute path='/admin/approval' page={AdminPage} component={AwaitingApproval} content={children} exact />
|
<WrappedRoute path='/admin/approval' staffOnly page={AdminPage} component={AwaitingApproval} content={children} exact />
|
||||||
<WrappedRoute path='/admin/reports' page={AdminPage} component={Reports} content={children} exact />
|
<WrappedRoute path='/admin/reports' staffOnly page={AdminPage} component={Reports} content={children} exact />
|
||||||
<WrappedRoute path='/admin/log' page={AdminPage} component={ModerationLog} content={children} exact />
|
<WrappedRoute path='/admin/log' staffOnly page={AdminPage} component={ModerationLog} content={children} exact />
|
||||||
<WrappedRoute path='/admin/users' page={AdminPage} component={UserIndex} content={children} exact />
|
<WrappedRoute path='/admin/users' staffOnly page={AdminPage} component={UserIndex} content={children} exact />
|
||||||
<WrappedRoute path='/info' page={EmptyPage} component={ServerInfo} content={children} />
|
<WrappedRoute path='/info' page={EmptyPage} component={ServerInfo} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/developers/apps/create' page={DefaultPage} component={CreateApp} content={children} />
|
<WrappedRoute path='/developers/apps/create' page={DefaultPage} component={CreateApp} content={children} />
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { Redirect, Route } from 'react-router-dom';
|
import { Redirect, Route } from 'react-router-dom';
|
||||||
import ColumnsAreaContainer from '../containers/columns_area_container';
|
import ColumnsAreaContainer from '../containers/columns_area_container';
|
||||||
import ColumnLoading from '../components/column_loading';
|
import ColumnLoading from '../components/column_loading';
|
||||||
|
import ColumnForbidden from '../components/column_forbidden';
|
||||||
import BundleColumnError from '../components/bundle_column_error';
|
import BundleColumnError from '../components/bundle_column_error';
|
||||||
import BundleContainer from '../containers/bundle_container';
|
import BundleContainer from '../containers/bundle_container';
|
||||||
|
import { isStaff, isAdmin } from 'soapbox/utils/accounts';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
|
const me = state.get('me');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
me: state.get('me'),
|
account: state.getIn(['accounts', me]),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,8 +26,10 @@ class WrappedRoute extends React.Component {
|
||||||
content: PropTypes.node,
|
content: PropTypes.node,
|
||||||
componentParams: PropTypes.object,
|
componentParams: PropTypes.object,
|
||||||
layout: PropTypes.object,
|
layout: PropTypes.object,
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
publicRoute: PropTypes.bool,
|
publicRoute: PropTypes.bool,
|
||||||
me: SoapboxPropTypes.me,
|
staffOnly: PropTypes.bool,
|
||||||
|
adminOnly: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -72,6 +78,14 @@ class WrappedRoute extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderForbidden = () => {
|
||||||
|
return (
|
||||||
|
<ColumnsAreaContainer layout={this.props.layout}>
|
||||||
|
<ColumnForbidden />
|
||||||
|
</ColumnsAreaContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderError = (props) => {
|
renderError = (props) => {
|
||||||
return (
|
return (
|
||||||
<ColumnsAreaContainer layout={this.props.layout}>
|
<ColumnsAreaContainer layout={this.props.layout}>
|
||||||
|
@ -80,16 +94,26 @@ class WrappedRoute extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
loginRedirect = () => {
|
||||||
const { component: Component, content, publicRoute, me, ...rest } = this.props;
|
const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types
|
||||||
|
return <Redirect to={`/auth/sign_in?redirect_uri=${actualUrl}`} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (!publicRoute && me === false) {
|
render() {
|
||||||
const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types
|
const { component: Component, content, account, publicRoute, staffOnly, adminOnly, ...rest } = this.props;
|
||||||
return <Redirect to={`/auth/sign_in?redirect_uri=${actualUrl}`} />;
|
|
||||||
// return <Route path={this.props.path} component={() => {
|
const authorized = [
|
||||||
// window.location.href = `/auth/sign_in?redirect_uri=${actualUrl}`;
|
account || publicRoute,
|
||||||
// return null;
|
staffOnly ? account && isStaff(account) : true,
|
||||||
// }}/>
|
adminOnly ? account && isAdmin(account) : true,
|
||||||
|
].every(c => c);
|
||||||
|
|
||||||
|
if (!authorized) {
|
||||||
|
if (!account) {
|
||||||
|
return this.loginRedirect();
|
||||||
|
} else {
|
||||||
|
return this.renderForbidden();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Route {...rest} render={this.renderComponent} />;
|
return <Route {...rest} render={this.renderComponent} />;
|
||||||
|
|
Loading…
Reference in a new issue