changeset 1954:050cd7b6fa96

mod_muc_access_control: Module to allow restricting rooms to a list of JIDs, which can include domains
author Matthew Wild <mwild1@gmail.com>
date Sun, 22 Nov 2015 19:33:09 +0000 (2015-11-22)
parents 0c3ba5ff7a3b
children 1a5be0ecc876
files mod_muc_access_control/mod_muc_access_control.lua
diffstat 1 files changed, 57 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_muc_access_control/mod_muc_access_control.lua	Sun Nov 22 19:33:09 2015 +0000
@@ -0,0 +1,57 @@
+local st = require "util.stanza";
+local jid = require "util.jid";
+local nodeprep = require "util.encodings".stringprep.nodeprep;
+
+local unprepped_access_lists = module:get_option("muc_access_lists", {});
+local access_lists = {};
+
+-- Make sure all input is prepped
+for unprepped_room_name, unprepped_list in pairs(unprepped_access_lists) do
+	local prepped_room_name = nodeprep(unprepped_room_name);
+	if not prepped_room_name then
+		module:log("error", "Invalid room name: %s", unprepped_room_name);
+	else
+		local prepped_list = {};
+		for _, unprepped_jid in ipairs(unprepped_list) do
+			local prepped_jid = jid.prep(jid);
+			if not prepped_jid then
+				module:log("error", "Invalid JID: %s", unprepped_jid);
+			else
+				table.insert(prepped_list, jid.pep(jid));
+			end
+		end
+	end
+end
+
+local function is_restricted(room, who)
+	local allowed = access_lists[room];
+
+	if allowed == nil or allowed[who] or allowed[select(2, jid.split(who))] then
+		return nil;
+	end
+
+	return "forbidden";
+end
+
+module:hook("presence/full", function(event)
+        local stanza = event.stanza;
+
+        if stanza.name == "presence" and stanza.attr.type == "unavailable" then   -- Leaving events get discarded
+                return;
+        end
+
+	-- Get the room
+	local room = jid.split(stanza.attr.to);
+        if not room then return; end
+
+	-- Get who has tried to join it
+	local who = jid.bare(stanza.attr.from)
+
+	-- Checking whether room is restricted
+	local check_restricted = is_restricted(room, who)
+        if check_restricted ~= nil then
+                event.allowed = false;
+                event.stanza.attr.type = 'error';
+	        return event.origin.send(st.error_reply(event.stanza, "cancel", "forbidden", "You're not allowed to enter this room: " .. check_restricted));
+        end
+end, 10);