aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2024-05-23 17:39:20 +0100
committerMatthew Wild <mwild1@gmail.com>2024-05-23 17:39:20 +0100
commitaa6b79c20c82451cd6a804d82c98d0830e792033 (patch)
tree7eb9e34a9056c912cd738b1990977015e9380a5a
parent5915d6fbcdc338efa23a79a47ca72eb42182f752 (diff)
downloadprosody-aa6b79c20c82451cd6a804d82c98d0830e792033.tar.gz
prosody-aa6b79c20c82451cd6a804d82c98d0830e792033.zip
MUC: Add per-room PM restriction functionality (thanks Wirlaburla)
Based on mod_muc_restrict_pm in prosody-modules d82c0383106a
-rw-r--r--plugins/muc/mod_muc.lua8
-rw-r--r--plugins/muc/restrict_pm.lib.lua119
2 files changed, 127 insertions, 0 deletions
diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua
index b3f30eed..7244ecbe 100644
--- a/plugins/muc/mod_muc.lua
+++ b/plugins/muc/mod_muc.lua
@@ -86,6 +86,12 @@ room_mt.get_registered_nick = register.get_registered_nick;
room_mt.get_registered_jid = register.get_registered_jid;
room_mt.handle_register_iq = register.handle_register_iq;
+local restrict_pm = module:require "muc/restrict_pm";
+room_mt.get_allow_pm = restrict_pm.get_allow_pm;
+room_mt.set_allow_pm = restrict_pm.set_allow_pm;
+room_mt.get_allow_modpm = restrict_pm.get_allow_modpm;
+room_mt.set_allow_modpm = restrict_pm.set_allow_modpm;
+
local presence_broadcast = module:require "muc/presence_broadcast";
room_mt.get_presence_broadcast = presence_broadcast.get;
room_mt.set_presence_broadcast = presence_broadcast.set;
@@ -293,6 +299,8 @@ local function set_room_defaults(room, lang)
room:set_language(lang or module:get_option_string("muc_room_default_language"));
room:set_presence_broadcast(module:get_option_enum("muc_room_default_presence_broadcast", room:get_presence_broadcast(), "visitor", "participant",
"moderator"));
+ room:set_allow_pm(module:get_option_enum("muc_room_default_allow_pm", room:get_allow_pm(), "visitor", "participant", "moderator"));
+ room:set_allow_modpm(module:get_option_boolean("muc_room_default_always_allow_moderator_pms", room:get_allow_modpm()));
end
function create_room(room_jid, config)
diff --git a/plugins/muc/restrict_pm.lib.lua b/plugins/muc/restrict_pm.lib.lua
new file mode 100644
index 00000000..e0b25cc8
--- /dev/null
+++ b/plugins/muc/restrict_pm.lib.lua
@@ -0,0 +1,119 @@
+-- Based on code from mod_muc_restrict_pm in prosody-modules@d82c0383106a
+-- by Nicholas George <wirlaburla@worlio.com>
+
+local st = require "util.stanza";
+local muc_util = module:require "muc/util";
+local valid_roles = muc_util.valid_roles;
+
+-- COMPAT w/ prosody-modules allow_pm
+local compat_map = {
+ everyone = "visitor";
+ participants = "participant";
+ moderators = "moderator";
+ members = "affiliated";
+};
+
+local function get_allow_pm(room)
+ local val = room._data.allow_pm;
+ return compat_map[val] or val or "visitor";
+end
+
+local function set_allow_pm(room, val)
+ if get_allow_pm(room) == val then return false; end
+ room._data.allow_pm = val;
+ return true;
+end
+
+local function get_allow_modpm(room)
+ return room._data.allow_modpm or false;
+end
+
+local function set_allow_modpm(room, val)
+ if get_allow_modpm(room) == val then return false; end
+ room._data.allow_modpm = val;
+ return true;
+end
+
+module:hook("muc-config-form", function(event)
+ local pmval = get_allow_pm(event.room);
+ table.insert(event.form, {
+ name = 'muc#roomconfig_allowpm';
+ type = 'list-single';
+ label = 'Allow private messages from';
+ options = {
+ { value = 'visitor', label = 'Everyone', default = pmval == 'visitor' };
+ { value = 'participant', label = 'Participants', default = pmval == 'participant' };
+ { value = 'moderator', label = 'Moderators', default = pmval == 'moderator' };
+ { value = 'affiliated', label = "Members", default = pmval == "affiliated" };
+ { value = 'none', label = 'No one', default = pmval == 'none' };
+ }
+ });
+ table.insert(event.form, {
+ name = '{xmpp:prosody.im}muc#allow_modpm';
+ type = 'boolean';
+ label = 'Always allow private messages to moderators';
+ value = get_allow_modpm(event.room)
+ });
+end);
+
+module:hook("muc-config-submitted/muc#roomconfig_allowpm", function(event)
+ if set_allow_pm(event.room, event.value) then
+ event.status_codes["104"] = true;
+ end
+end);
+
+module:hook("muc-config-submitted/{xmpp:prosody.im}muc#allow_modpm", function(event)
+ if set_allow_modpm(event.room, event.value) then
+ event.status_codes["104"] = true;
+ end
+end);
+
+local who_restricted = {
+ none = "in this group";
+ participant = "from guests";
+ moderator = "from non-moderators";
+ affiliated = "from non-members";
+};
+
+module:hook("muc-private-message", function(event)
+ local stanza, room = event.stanza, event.room;
+ local from_occupant = room:get_occupant_by_nick(stanza.attr.from);
+ local to_occupant = room:get_occupant_by_nick(stanza.attr.to);
+
+ -- To self is always okay
+ if to_occupant.bare_jid == from_occupant.bare_jid then return; end
+
+ if get_allow_modpm(room) then
+ if to_occupant and to_occupant.role == 'moderator'
+ or from_occupant and from_occupant.role == "moderator" then
+ return; -- Allow to/from moderators
+ end
+ end
+
+ local pmval = get_allow_pm(room);
+
+ if pmval ~= "none" then
+ if pmval == "affiliated" and room:get_affiliation(from_occupant.bare_jid) then
+ return; -- Allow from affiliated users
+ elseif valid_roles[from_occupant.role] >= valid_roles[pmval] then
+ module:log("debug", "Allowing PM: %s(%d) >= %s(%d)", from_occupant.role, valid_roles[from_occupant.role], pmval, valid_roles[pmval]);
+ return; -- Allow from a permitted role
+ end
+ end
+
+ local msg = ("Private messages are restricted %s"):format(who_restricted[pmval]);
+ module:log("debug", "Blocking PM from %s %s: %s", from_occupant.role, stanza.attr.from, msg);
+
+ room:route_to_occupant(
+ from_occupant,
+ st.error_reply(stanza, "cancel", "policy-violation", msg, room.jid)
+ );
+ return false;
+end, 1);
+
+return {
+ get_allow_pm = get_allow_pm;
+ set_allow_pm = set_allow_pm;
+ get_allow_modpm = get_allow_modpm;
+ set_allow_modpm = set_allow_modpm;
+};