diff --git a/app/soapbox/features/ui/components/column_forbidden.js b/app/soapbox/features/ui/components/column_forbidden.js new file mode 100644 index 000000000..d57d2f547 --- /dev/null +++ b/app/soapbox/features/ui/components/column_forbidden.js @@ -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 ( + + +
+ {formatMessage(messages.body)} +
+
+ ); + } + +} + +export default injectIntl(ColumnForbidden); diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 49e4c26d7..85b376d54 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -317,14 +317,14 @@ class SwitchingColumnsArea extends React.PureComponent { - + - - - - - + + + + + diff --git a/app/soapbox/features/ui/util/react_router_helpers.js b/app/soapbox/features/ui/util/react_router_helpers.js index 4a636a738..af0b40800 100644 --- a/app/soapbox/features/ui/util/react_router_helpers.js +++ b/app/soapbox/features/ui/util/react_router_helpers.js @@ -1,16 +1,20 @@ import React from 'react'; import { connect } from 'react-redux'; 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 ColumnsAreaContainer from '../containers/columns_area_container'; import ColumnLoading from '../components/column_loading'; +import ColumnForbidden from '../components/column_forbidden'; import BundleColumnError from '../components/bundle_column_error'; import BundleContainer from '../containers/bundle_container'; +import { isStaff, isAdmin } from 'soapbox/utils/accounts'; const mapStateToProps = state => { + const me = state.get('me'); + return { - me: state.get('me'), + account: state.getIn(['accounts', me]), }; }; @@ -22,8 +26,10 @@ class WrappedRoute extends React.Component { content: PropTypes.node, componentParams: PropTypes.object, layout: PropTypes.object, + account: ImmutablePropTypes.map, publicRoute: PropTypes.bool, - me: SoapboxPropTypes.me, + staffOnly: PropTypes.bool, + adminOnly: PropTypes.bool, }; static defaultProps = { @@ -72,6 +78,14 @@ class WrappedRoute extends React.Component { ); } + renderForbidden = () => { + return ( + + + + ); + } + renderError = (props) => { return ( @@ -80,16 +94,26 @@ class WrappedRoute extends React.Component { ); } + loginRedirect = () => { + const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types + return ; + } + render() { - const { component: Component, content, publicRoute, me, ...rest } = this.props; - - if (!publicRoute && me === false) { - const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types - return ; - // return { - // window.location.href = `/auth/sign_in?redirect_uri=${actualUrl}`; - // return null; - // }}/> + const { component: Component, content, account, publicRoute, staffOnly, adminOnly, ...rest } = this.props; + + const authorized = [ + account || publicRoute, + 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 ;