Prevent API access from suspended user

This commit is contained in:
Jori Lallo
2018-03-04 17:08:18 -08:00
parent a0f58583b5
commit 1c2b3e992e
3 changed files with 75 additions and 43 deletions

View File

@ -2,7 +2,7 @@
import JWT from 'jsonwebtoken'; import JWT from 'jsonwebtoken';
import { type Context } from 'koa'; import { type Context } from 'koa';
import { User, ApiKey } from '../../models'; import { User, ApiKey } from '../../models';
import { AuthenticationError } from '../../errors'; import { AuthenticationError, UserSuspendedError } from '../../errors';
export default function auth() { export default function auth() {
return async function authMiddleware( return async function authMiddleware(
@ -35,7 +35,6 @@ export default function auth() {
if (!token) throw new AuthenticationError('Authentication required'); if (!token) throw new AuthenticationError('Authentication required');
if (token) {
let user; let user;
if (String(token).match(/^[\w]{38}$/)) { if (String(token).match(/^[\w]{38}$/)) {
@ -76,11 +75,12 @@ export default function auth() {
} }
} }
if (user.isSuspended) throw new UserSuspendedError();
ctx.state.token = token; ctx.state.token = token;
ctx.state.user = user; ctx.state.user = user;
// $FlowFixMe // $FlowFixMe
ctx.cache[user.id] = user; ctx.cache[user.id] = user;
}
return next(); return next();
}; };

View File

@ -1,5 +1,6 @@
/* eslint-disable flowtype/require-valid-file-annotation */ /* eslint-disable flowtype/require-valid-file-annotation */
import { flushdb, seed } from '../../test/support'; import { flushdb, seed } from '../../test/support';
import { buildUser } from '../../test/factories';
import { ApiKey } from '../../models'; import { ApiKey } from '../../models';
import randomstring from 'randomstring'; import randomstring from 'randomstring';
import auth from './authentication'; import auth from './authentication';
@ -155,4 +156,29 @@ describe('Authentication middleware', async () => {
); );
expect(state.user.id).toEqual(user.id); expect(state.user.id).toEqual(user.id);
}); });
it('should return an error for suspended users', async () => {
const state = {};
const user = await buildUser({
suspendedAt: new Date(),
});
const authMiddleware = auth();
try {
await authMiddleware(
{
request: {
get: jest.fn(() => `Bearer ${user.getJwtToken()}`),
},
state,
cache: {},
},
jest.fn()
);
} catch (e) {
expect(e.message).toEqual(
'Your access has been suspended by the team admin'
);
}
});
}); });

View File

@ -19,6 +19,12 @@ export function AdminRequiredError(
return httpErrors(403, message, { id: 'admin_required' }); return httpErrors(403, message, { id: 'admin_required' });
} }
export function UserSuspendedError(
message: string = 'Your access has been suspended by the team admin'
) {
return httpErrors(403, message, { id: 'user_suspended' });
}
export function InvalidRequestError(message: string = 'Request invalid') { export function InvalidRequestError(message: string = 'Request invalid') {
return httpErrors(400, message, { id: 'invalid_request' }); return httpErrors(400, message, { id: 'invalid_request' });
} }