MUC: Add ad-hoc command setting affiliation in a room (fixes #1174)
authorKim Alvefur <zash@zash.se>
Sat, 21 Mar 2020 00:00:50 +0100
changeset 10702 e4034f6668a5
parent 10701 08ec83f90ce0
child 10705 929c95e518f0
MUC: Add ad-hoc command setting affiliation in a room (fixes #1174) This gives service admins a way to set an arbitrary affiliation in any room. Enables various administrative use cases such as room ownership reassignment or recovery. Reduces the need for the admins-as-owners feature, as this can be used by admins to make themselves owner in any room when needed, instead of being owners all the time.
plugins/muc/mod_muc.lua
--- a/plugins/muc/mod_muc.lua	Fri Mar 20 18:52:41 2020 +0100
+++ b/plugins/muc/mod_muc.lua	Sat Mar 21 00:00:50 2020 +0100
@@ -499,6 +499,7 @@
 	local t_concat = table.concat;
 	local adhoc_new = module:require "adhoc".new;
 	local adhoc_initial = require "util.adhoc".new_initial_data_form;
+	local adhoc_simple = require "util.adhoc".new_simple_form;
 	local array = require "util.array";
 	local dataforms_new = require "util.dataforms".new;
 
@@ -529,4 +530,46 @@
 		"http://prosody.im/protocol/muc#destroy", destroy_rooms_handler, "admin");
 
 	module:provides("adhoc", destroy_rooms_desc);
+
+
+	local set_affiliation_layout = dataforms_new {
+		-- FIXME wordsmith title, instructions, labels etc
+		title = "Set affiliation";
+
+		{ name = "FORM_TYPE", type = "hidden", value = "http://prosody.im/protocol/muc#set-affiliation" };
+		{ name = "room", type = "jid-single", required = true, label = "Room"};
+		{ name = "jid", type = "jid-single", required = true, label = "JID"};
+		{ name = "affiliation", type = "list-single", required = true, label = "Affiliation",
+			options = { "owner"; "admin"; "member"; "none"; "outcast"; },
+		};
+		{ name = "reason", type = "text-single", "Reason", }
+	};
+
+	local set_affiliation_handler = adhoc_simple(set_affiliation_layout, function (fields, errors)
+		if errors then
+			local errmsg = {};
+			for field, err in pairs(errors) do
+				errmsg[#errmsg + 1] = field .. ": " .. err;
+			end
+			return { status = "completed", error = { message = t_concat(errmsg, "\n") } };
+		end
+
+		local room = get_room_from_jid(fields.room);
+		if not room then
+			return { status = "canceled", error = { message =  "No such room"; }; };
+		end
+		local ok, err, condition = room:set_affiliation(true, fields.jid, fields.affiliation, fields.reason);
+
+		if not ok then
+			return { status = "canceled", error = { message =  "Affiliation change failed: "..err..":"..condition; }; };
+		end
+
+		return { status = "completed", info = "Affiliation updated",
+		};
+	end);
+
+	local set_affiliation_desc = adhoc_new("Set affiliation in room",
+		"http://prosody.im/protocol/muc#set-affiliation", set_affiliation_handler, "admin");
+
+	module:provides("adhoc", set_affiliation_desc);
 end