# HG changeset patch # User Matthew Wild # Date 1686237642 -3600 # Node ID 96dec7681af80ff9c16ed47185fdc8f7273b0d6d # Parent eeccec0955a1c4ab9ec393b194f241e8849b5bfb mod_firewall: Update user marks to store instantly via map store The original approach was to keep marks in memory only, and persist them at shutdown. That saves I/O, at the cost of potentially losing marks on an unclean shutdown. This change persists marks instantly, which may have some performance overhead but should be more "correct". It also splits the marking/unmarking into an event which may be watched or even fired by other modules. diff -r eeccec0955a1 -r 96dec7681af8 mod_firewall/actions.lib.lua --- a/mod_firewall/actions.lib.lua Thu Jun 08 16:17:25 2023 +0100 +++ b/mod_firewall/actions.lib.lua Thu Jun 08 16:20:42 2023 +0100 @@ -220,11 +220,22 @@ end function action_handlers.MARK_USER(name) - return [[if session.firewall_marks then session.firewall_marks.]]..idsafe(name)..[[ = current_timestamp; end]], { "timestamp" }; + return ([[if session.firewall_marks then + fire_event("firewall/marked/user", { + username = session.username; + mark = %q; + timestamp = current_timestamp; + }); + end]]):format(idsafe(name)), { "timestamp" }; end function action_handlers.UNMARK_USER(name) - return [[if session.firewall_marks then session.firewall_marks.]]..idsafe(name)..[[ = nil; end]], { "timestamp" }; + return ([[if session.firewall_marks then + fire_event("firewall/unmarked/user", { + username = session.username; + mark = %q; + }); + end]]):format(idsafe(name)); end function action_handlers.ADD_TO(spec) diff -r eeccec0955a1 -r 96dec7681af8 mod_firewall/marks.lib.lua --- a/mod_firewall/marks.lib.lua Thu Jun 08 16:17:25 2023 +0100 +++ b/mod_firewall/marks.lib.lua Thu Jun 08 16:20:42 2023 +0100 @@ -1,4 +1,5 @@ local mark_storage = module:open_store("firewall_marks"); +local mark_map_storage = module:open_store("firewall_marks", "map"); local user_sessions = prosody.hosts[module.host].sessions; @@ -14,10 +15,26 @@ session.firewall_marks = marks; end); -module:hook("resource-unbind", function (event) - local session = event.session; - local username = session.username; - local marks = session.firewall_marks; - mark_storage:set(username, marks); -end); +module:hook("firewall/marked/user", function (event) + local user = user_sessions[event.username]; + local marks = user and user.firewall_marks; + if marks then + marks[event.mark] = event.timestamp; + end + local ok, err = mark_map_storage:set(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 +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_map_storage:set(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 +end, 1);