Mercurial > prosody-modules
view mod_firewall/marks.lib.lua @ 6556:7477e97a9045
mod_firewall: Apply pre-reload state before re-reading config
This change makes load/reload a bit more robust. module.load() runs before
module.restore() and it reads from the config and updates the state (if
needed).
However, after this, module.restore() could run and apply the old state again.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sun, 24 May 2026 20:03:20 +0100 |
| parents | f9d93d7cd6d5 |
| children | 2d916ba3253c |
line wrap: on
line source
local mark_storage = module:open_store("firewall_marks", "keyval+"); local user_sessions = prosody.hosts[module.host].sessions; module:hook("resource-bind", function (event) local session = event.session; local username = session.username; local user = user_sessions[username]; local marks = user.firewall_marks; if not marks then marks = mark_storage:get(username) or {}; user.firewall_marks = marks; -- luacheck: ignore 122 end session.firewall_marks = marks; end); module:hook("firewall/marked/user", function (event) local user = user_sessions[event.username]; local marks = user and user.firewall_marks; if user and not marks then -- Load marks from storage to cache on the user object marks = mark_storage:get(event.username) or {}; user.firewall_marks = marks; --luacheck: ignore 122 end if marks then marks[event.mark] = event.timestamp; end local ok, err = mark_storage:set_key(event.username, event.mark, event.timestamp); if not ok then module:log("error", "Failed to mark user %q with %q: %s", event.username, event.mark, err); end return true; end, -1); module:hook("firewall/unmarked/user", function (event) local user = user_sessions[event.username]; local marks = user and user.firewall_marks; if marks then marks[event.mark] = nil; end local ok, err = mark_storage:set_key(event.username, event.mark, nil); if not ok then module:log("error", "Failed to unmark user %q with %q: %s", event.username, event.mark, err); end return true; end, -1); module:add_item("shell-command", { section = "firewall"; section_desc = "mod_firewall commands"; name = "mark"; desc = "Add a firewall mark to a user account"; args = { { name = "user_jid", type = "string" }; { name = "mark_name", type = "string" }; }; host_selector = "user_jid"; handler = function(self, user_jid, mark_name) --luacheck: ignore 212/self 212/host local username, host = jid.split(user_jid); if not username or not hosts[host] then return nil, "Invalid JID supplied"; elseif not idsafe(mark_name) then return nil, "Invalid characters in mark name"; end if not module:fire_event("firewall/marked/user", { username = session.username; mark = mark_name; timestamp = os.time(); }) then return nil, "Failed to set mark"; end return true, "Marked"; end; }); module:add_item("shell-command", { section = "firewall"; section_desc = "mod_firewall commands"; name = "unmark"; desc = "Remove a firewall mark from a user account"; args = { { name = "user_jid", type = "string" }; { name = "mark_name", type = "string" }; }; host_selector = "user_jid"; handler = function(self, user_jid, mark_name) --luacheck: ignore 212/self 212/host local username, host = jid.split(user_jid); if not username or not hosts[host] then return nil, "Invalid JID supplied"; elseif not idsafe(mark_name) then return nil, "Invalid characters in mark name"; end if not module:fire_event("firewall/unmarked/user", { username = session.username; mark = mark_name; timestamp = os.time(); }) then return nil, "Failed to remove mark"; end return true, "Unmarked"; end; }); module:add_item("shell-command", { section = "firewall"; section_desc = "mod_firewall commands"; name = "marked"; desc = "List all user accounts with a specific firewall mark"; args = { { name = "host", type = "string" }; { name = "mark_name", type = "string" }; }; host_selector = "host"; handler = function(self, host, mark_name) --luacheck: ignore 212/self 212/host if not idsafe(mark_name) then return nil, "Invalid characters in mark name"; end local users = mark_storage:get_key_from_all(mark_name); local usernames = {}; for username in it.keys(users) do table.insert(usernames, username); end table.sort(usernames, function (a, b) return users[a] < users[b]; end); for _, username in ipairs(usernames) do self.session.print(username, os.date("%Y-%m-%d %R:%s", users[username]); end return true, ("Showing %d users"):format(#usernames); end; });
