mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
Added invite limit and tests for when multiple users with an error
This commit is contained in:
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
throw new BadRequest(res.t('uuidsMustBeAnArray'));
|
if (!uuidsIsArray) {
|
||||||
|
throw new BadRequest(res.t('uuidsMustBeAnArray'));
|
||||||
|
} else {
|
||||||
|
totalInvites += uuids.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emails && !emailsIsArray) {
|
if (emails) {
|
||||||
throw new BadRequest(res.t('emailsMustBeAnArray'));
|
if (!emailsIsArray) {
|
||||||
|
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) {
|
||||||
|
|||||||
@@ -520,3 +520,5 @@ model.count({_id: 'habitrpg'}, (err, ct) => {
|
|||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
}).save();
|
}).save();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const INVITES_LIMIT = 100;
|
||||||
|
|||||||
Reference in New Issue
Block a user