aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/mod_blocklist.lua
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/mod_blocklist.lua')
-rw-r--r--plugins/mod_blocklist.lua61
1 files changed, 37 insertions, 24 deletions
diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua
index 6b8ce16c..6587c8b1 100644
--- a/plugins/mod_blocklist.lua
+++ b/plugins/mod_blocklist.lua
@@ -9,34 +9,29 @@
-- This module implements XEP-0191: Blocking Command
--
-local user_exists = require"core.usermanager".user_exists;
-local rostermanager = require"core.rostermanager";
+local user_exists = require"prosody.core.usermanager".user_exists;
+local rostermanager = require"prosody.core.rostermanager";
local is_contact_subscribed = rostermanager.is_contact_subscribed;
local is_contact_pending_in = rostermanager.is_contact_pending_in;
local load_roster = rostermanager.load_roster;
local save_roster = rostermanager.save_roster;
-local st = require"util.stanza";
+local st = require"prosody.util.stanza";
local st_error_reply = st.error_reply;
-local jid_prep = require"util.jid".prep;
-local jid_split = require"util.jid".split;
+local jid_prep = require"prosody.util.jid".prep;
+local jid_split = require"prosody.util.jid".split;
local storage = module:open_store();
local sessions = prosody.hosts[module.host].sessions;
local full_sessions = prosody.full_sessions;
--- First level cache of blocklists by username.
--- Weak table so may randomly expire at any time.
-local cache = setmetatable({}, { __mode = "v" });
-
--- Second level of caching, keeps a fixed number of items, also anchors
--- items in the above cache.
+-- Cache of blocklists, keeps a fixed number of items.
--
-- The size of this affects how often we will need to load a blocklist from
-- disk, which we want to avoid during routing. On the other hand, we don't
-- want to use too much memory either, so this can be tuned by advanced
-- users. TODO use science to figure out a better default, 64 is just a guess.
-local cache_size = module:get_option_number("blocklist_cache_size", 64);
-local cache2 = require"util.cache".new(cache_size);
+local cache_size = module:get_option_integer("blocklist_cache_size", 256, 1);
+local blocklist_cache = require"prosody.util.cache".new(cache_size);
local null_blocklist = {};
@@ -48,12 +43,12 @@ local function set_blocklist(username, blocklist)
return ok, err;
end
-- Successful save, update the cache
- cache2:set(username, blocklist);
- cache[username] = blocklist;
+ blocklist_cache:set(username, blocklist);
return true;
end
-- Migrates from the old mod_privacy storage
+-- TODO mod_privacy was removed in 0.10.0, this should be phased out
local function migrate_privacy_list(username)
local legacy_data = module:open_store("privacy"):get(username);
if not legacy_data or not legacy_data.lists or not legacy_data.default then return; end
@@ -77,8 +72,15 @@ local function migrate_privacy_list(username)
return migrated_data;
end
+if not module:get_option_boolean("migrate_legacy_blocking", true) then
+ migrate_privacy_list = function (username)
+ module:log("debug", "Migrating from mod_privacy disabled, user '%s' will start with a fresh blocklist", username);
+ return nil;
+ end
+end
+
local function get_blocklist(username)
- local blocklist = cache2:get(username);
+ local blocklist = blocklist_cache:get(username);
if not blocklist then
if not user_exists(username, module.host) then
return null_blocklist;
@@ -90,9 +92,8 @@ local function get_blocklist(username)
if not blocklist then
blocklist = { [false] = { created = os.time(); }; };
end
- cache2:set(username, blocklist);
+ blocklist_cache:set(username, blocklist);
end
- cache[username] = blocklist;
return blocklist;
end
@@ -100,7 +101,7 @@ module:hook("iq-get/self/urn:xmpp:blocking:blocklist", function (event)
local origin, stanza = event.origin, event.stanza;
local username = origin.username;
local reply = st.reply(stanza):tag("blocklist", { xmlns = "urn:xmpp:blocking" });
- local blocklist = cache[username] or get_blocklist(username);
+ local blocklist = get_blocklist(username);
for jid in pairs(blocklist) do
if jid then
reply:tag("item", { jid = jid }):up();
@@ -159,7 +160,7 @@ local function edit_blocklist(event)
return true;
end
- local blocklist = cache[username] or get_blocklist(username);
+ local blocklist = get_blocklist(username);
local new_blocklist = {
-- We set the [false] key to something as a signal not to migrate privacy lists
@@ -233,8 +234,7 @@ module:hook("iq-set/self/urn:xmpp:blocking:unblock", edit_blocklist, -1);
-- Cache invalidation, solved!
module:hook_global("user-deleted", function (event)
if event.host == module.host then
- cache2:set(event.username, nil);
- cache[event.username] = nil;
+ blocklist_cache:set(event.username, nil);
end
end);
@@ -249,7 +249,7 @@ module:hook("iq-error/self/blocklist-push", function (event)
end);
local function is_blocked(user, jid)
- local blocklist = cache[user] or get_blocklist(user);
+ local blocklist = get_blocklist(user);
if blocklist[jid] then return true; end
local node, host = jid_split(jid);
return blocklist[host] or node and blocklist[node..'@'..host];
@@ -262,7 +262,20 @@ local function drop_stanza(event)
local to, from = attr.to, attr.from;
to = to and jid_split(to);
if to and from then
- return is_blocked(to, from);
+ if is_blocked(to, from) then
+ return true;
+ end
+
+ -- Check mediated MUC inviter
+ if stanza.name == "message" then
+ local invite = stanza:find("{http://jabber.org/protocol/muc#user}x/invite");
+ if invite then
+ from = jid_prep(invite.attr.from);
+ if is_blocked(to, from) then
+ return true;
+ end
+ end
+ end
end
end