From cd9977c94ea95614e2db64c32586889c851d1b71 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Tue, 13 Apr 2021 15:28:00 +0200 Subject: [PATCH] Add an API for setting affiliations This allows us to set affiliations in MUCs without having to first enter the MUC in order to create a `ChatRoom` instance. --- karma.conf.js | 1 + src/headless/plugins/muc/affiliations/api.js | 30 +++++++++++++ src/headless/plugins/muc/index.js | 2 + .../plugins/muc/tests/affiliations.js | 42 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/headless/plugins/muc/affiliations/api.js create mode 100644 src/headless/plugins/muc/tests/affiliations.js diff --git a/karma.conf.js b/karma.conf.js index 76288e14e..8a3c275a5 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -43,6 +43,7 @@ module.exports = function(config) { { pattern: "spec/user-details-modal.js", type: 'module' }, { pattern: "spec/utils.js", type: 'module' }, { pattern: "spec/xmppstatus.js", type: 'module' }, + { pattern: "src/headless/plugins/muc/tests/affiliations.js", type: 'module' }, { pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/chatbox.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/me-messages.js", type: 'module' }, diff --git a/src/headless/plugins/muc/affiliations/api.js b/src/headless/plugins/muc/affiliations/api.js new file mode 100644 index 000000000..f1000e059 --- /dev/null +++ b/src/headless/plugins/muc/affiliations/api.js @@ -0,0 +1,30 @@ +import { setAffiliations } from './utils.js'; + +export default { + /** + * The "affiliations" namespace groups methods relevant to setting and + * getting MUC affiliations. + * + * @namespace api.rooms.affiliations + * @memberOf api.rooms + */ + affiliations: { + /** + * Set the given affliation for the given JIDs in the specified MUCs + * + * @param { ('outcast'|'member'|'admin'|'owner') } affiliation - The affiliation to be set + * @param { String|Array } muc_jids - The JIDs of the MUCs in + * which the affiliation should be set. + * @param { Object[] } users - An array of objects representing users + * for whom the affiliation is to be set. + * @param { string } users[].jid - The JID of the user whose affiliation will change + * @param { Array } users[].affiliation - The new affiliation for this user + * @param { string } [users[].reason] - An optional reason for the affiliation change + */ + set (muc_jids, users) { + users = !Array.isArray(users) ? [users] : users; + muc_jids = !Array.isArray(muc_jids) ? [muc_jids] : muc_jids; + return setAffiliations(muc_jids, users); + } + } +} diff --git a/src/headless/plugins/muc/index.js b/src/headless/plugins/muc/index.js index f80d7fcab..57f616457 100644 --- a/src/headless/plugins/muc/index.js +++ b/src/headless/plugins/muc/index.js @@ -13,6 +13,7 @@ import ChatRoomOccupant from './occupant.js'; import ChatRoomOccupants from './occupants.js'; import log from '../../log'; import muc_api from './api.js'; +import affiliations_api from './affiliations/api.js'; import { computeAffiliationsDelta } from './affiliations/utils.js'; import u from '../../utils/form'; import { Collection } from '@converse/skeletor/src/collection'; @@ -268,6 +269,7 @@ converse.plugins.add('converse-muc', { // This is for tests (at least until we can import modules inside tests) converse.env.muc_utils = { computeAffiliationsDelta }; Object.assign(api, muc_api); + Object.assign(api.rooms, affiliations_api); /* https://xmpp.org/extensions/xep-0045.html * ---------------------------------------- diff --git a/src/headless/plugins/muc/tests/affiliations.js b/src/headless/plugins/muc/tests/affiliations.js new file mode 100644 index 000000000..f6f0092a7 --- /dev/null +++ b/src/headless/plugins/muc/tests/affiliations.js @@ -0,0 +1,42 @@ +/*global mock, converse */ + +const $pres = converse.env.$pres; +const Strophe = converse.env.Strophe; + +describe('The MUC Affiliations API', function () { + + it('can be used to set affiliations in MUCs without having to join them first', + mock.initConverse([], {}, async function (done, _converse) { + const { api } = _converse; + const user_jid = 'annoyingguy@montague.lit'; + const muc_jid = 'lounge@montague.lit'; + await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); + const presence = $pres({ + 'from': 'lounge@montague.lit/annoyingGuy', + 'id': '27C55F89-1C6A-459A-9EB5-77690145D624', + 'to': 'romeo@montague.lit/desktop' + }) + .c('x', { 'xmlns': 'http://jabber.org/protocol/muc#user' }) + .c('item', { + 'jid': user_jid, + 'affiliation': 'member', + 'role': 'participant' + }); + _converse.connection._dataRecv(mock.createRequest(presence)); + + api.rooms.affiliations.set(muc_jid, { 'jid': user_jid, 'affiliation': 'outcast', 'reason': 'Ban hammer!' }); + + const iq = _converse.connection.IQ_stanzas.pop(); + expect(Strophe.serialize(iq)).toBe( + `` + + `` + + `` + + `Ban hammer!` + + `` + + `` + + ``); + + done(); + }) + ); +});