Commit 802c9d1f authored by JC Brand's avatar JC Brand

Make it configurable how the affiliations delta is computed.

When inviting someone to a members-only room, you only want to add an
affiliation of 'member' if they don't already have any other affiliation.

So we need to ignore the "new" member if they're already on *any* of the lists.
parent 58f07cf1
......@@ -532,7 +532,7 @@
);
},
computeAffiliationsDelta: function (new_map, old_map, remove_absentees) {
computeAffiliationsDelta: function (exclude_existing, remove_absentees, new_map, old_map) {
/* Given two affiliation maps (JIDs mapped to
* affiliations), return a new map containing
* those JIDs that are new, changed or removed
......@@ -542,28 +542,36 @@
* same, for removed members, the affiliation is set to 'none'.
*
* Parameters:
* (Object) new_map: Map containing the new affiliations
* (Object) old_map: Map containing the old affiliations
* (Boolean) exclude_existing: Indicates whether JIDs from
* the new map which are also in the old map
* (regardless of affiliation) should be excluded
* from the delta. One reason to do this
* would be when you want to add a JID only if it
* doesn't have *any* existing affiliation at all.
* (Boolean) remove_absentees: Indicates whether JIDs
* from the old map which are not in the new map
* should be considered removed and therefore be
* included in the delta with affiliation set
* to 'none'.
* (Object) new_map: Map containing the new affiliations
* (Object) old_map: Map containing the old affiliations
*/
var delta = {};
var new_jids = _.keys(new_map);
var old_jids = _.keys(old_map);
var same_jids = _.intersection(new_jids, old_jids);
// Get the changed affiliations
_.each(same_jids, function (jid) {
if (new_map[jid] !== old_map[jid]) {
delta[jid] = new_map[jid];
}
});
// Get the new affiliations
_.each(_.difference(new_jids, old_jids), function (jid) {
delta[jid] = new_map[jid];
});
if (!exclude_existing) {
// Get the changed affiliations
_.each(same_jids, function (jid) {
if (new_map[jid] !== old_map[jid]) {
delta[jid] = new_map[jid];
}
});
}
if (remove_absentees) {
// Get the removed affiliations
_.each(_.difference(old_jids, new_jids), function (jid) {
......@@ -600,7 +608,31 @@
return converse.connection.sendIQ(iq, onSuccess, onError);
},
updateMemberLists: function (members, affiliations, remove_absentees) {
getJidsWithAffiliations: function (affiliations) {
/* Returns a map of JIDs that have the affiliations
* as provided.
*/
if (typeof affiliations === "string") {
affiliations = [affiliations];
}
var that = this;
var deferred = new $.Deferred();
var promises = [];
_.each(affiliations, function (affiliation) {
promises.push(that.requestMemberList(affiliation));
});
$.when.apply($, promises).always(function () {
var old_members = _.flatten(_.map(arguments, that.parseMemberListIQ));
old_members = _.reduce(old_members, function (memo, member) {
memo[member.jid] = member.affiliation;
return memo;
}, {});
deferred.resolve(old_members);
});
return deferred.promise();
},
updateMemberLists: function (members, affiliations, deltaFunc) {
/* Fetch the lists of users with the given affiliations.
* Then compute the delta between those users and
* the passed in members, and if it exists, send the delta
......@@ -610,10 +642,8 @@
* (Object) members: Map of member jids and affiliations.
* (String|Array) affiliation: An array of affiliations or
* a string if only one affiliation.
* (Boolean) remove_absentees: When computing the list
* delta, consider members from the old list that
* are not in the new list as removed (therefore their
* affiliation will get set to 'none').
* (Function) deltaFunc: The function to compute the delta
* between old and new member lists.
*
* Returns:
* A promise which is resolved once the list has been
......@@ -622,21 +652,12 @@
*/
var that = this;
var deferred = new $.Deferred();
if (typeof affiliations === "string") {
affiliations = [affiliations];
}
var promises = [];
_.each(affiliations, function (affiliation) {
promises.push(that.requestMemberList(affiliation));
});
$.when.apply($, promises).always(function () {
var old_members = _.flatten(_.map(arguments, that.parseMemberListIQ));
old_members = _.reduce(old_members, function (memo, member) {
memo[member.jid] = member.affiliation;
return memo;
}, {});
var delta = that.computeAffiliationsDelta(members, old_members, remove_absentees);
that.setAffiliations(delta, deferred.resolve, deferred.reject);
this.getJidsWithAffiliations(affiliations).then(function (old_members) {
that.setAffiliations(
deltaFunc(members, old_members),
deferred.resolve,
deferred.reject
);
});
return deferred.promise();
},
......@@ -650,11 +671,12 @@
*/
if (this.model.get('membersonly')) {
// When inviting to a members-only room, we first add
// the person to the member list, otherwise they won't
// be able to join.
var map = {};
map[recipient] = 'member';
this.updateMemberLists(map, ['member', 'owner', 'admin'], false);
// the person to the member list by giving them an
// affiliation of 'member' (if they're not affiliated
// already), otherwise they won't be able to join.
var map = {}; map[recipient] = 'member';
var deltaFunc = _.partial(this.computeAffiliationsDelta, true, false);
this.updateMemberLists(map, ['member', 'owner', 'admin'], deltaFunc);
}
var attrs = {
'xmlns': 'jabber:x:conference',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment