From 76499412edbc560e24accf38daf79c99c1db86d5 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Fri, 30 Sep 2016 10:20:12 -0500 Subject: [PATCH] refactor(api): Move invitation validation to group static method --- .../groups/POST-groups_invite.test.js | 6 +- test/api/v3/unit/models/group.test.js | 117 ++++++++++++++++++ website/server/controllers/api-v3/groups.js | 20 +-- website/server/models/group.js | 35 ++++++ 4 files changed, 155 insertions(+), 23 deletions(-) diff --git a/test/api/v3/integration/groups/POST-groups_invite.test.js b/test/api/v3/integration/groups/POST-groups_invite.test.js index 7e402baea6..171f080e84 100644 --- a/test/api/v3/integration/groups/POST-groups_invite.test.js +++ b/test/api/v3/integration/groups/POST-groups_invite.test.js @@ -69,9 +69,8 @@ describe('Post /groups/:groupId/invite', () => { }); }); - it('returns an error when uuids is empty and emails is undefined', async () => { + it('returns an error when uuids is empty and emails is not passed', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { - emails: undefined, uuids: [], })) .to.eventually.be.rejected.and.eql({ @@ -176,10 +175,9 @@ describe('Post /groups/:groupId/invite', () => { }); }); - it('returns an error when emails is empty and uuids is undefined', async () => { + it('returns an error when emails is empty and uuids is not passed', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { emails: [], - uuids: undefined, })) .to.eventually.be.rejected.and.eql({ code: 400, diff --git a/test/api/v3/unit/models/group.test.js b/test/api/v3/unit/models/group.test.js index 427cc9952f..ccd1f47c87 100644 --- a/test/api/v3/unit/models/group.test.js +++ b/test/api/v3/unit/models/group.test.js @@ -1,6 +1,7 @@ import { sleep } from '../../../../helpers/api-unit.helper'; import { model as Group } from '../../../../../website/server/models/group'; import { model as User } from '../../../../../website/server/models/user'; +import { BadRequest } from '../../../../../website/server/libs/errors'; import { quests as questScrolls } from '../../../../../website/common/script/content'; import * as email from '../../../../../website/server/libs/email'; import validator from 'validator'; @@ -433,6 +434,122 @@ describe('Group Model', () => { }); }); }); + + describe('validateInvitations', () => { + let res; + + beforeEach(() => { + res = { + t: sandbox.spy(), + }; + }); + + it('throws an error if no uuids or emails are passed in', (done) => { + try { + Group.validateInvitations(null, null, res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('canOnlyInviteEmailUuid'); + done(); + } + }); + + it('throws an error if only uuids are passed in, but they are not an array', (done) => { + try { + Group.validateInvitations({ uuid: 'user-id'}, null, res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('uuidsMustBeAnArray'); + done(); + } + }); + + it('throws an error if only emails are passed in, but they are not an array', (done) => { + try { + Group.validateInvitations(null, { emails: 'user@example.com'}, res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('emailsMustBeAnArray'); + done(); + } + }); + + it('throws an error if emails are not passed in, and uuid array is empty', (done) => { + try { + Group.validateInvitations([], null, res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('inviteMissingUuid'); + done(); + } + }); + + it('throws an error if uuids are not passed in, and email array is empty', (done) => { + try { + Group.validateInvitations(null, [], res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('inviteMissingEmail'); + done(); + } + }); + + it('throws an error if uuids and emails are passed in as empty arrays', (done) => { + try { + Group.validateInvitations([], [], res); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(res.t).to.be.calledOnce; + expect(res.t).to.be.calledWith('inviteMustNotBeEmpty'); + done(); + } + }); + + it('does not throw an error if only user ids are passed in', () => { + expect(function () { + Group.validateInvitations(['user-id', 'user-id2'], null, res); + }).to.not.throw(); + + expect(res.t).to.not.be.called; + }); + + it('does not throw an error if only emails are passed in', () => { + expect(function () { + Group.validateInvitations(null, ['user1@example.com', 'user2@example.com'], res); + }).to.not.throw(); + + expect(res.t).to.not.be.called; + }); + + it('does not throw an error if both uuids and emails are passed in', () => { + expect(function () { + Group.validateInvitations(['user-id', 'user-id2'], ['user1@example.com', 'user2@example.com'], res); + }).to.not.throw(); + + expect(res.t).to.not.be.called; + }); + + it('does not throw an error if uuids are passed in and emails are an empty array', () => { + expect(function () { + Group.validateInvitations(['user-id', 'user-id2'], [], res); + }).to.not.throw(); + + expect(res.t).to.not.be.called; + }); + + it('does not throw an error if emails are passed in and uuids are an empty array', () => { + expect(function () { + Group.validateInvitations([], ['user1@example.com', 'user2@example.com'], res); + }).to.not.throw(); + + expect(res.t).to.not.be.called; + }); + }); }); context('Instance Methods', () => { diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index 4d7d658ba0..54ec1bbb4a 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -673,25 +673,7 @@ api.inviteToGroup = { let uuids = req.body.uuids; let emails = req.body.emails; - let uuidsIsArray = Array.isArray(uuids); - let emailsIsArray = Array.isArray(emails); - let emptyEmails = emailsIsArray && emails.length < 1; - let emptyUuids = uuidsIsArray && uuids.length < 1; - - - if (!uuids && !emails) { - throw new BadRequest(res.t('canOnlyInviteEmailUuid')); - } else if (uuids && !uuidsIsArray) { - throw new BadRequest(res.t('uuidsMustBeAnArray')); - } else if (emails && !emailsIsArray) { - throw new BadRequest(res.t('emailsMustBeAnArray')); - } else if (!emails && emptyUuids) { - throw new BadRequest(res.t('inviteMissingUuid')); - } else if (!uuids && emptyEmails) { - throw new BadRequest(res.t('inviteMissingEmail')); - } else if (emptyEmails && emptyUuids) { - throw new BadRequest(res.t('inviteMustNotBeEmpty')); - } + Group.validateInvitations(uuids, emails, res); let results = []; let totalInvites = 0; diff --git a/website/server/models/group.js b/website/server/models/group.js index 4c47c49598..92e17cde13 100644 --- a/website/server/models/group.js +++ b/website/server/models/group.js @@ -265,6 +265,41 @@ schema.statics.toJSONCleanChat = function groupToJSONCleanChat (group, user) { return toJSON; }; +/** + * Checks inivtation uuids and emails for possible errors. + * + * @param uuids An array of user ids + * @param emails An array of emails + * @param res Express res object for use with translations + * @throws BadRequest An error describing the issue with the invitations + */ +schema.statics.validateInvitations = function getInvitationError (uuids, emails, res) { + let uuidsIsArray = Array.isArray(uuids); + let emailsIsArray = Array.isArray(emails); + let emptyEmails = emailsIsArray && emails.length < 1; + let emptyUuids = uuidsIsArray && uuids.length < 1; + + let errorString; + + if (!uuids && !emails) { + errorString = 'canOnlyInviteEmailUuid'; + } else if (uuids && !uuidsIsArray) { + errorString = 'uuidsMustBeAnArray'; + } else if (emails && !emailsIsArray) { + errorString = 'emailsMustBeAnArray'; + } else if (!emails && emptyUuids) { + errorString = 'inviteMissingUuid'; + } else if (!uuids && emptyEmails) { + errorString = 'inviteMissingEmail'; + } else if (emptyEmails && emptyUuids) { + errorString = 'inviteMustNotBeEmpty'; + } + + if (errorString) { + throw new BadRequest(res.t(errorString)); + } +}; + schema.methods.getParticipatingQuestMembers = function getParticipatingQuestMembers () { return Object.keys(this.quest.members).filter(member => this.quest.members[member]); };