UI to prevent suspended users viewing the application

This commit is contained in:
Jori Lallo
2018-03-04 22:18:23 -08:00
parent 1c2b3e992e
commit 1a8ca20fce
8 changed files with 49 additions and 9 deletions

View File

@ -1,6 +1,6 @@
// @flow
import React from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import { Switch, Route, Redirect, withRouter } from 'react-router-dom';
import type { Location } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import styled from 'styled-components';
@ -17,6 +17,7 @@ import Sidebar from 'components/Sidebar';
import SettingsSidebar from 'components/Sidebar/Settings';
import Modals from 'components/Modals';
import Toasts from 'components/Toasts';
import ErrorSuspended from 'scenes/ErrorSuspended';
import AuthStore from 'stores/AuthStore';
import UiStore from 'stores/UiStore';
@ -66,11 +67,17 @@ class Layout extends React.Component {
this.props.ui.setActiveModal('keyboard-shortcuts');
}
renderSuspended() {
return <ErrorSuspended />;
}
render() {
const { auth, ui } = this.props;
const { user, team } = auth;
const showSidebar = auth.authenticated && user && team;
if (auth.isSuspended) return this.renderSuspended();
return (
<Container column auto>
<Helmet>

View File

@ -0,0 +1,24 @@
// @flow
import React from 'react';
import CenteredContent from 'components/CenteredContent';
import PageTitle from 'components/PageTitle';
const ErrorSuspended = () => (
<CenteredContent>
<PageTitle title="Your account has been suspended" />
<h1>
<span role="img" aria-label="Warning sign">
</span>{' '}
Your account has been suspended
</h1>
<p>
Team admin has suspended your account. To re-activate your account, please
reach out to them directly.
</p>
</CenteredContent>
);
export default ErrorSuspended;

View File

@ -0,0 +1,3 @@
// @flow
import ErrorSuspended from './ErrorSuspended';
export default ErrorSuspended;

View File

@ -14,6 +14,7 @@ class AuthStore {
@observable token: ?string;
@observable oauthState: string;
@observable isLoading: boolean = false;
@observable isSuspended: boolean = false;
/* Computed */
@ -43,8 +44,9 @@ class AuthStore {
this.team = res.data.team;
});
} catch (err) {
// Failure to update user info is a non-fatal error.
console.error(err);
if (err.data.error === 'user_suspended') {
this.isSuspended = true;
}
}
};

View File

@ -75,7 +75,9 @@ export default function auth() {
}
}
if (user.isSuspended) throw new UserSuspendedError();
if (user.isSuspended) {
throw new UserSuspendedError();
}
ctx.state.token = token;
ctx.state.user = user;

View File

@ -22,7 +22,9 @@ export function AdminRequiredError(
export function UserSuspendedError(
message: string = 'Your access has been suspended by the team admin'
) {
return httpErrors(403, message, { id: 'user_suspended' });
return httpErrors(403, message, {
id: 'user_suspended',
});
}
export function InvalidRequestError(message: string = 'Request invalid') {

View File

@ -2,6 +2,10 @@ module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('users', 'suspendedById', {
type: Sequelize.UUID,
allowNull: true,
references: {
model: 'users',
},
});
await queryInterface.addColumn('users', 'suspendedAt', {
type: Sequelize.DATE,

View File

@ -49,10 +49,6 @@ User.associate = models => {
User.hasMany(models.ApiKey, { as: 'apiKeys' });
User.hasMany(models.Document, { as: 'documents' });
User.hasMany(models.View, { as: 'views' });
User.belongsTo(models.User, {
as: 'suspendedBy',
foreignKey: 'suspendedById',
});
};
// Instance methods