From 1e0190abef7f3b0f7fb7d9ab2a727c0b573131c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 18 Aug 2019 21:51:32 -0400 Subject: [PATCH] fix: #7842, groups.invite works with an array of uids --- src/database/mongo/sets.js | 4 +++- src/database/postgres/sets.js | 4 +++- src/groups/invite.js | 37 +++++++++++++++++------------------ src/socket.io/groups.js | 19 +++++++----------- test/database/sets.js | 8 ++++++++ 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/database/mongo/sets.js b/src/database/mongo/sets.js index a68fb713c3..41928f278d 100644 --- a/src/database/mongo/sets.js +++ b/src/database/mongo/sets.js @@ -7,7 +7,9 @@ module.exports = function (module) { if (!Array.isArray(value)) { value = [value]; } - + if (!value.length) { + return; + } value = value.map(v => helpers.valueToString(v)); await module.client.collection('objects').updateOne({ diff --git a/src/database/postgres/sets.js b/src/database/postgres/sets.js index ad540946aa..99894140cf 100644 --- a/src/database/postgres/sets.js +++ b/src/database/postgres/sets.js @@ -9,7 +9,9 @@ module.exports = function (module) { if (!Array.isArray(value)) { value = [value]; } - + if (!value.length) { + return; + } await module.transaction(async function (client) { await helpers.ensureLegacyObjectType(client, key, 'set'); await client.query({ diff --git a/src/groups/invite.js b/src/groups/invite.js index 9155aea172..93b69c20e5 100644 --- a/src/groups/invite.js +++ b/src/groups/invite.js @@ -51,44 +51,43 @@ module.exports = function (Groups) { await db.setsRemove(sets, uid); }; - Groups.invite = async function (groupName, uid) { - await inviteOrRequestMembership(groupName, uid, 'invite'); - const notification = await notifications.create({ + Groups.invite = async function (groupName, uids) { + uids = Array.isArray(uids) ? uids : [uids]; + await inviteOrRequestMembership(groupName, uids, 'invite'); + + const notificationData = await Promise.all(uids.map(uid => notifications.create({ type: 'group-invite', bodyShort: '[[groups:invited.notification_title, ' + groupName + ']]', bodyLong: '', nid: 'group:' + groupName + ':uid:' + uid + ':invite', path: '/groups/' + utils.slugify(groupName), - }); - await notifications.push(notification, [uid]); + }))); + + await Promise.all(uids.map((uid, index) => notifications.push(notificationData[index], uid))); }; - async function inviteOrRequestMembership(groupName, uid, type) { - if (!(parseInt(uid, 10) > 0)) { - throw new Error('[[error:not-logged-in]]'); - } - + async function inviteOrRequestMembership(groupName, uids, type) { + uids = Array.isArray(uids) ? uids : [uids]; + uids = uids.filter(uid => parseInt(uid, 10) > 0); const [exists, isMember, isPending, isInvited] = await Promise.all([ Groups.exists(groupName), - Groups.isMember(uid, groupName), - Groups.isPending(uid, groupName), - Groups.isInvited(uid, groupName), + Groups.isMembers(uids, groupName), + Groups.isPending(uids, groupName), + Groups.isInvited(uids, groupName), ]); if (!exists) { throw new Error('[[error:no-group]]'); - } else if (isMember || (type === 'invite' && isInvited)) { - return; - } else if (type === 'request' && isPending) { - throw new Error('[[error:group-already-requested]]'); } + uids = uids.filter((uid, i) => !isMember[i] && ((type === 'invite' && !isInvited[i]) || (type === 'request' && !isPending[i]))); + const set = type === 'invite' ? 'group:' + groupName + ':invited' : 'group:' + groupName + ':pending'; - await db.setAdd(set, uid); + await db.setAdd(set, uids); const hookName = type === 'invite' ? 'action:group.inviteMember' : 'action:group.requestMembership'; plugins.fireHook(hookName, { groupName: groupName, - uid: uid, + uids: uids, }); } diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js index e753f34bf7..bb0e9babb3 100644 --- a/src/socket.io/groups.js +++ b/src/socket.io/groups.js @@ -175,23 +175,18 @@ SocketGroups.issueMassInvite = async (socket, data) => { if (!data || !data.usernames || !data.groupName) { throw new Error('[[error:invalid-data]]'); } - var usernames = String(data.usernames).split(','); - usernames = usernames.map(function (username) { - return username && username.trim(); - }); + let usernames = String(data.usernames).split(','); + usernames = usernames.map(username => username && username.trim()); let uids = await user.getUidsByUsernames(usernames); - uids = uids.filter(function (uid) { - return !!uid && parseInt(uid, 10); - }); + uids = uids.filter(uid => !!uid && parseInt(uid, 10)); - // eslint-disable-next-line guard-for-in - for (const i in uids) { - // eslint-disable-next-line no-await-in-loop - await groups.invite(data.groupName, uids[i]); + await groups.invite(data.groupName, uids); + + for (const uid of uids) { logGroupEvent(socket, 'group-invite', { groupName: data.groupName, - targetUid: data.toUid, + targetUid: uid, }); } }; diff --git a/test/database/sets.js b/test/database/sets.js index d7390417ba..2ddc465f58 100644 --- a/test/database/sets.js +++ b/test/database/sets.js @@ -22,6 +22,14 @@ describe('Set methods', function () { done(); }); }); + + it('should not do anything if values array is empty', async function () { + await db.setAdd('emptyArraySet', []); + const members = await db.getSetMembers('emptyArraySet'); + const exists = await db.exists('emptyArraySet'); + assert.deepStrictEqual(members, []); + assert(!exists); + }); }); describe('getSetMembers()', function () {