# HG changeset patch # User Kim Alvefur <zash@zash.se> # Date 1519504856 -3600 # Node ID 165d2877eeac82b4fbefba0211e110f5b41bd3c0 # Parent d958558e00585869e333614483ff2bf82d816584 mod_firewall: Add experimental user-centric persistent marks behind a feature flag diff -r d958558e0058 -r 165d2877eeac mod_firewall/actions.lib.lua --- a/mod_firewall/actions.lib.lua Sat Feb 24 19:38:10 2018 +0100 +++ b/mod_firewall/actions.lib.lua Sat Feb 24 21:40:56 2018 +0100 @@ -213,6 +213,14 @@ return [[session.firewall_marked_]]..idsafe(name)..[[ = nil;]] end +function action_handlers.MARK_USER(name) + return [[if session.firewall_marks then session.firewall_marks.]]..idsafe(name)..[[ = current_timestamp; end]], { "timestamp" }; +end + +function action_handlers.UNMARK_USER(name) + return [[if session.firewall_marks then session.firewall_marks.]]..idsafe(name)..[[ = nil; end]], { "timestamp" }; +end + function action_handlers.ADD_TO(spec) local list_name, value = spec:match("(%S+) (.+)"); local meta_deps = {}; diff -r d958558e0058 -r 165d2877eeac mod_firewall/conditions.lib.lua --- a/mod_firewall/conditions.lib.lua Sat Feb 24 19:38:10 2018 +0100 +++ b/mod_firewall/conditions.lib.lua Sat Feb 24 21:40:56 2018 +0100 @@ -276,6 +276,20 @@ return ("not not session.firewall_marked_"..idsafe(name)); end +function condition_handlers.USER_MARKED(name_and_time) + local name, time = name_and_time:match("^%s*([%w_]+)%s+%(([^)]+)s%)%s*$"); + if not name then + name = name_and_time:match("^%s*([%w_]+)%s*$"); + end + if not name then + error("Error parsing mark name, see documentation for usage examples"); + end + if time then + return ("(current_timestamp - (session.firewall_marks and session.firewall_marks.%s or 0)) < %d"):format(idsafe(name), tonumber(time)), { "timestamp" }; + end + return ("not not (session.firewall_marks and session.firewall_marks."..idsafe(name)..")"); +end + function condition_handlers.SENT_DIRECTED_PRESENCE_TO_SENDER() return "not not (session.directed and session.directed[from])", { "from" }; end diff -r d958558e0058 -r 165d2877eeac mod_firewall/marks.lib.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_firewall/marks.lib.lua Sat Feb 24 21:40:56 2018 +0100 @@ -0,0 +1,23 @@ +local mark_storage = module:open_store("firewall_marks"); + +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("resource-unbind", function (event) + local session = event.session; + local username = session.username; + local marks = session.firewall_marks; + mark_storage:set(username, marks); +end); + diff -r d958558e0058 -r 165d2877eeac mod_firewall/mod_firewall.lua --- a/mod_firewall/mod_firewall.lua Sat Feb 24 19:38:10 2018 +0100 +++ b/mod_firewall/mod_firewall.lua Sat Feb 24 21:40:56 2018 +0100 @@ -303,6 +303,10 @@ local condition_handlers = module:require("conditions"); local action_handlers = module:require("actions"); +if module:get_option_boolean("firewall_experimental_user_marks", false) then + module:require"marks"; +end + local function new_rule(ruleset, chain) assert(chain, "no chain specified"); local rule = { conditions = {}, actions = {}, deps = {} };