Added invite limit and tests for when multiple users with an error

This commit is contained in:
Keith Holliday
2016-01-12 08:33:02 -06:00
parent 9141598a34
commit 1b395b39f8
4 changed files with 106 additions and 13 deletions

View File

@@ -53,5 +53,6 @@
"userAlreadyInAParty": "User already in a party.", "userAlreadyInAParty": "User already in a party.",
"userWithIDNotFound": "User with id \"<%= userId %>\" not found.", "userWithIDNotFound": "User with id \"<%= userId %>\" not found.",
"uuidsMustBeAnArray": "UUIDs invites must be a an Array.", "uuidsMustBeAnArray": "UUIDs invites must be a an Array.",
"emailsMustBeAnArray": "Email invites must be a an Array." "emailsMustBeAnArray": "Email invites must be a an Array.",
"canOnlyInviteMaxInvites": "You can only invite \"<%= maxInvites %>\" at a time"
} }

View File

@@ -2,6 +2,9 @@ import {
generateUser, generateUser,
translate as t, translate as t,
} from '../../../../helpers/api-integration.helper'; } from '../../../../helpers/api-integration.helper';
import { v4 as generateUUID } from 'uuid';
const INVITES_LIMIT = 100;
describe('Post /groups/:groupId/invite', () => { describe('Post /groups/:groupId/invite', () => {
let inviter; let inviter;
@@ -18,7 +21,7 @@ describe('Post /groups/:groupId/invite', () => {
describe('user id invites', () => { describe('user id invites', () => {
it('returns an error when invited user is not found', async () => { it('returns an error when invited user is not found', async () => {
let fakeID = '206039c6-24e4-4b9f-8a31-61cbb9aa3f66'; let fakeID = generateUUID();
await expect(inviter.post(`/groups/${group._id}/invite`, { await expect(inviter.post(`/groups/${group._id}/invite`, {
uuids: [fakeID], uuids: [fakeID],
@@ -31,7 +34,7 @@ describe('Post /groups/:groupId/invite', () => {
}); });
it('returns an error when uuids is not an array', async () => { it('returns an error when uuids is not an array', async () => {
let fakeID = '206039c6-24e4-4b9f-8a31-61cbb9aa3f66'; let fakeID = generateUUID();
await expect(inviter.post(`/groups/${group._id}/invite`, { await expect(inviter.post(`/groups/${group._id}/invite`, {
uuids: {fakeID}, uuids: {fakeID},
@@ -50,6 +53,23 @@ describe('Post /groups/:groupId/invite', () => {
.to.eventually.be.empty; .to.eventually.be.empty;
}); });
it('returns an error when there are more than INVITES_LIMIT uuids', async () => {
let uuids = [];
for (let i = 0; i < 101; i += 1) {
uuids.push(generateUUID());
}
await expect(inviter.post(`/groups/${group._id}/invite`, {
uuids,
}))
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}),
});
});
it('invites a user to a group by uuid', async () => { it('invites a user to a group by uuid', async () => {
let userToInvite = await generateUser(); let userToInvite = await generateUser();
@@ -85,10 +105,24 @@ describe('Post /groups/:groupId/invite', () => {
await expect(userToInvite.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id); await expect(userToInvite.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id);
await expect(userToInvite2.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id); await expect(userToInvite2.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id);
}); });
it('returns an error when inviting multiple users and a user is not found', async () => {
let userToInvite = await generateUser();
let fakeID = generateUUID();
await expect(inviter.post(`/groups/${group._id}/invite`, {
uuids: [userToInvite._id, fakeID],
}))
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
message: t('userWithIDNotFound', {userId: fakeID}),
});
});
}); });
describe('email invites', () => { describe('email invites', () => {
let testInvite = {name: 'test', email: 'test@habitca.com'}; let testInvite = {name: 'test', email: 'test@habitica.com'};
it('returns an error when invite is missing an email', async () => { it('returns an error when invite is missing an email', async () => {
await expect(inviter.post(`/groups/${group._id}/invite`, { await expect(inviter.post(`/groups/${group._id}/invite`, {
@@ -119,6 +153,23 @@ describe('Post /groups/:groupId/invite', () => {
.to.eventually.be.empty; .to.eventually.be.empty;
}); });
it('returns an error when there are more than INVITES_LIMIT emails', async () => {
let emails = [];
for (let i = 0; i < 101; i += 1) {
emails.push(`${generateUUID()}@habitica.com`);
}
await expect(inviter.post(`/groups/${group._id}/invite`, {
emails,
}))
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}),
});
});
it('invites a user to a group by email', async () => { it('invites a user to a group by email', async () => {
await expect(inviter.post(`/groups/${group._id}/invite`, { await expect(inviter.post(`/groups/${group._id}/invite`, {
emails: [testInvite], emails: [testInvite],
@@ -127,7 +178,7 @@ describe('Post /groups/:groupId/invite', () => {
it('invites multiple users to a group by email', async () => { it('invites multiple users to a group by email', async () => {
await expect(inviter.post(`/groups/${group._id}/invite`, { await expect(inviter.post(`/groups/${group._id}/invite`, {
emails: [testInvite, {name: 'test2', email: 'test2@habitca.com'}], emails: [testInvite, {name: 'test2', email: 'test2@habitica.com'}],
})).to.exist; })).to.exist;
}); });
}); });
@@ -142,11 +193,34 @@ describe('Post /groups/:groupId/invite', () => {
}); });
}); });
it('returns an error when there are more than INVITES_LIMIT uuids and emails', async () => {
let emails = [];
let uuids = [];
for (let i = 0; i < 50; i += 1) {
emails.push(`${generateUUID()}@habitica.com`);
}
for (let i = 0; i < 51; i += 1) {
uuids.push(generateUUID());
}
await expect(inviter.post(`/groups/${group._id}/invite`, {
emails,
uuids,
}))
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}),
});
});
it('invites users to a group by uuid and email', async () => { it('invites users to a group by uuid and email', async () => {
let newUser = await generateUser(); let newUser = await generateUser();
let invite = await inviter.post(`/groups/${group._id}/invite`, { let invite = await inviter.post(`/groups/${group._id}/invite`, {
uuids: [newUser._id], uuids: [newUser._id],
emails: [{name: 'test', email: 'test@habitca.com'}], emails: [{name: 'test', email: 'test@habitica.com'}],
}); });
let invitedUser = await newUser.get('/user'); let invitedUser = await newUser.get('/user');

View File

@@ -2,7 +2,10 @@ import { authWithHeaders } from '../../middlewares/api-v3/auth';
import Q from 'q'; import Q from 'q';
import _ from 'lodash'; import _ from 'lodash';
import cron from '../../middlewares/api-v3/cron'; import cron from '../../middlewares/api-v3/cron';
import { model as Group } from '../../models/group'; import {
INVITES_LIMIT,
model as Group,
} from '../../models/group';
import { model as User } from '../../models/user'; import { model as User } from '../../models/user';
import { model as EmailUnsubscription } from '../../models/emailUnsubscription'; import { model as EmailUnsubscription } from '../../models/emailUnsubscription';
import { import {
@@ -407,7 +410,7 @@ async function _inviteByUUID (uuid, group, inviter, req, res) {
if (_.find(userToInvite.invitations.guilds, {id: group._id})) { if (_.find(userToInvite.invitations.guilds, {id: group._id})) {
throw new NotAuthorized(res.t('userAlreadyInvitedToGroup')); throw new NotAuthorized(res.t('userAlreadyInvitedToGroup'));
} }
userToInvite.invitations.guilds.push({id: group._id, name: group.name, inviter: res.locals.user._id}); userToInvite.invitations.guilds.push({id: group._id, name: group.name, inviter: inviter._id});
} else if (group.type === 'party') { } else if (group.type === 'party') {
if (!_.isEmpty(userToInvite.invitations.party)) { if (!_.isEmpty(userToInvite.invitations.party)) {
throw new NotAuthorized(res.t('userAlreadyPendingInvitation')); throw new NotAuthorized(res.t('userAlreadyPendingInvitation'));
@@ -417,7 +420,7 @@ async function _inviteByUUID (uuid, group, inviter, req, res) {
} }
// @TODO: Why was this here? // @TODO: Why was this here?
// req.body.type in 'guild', 'party' // req.body.type in 'guild', 'party'
userToInvite.invitations.party = {id: group._id, name: group.name, inviter: res.locals.user._id}; userToInvite.invitations.party = {id: group._id, name: group.name, inviter: inviter._id};
} }
let groupLabel = group.type === 'guild' ? 'Guild' : 'Party'; let groupLabel = group.type === 'guild' ? 'Guild' : 'Party';
@@ -532,13 +535,26 @@ api.inviteToGroup = {
} }
let results = []; let results = [];
let totalInvites = 0;
if (uuids && !uuidsIsArray) { if (uuids) {
if (!uuidsIsArray) {
throw new BadRequest(res.t('uuidsMustBeAnArray')); throw new BadRequest(res.t('uuidsMustBeAnArray'));
} else {
totalInvites += uuids.length;
}
} }
if (emails && !emailsIsArray) { if (emails) {
if (!emailsIsArray) {
throw new BadRequest(res.t('emailsMustBeAnArray')); throw new BadRequest(res.t('emailsMustBeAnArray'));
} else {
totalInvites += emails.length;
}
}
if (totalInvites > INVITES_LIMIT) {
throw new BadRequest(res.t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}));
} }
if (uuids) { if (uuids) {

View File

@@ -520,3 +520,5 @@ model.count({_id: 'habitrpg'}, (err, ct) => {
privacy: 'public', privacy: 'public',
}).save(); }).save();
}); });
export const INVITES_LIMIT = 100;