modtools: Don't show admin...

as assignable affiliation when the current user is an admin.

https://xmpp.org/extensions/xep-0045.html#affil-priv
This commit is contained in:
JC Brand 2020-06-22 10:45:53 +02:00
parent 7c29ae4a8a
commit 0120f78c87
2 changed files with 94 additions and 8 deletions

View File

@ -370,4 +370,86 @@ describe("The groupchat moderator tool", function () {
expect(user_els[0].textContent.trim()).toBe('Error: not allowed to fetch outcast list for MUC lounge@montague.lit');
done();
}));
it("doesn't allow admins to make more admins",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit';
const members = [
{'jid': 'hag66@shakespeare.lit', 'nick': 'witch', 'affiliation': 'member'},
{'jid': 'gower@shakespeare.lit', 'nick': 'gower', 'affiliation': 'member'},
{'jid': 'romeo@montague.lit', 'nick': 'romeo', 'affiliation': 'admin'},
];
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', [], members);
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => (view.model.occupants.length === 3));
const textarea = view.el.querySelector('.chat-textarea');
textarea.value = '/modtools';
const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
view.onKeyDown(enter);
await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
const modal = view.modtools_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const tab = modal.el.querySelector('#affiliations-tab');
// Clear so that we don't match older stanzas
_converse.connection.IQ_stanzas = [];
tab.click();
const show_affiliation_dropdown = modal.el.querySelector('.select-affiliation');
show_affiliation_dropdown.value = 'member';
const button = modal.el.querySelector('.btn-primary[name="users_with_affiliation"]');
button.click();
await u.waitUntil(() => !modal.loading_users_with_affiliation);
const user_els = modal.el.querySelectorAll('.list-group--users > li');
expect(user_els.length).toBe(2);
let change_affiliation_dropdown = user_els[0].querySelector('.select-affiliation');
expect(Array.from(change_affiliation_dropdown.options).map(o => o.value)).toEqual(['member', 'outcast', 'none']);
change_affiliation_dropdown = user_els[1].querySelector('.select-affiliation');
expect(Array.from(change_affiliation_dropdown.options).map(o => o.value)).toEqual(['member', 'outcast', 'none']);
done();
}));
it("lets the assignable affiliations and roles be configured via modtools_disable_assign",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
spyOn(_converse.ChatRoomView.prototype, 'showModeratorToolsModal').and.callThrough();
const muc_jid = 'lounge@montague.lit';
const members = [{'jid': 'romeo@montague.lit', 'nick': 'romeo', 'affiliation': 'owner'}];
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', [], members);
const view = _converse.chatboxviews.get(muc_jid);
const textarea = view.el.querySelector('.chat-textarea');
textarea.value = '/modtools';
const enter = { 'target': textarea, 'preventDefault': function preventDefault () {}, 'keyCode': 13 };
view.onKeyDown(enter);
await u.waitUntil(() => view.showModeratorToolsModal.calls.count());
const modal = view.modtools_modal;
const occupant = view.model.occupants.findWhere({'jid': _converse.bare_jid});
expect(modal.getAssignableAffiliations(occupant)).toEqual(['owner', 'admin', 'member', 'outcast', 'none']);
_converse.api.settings.set('modtools_disable_assign', ['owner']);
expect(modal.getAssignableAffiliations(occupant)).toEqual(['admin', 'member', 'outcast', 'none']);
_converse.api.settings.set('modtools_disable_assign', ['owner', 'admin']);
expect(modal.getAssignableAffiliations(occupant)).toEqual(['member', 'outcast', 'none']);
_converse.api.settings.set('modtools_disable_assign', ['owner', 'admin', 'outcast']);
expect(modal.getAssignableAffiliations(occupant)).toEqual(['member', 'none']);
expect(modal.getAssignableRoles(occupant)).toEqual(['moderator', 'participant', 'visitor']);
_converse.api.settings.set('modtools_disable_assign', ['admin', 'moderator']);
expect(modal.getAssignableRoles(occupant)).toEqual(['participant', 'visitor']);
done();
}));
});

View File

@ -4,7 +4,7 @@ import tpl_moderator_tools_modal from "../templates/moderator_tools_modal.js";
import { AFFILIATIONS, ROLES } from "@converse/headless/converse-muc.js";
import { BootstrapModal } from "../converse-modal.js";
import { __ } from '@converse/headless/i18n';
import { converse } from "@converse/headless/converse-core";
import { api, converse } from "@converse/headless/converse-core";
const { Strophe } = converse.env;
const u = converse.env.utils;
@ -66,23 +66,27 @@ export default BootstrapModal.extend({
},
getAssignableAffiliations (occupant) {
const disabled = _converse.modtools_disable_assign;
let disabled = api.settings.get('modtools_disable_assign');
if (!Array.isArray(disabled)) {
return disabled ? [] : AFFILIATIONS;
} else if (occupant.get('affiliation') === 'owner') {
disabled = disabled ? AFFILIATIONS : [];
}
if (occupant.get('affiliation') === 'owner') {
return AFFILIATIONS.filter(a => !disabled.includes(a));
} else if (occupant.get('affiliation') === 'admin') {
return AFFILIATIONS.filter(a => !['owner', ...disabled].includes(a));
return AFFILIATIONS.filter(a => !['owner', 'admin', ...disabled].includes(a));
} else {
return [];
}
},
getAssignableRoles (occupant) {
const disabled = _converse.modtools_disable_assign;
let disabled = api.settings.get('modtools_disable_assign');
if (!Array.isArray(disabled)) {
return disabled ? [] : ROLES;
} else if (occupant.get('role') === 'moderator') {
disabled = disabled ? ROLES : [];
}
if (occupant.get('role') === 'moderator') {
return ROLES.filter(r => !disabled.includes(r));
} else {
return [];