From 45eb19e992b3f6e6fd17e6667dfc5a1ab3d0d48e Mon Sep 17 00:00:00 2001 From: Travis Date: Sat, 17 Mar 2018 14:26:07 -0700 Subject: [PATCH] Update the API to prevent the user from leaving a group if they are the only member and have a quest active. (#10091) * Update the API to prevent the user from leaving a group if they are the only member and have a quest active. fixes #10068 * fixing api doc --- .../groups/POST-groups_groupId_join.test.js | 24 +++++++++++++++++++ website/client/store/actions/guilds.js | 8 ++++++- website/common/locales/en/messages.json | 1 + website/server/controllers/api-v3/groups.js | 19 +++++++++------ 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js index 41d2156ecd..9a795b2c5d 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js @@ -262,6 +262,30 @@ describe('POST /group/:groupId/join', () => { await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(false); }); + it('does not allow user to leave a party if a quest was active and they were the only member', async () => { + let userToInvite = await generateUser(); + let oldParty = await userToInvite.post('/groups', { // add user to a party + name: 'Another Test Party', + type: 'party', + }); + + await userToInvite.update({ + [`items.quests.${PET_QUEST}`]: 1, + }); + await userToInvite.post(`/groups/${oldParty._id}/quests/invite/${PET_QUEST}`); + + await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(true); + await user.post(`/groups/${party._id}/invite`, { + uuids: [userToInvite._id], + }); + + await expect(userToInvite.post(`/groups/${party._id}/join`)).to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('messageCannotLeaveWhileQuesting'), + }); + }); + it('invites joining member to active quest', async () => { await user.update({ [`items.quests.${PET_QUEST}`]: 1, diff --git a/website/client/store/actions/guilds.js b/website/client/store/actions/guilds.js index 9805da9fad..564030e553 100644 --- a/website/client/store/actions/guilds.js +++ b/website/client/store/actions/guilds.js @@ -55,7 +55,13 @@ export async function join (store, payload) { const user = store.state.user.data; const invitations = user.invitations; - let response = await axios.post(`/api/v3/groups/${groupId}/join`); + let response; + try { + response = await axios.post(`/api/v3/groups/${groupId}/join`); + } catch (err) { + alert(err.response.data.message); + return; + } if (type === 'guild') { const invitationI = invitations.guilds.findIndex(i => i.id === groupId); diff --git a/website/common/locales/en/messages.json b/website/common/locales/en/messages.json index 11e26c7a70..9a9ce2abf3 100644 --- a/website/common/locales/en/messages.json +++ b/website/common/locales/en/messages.json @@ -60,6 +60,7 @@ "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", "messageCannotFlagSystemMessages": "You cannot flag a system message. If you need to report a violation of the Community Guidelines related to this message, please email a screenshot and explanation to Lemoness at <%= communityManagerEmail %>.", "messageGroupChatSpam": "Whoops, looks like you're posting too many messages! Please wait a minute and try again. The Tavern chat only holds 200 messages at a time, so Habitica encourages posting longer, more thoughtful messages and consolidating replies. Can't wait to hear what you have to say. :)", + "messageCannotLeaveWhileQuesting": "You cannot accept this party invitation while you are in a quest. If you'd like to join this party, you must first abort your quest, which you can do from your party screen. You will be given back the quest scroll.", "messageUserOperationProtected": "path `<%= operation %>` was not saved, as it's a protected path.", "messageUserOperationNotFound": "<%= operation %> operation not found", diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index d3f135dcf8..834a6dfc54 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -518,6 +518,18 @@ api.joinGroup = { if (inviterParty) { inviter = inviterParty.inviter; + // If user was in a different party (when partying solo you can be invited to a new party) + // make them leave that party before doing anything + if (user.party._id) { + let userPreviousParty = await Group.getGroup({user, groupId: user.party._id}); + + if (userPreviousParty.memberCount === 1 && user.party.quest.key) { + throw new NotAuthorized(res.t('messageCannotLeaveWhileQuesting')); + } + + if (userPreviousParty) await userPreviousParty.leave(user); + } + // Clear all invitations of new user user.invitations.parties = []; user.invitations.party = {}; @@ -530,13 +542,6 @@ api.joinGroup = { group.markModified('quest.members'); } - // If user was in a different party (when partying solo you can be invited to a new party) - // make them leave that party before doing anything - if (user.party._id) { - let userPreviousParty = await Group.getGroup({user, groupId: user.party._id}); - if (userPreviousParty) await userPreviousParty.leave(user); - } - user.party._id = group._id; // Set group as user's party isUserInvited = true;