# HG changeset patch # User Matthew Wild # Date 1660233893 -3600 # Node ID 84997bc3f92e5fbd8c5745a89be07f3434033672 # Parent cb19cb1c03d66c0520b427f6c9b3116d5098066e mod_firewall: Update for role-auth (backwards compatible) Probably worth investigating mod_compat_roles in the future. diff -r cb19cb1c03d6 -r 84997bc3f92e mod_firewall/README.markdown --- a/mod_firewall/README.markdown Wed Jul 13 11:27:44 2022 +0100 +++ b/mod_firewall/README.markdown Thu Aug 11 17:04:53 2022 +0100 @@ -435,8 +435,40 @@ NOT SENT DIRECTED PRESENCE TO SENDER? BOUNCE=service-unavailable +### Permissions + +Rules can consult Prosody's internal role and permissions system to check whether a certain action may +be performed. The acting entity, their role, and appropriate context is automatically inferred. All you +need to do is provide the identifier of the permission that should be checked. + + Condition Description + ----------------------- -------------------------------------------------------------------- + `MAY=permission` Checks whether 'permission' is allowed in the current context. + +As with all other conditions, `MAY` can be combined with `NOT` to negate the result of the check. + +Example, blocking outgoing stanzas from users with roles that do not allow the 'xmpp:federate' permission: + +``` +::deliver_remote +MAY NOT: xmpp:federate +BOUNCE=policy-violation (You are not allowed access to the federation) +``` + +### Roles + + Condition Matches + ---------------- ------------------------------------------------------------------------------------- + `TO ROLE` When the recipient JID of the stanza has the named role + `FROM ROLE` When the sender JID of the stanza has the named role + +**Note:** In most cases, you should avoid checking for specific roles, and instead check for +permissions granted by those roles (using the 'MAY' condition). + ### Admins +**Deprecated:** These conditions should no longer be used. Prefer 'MAY', 'TO ROLE' or 'FROM ROLE'. + Prosody allows certain JIDs to be declared as administrators of a host, component or the whole server. Condition Matches diff -r cb19cb1c03d6 -r 84997bc3f92e mod_firewall/conditions.lib.lua --- a/mod_firewall/conditions.lib.lua Wed Jul 13 11:27:44 2022 +0100 +++ b/mod_firewall/conditions.lib.lua Thu Aug 11 17:04:53 2022 +0100 @@ -175,22 +175,39 @@ return "not "..table.concat(code, " or "), { "group_contains", "bare_to", "bare_from" }; end +-- COMPAT w/0.12: Deprecated function condition_handlers.FROM_ADMIN_OF(host) return ("is_admin(bare_from, %s)"):format(host ~= "*" and metaq(host) or nil), { "is_admin", "bare_from" }; end +-- COMPAT w/0.12: Deprecated function condition_handlers.TO_ADMIN_OF(host) return ("is_admin(bare_to, %s)"):format(host ~= "*" and metaq(host) or nil), { "is_admin", "bare_to" }; end +-- COMPAT w/0.12: Deprecated function condition_handlers.FROM_ADMIN() return ("is_admin(bare_from, current_host)"), { "is_admin", "bare_from", "current_host" }; end +-- COMPAT w/0.12: Deprecated function condition_handlers.TO_ADMIN() return ("is_admin(bare_to, current_host)"), { "is_admin", "bare_to", "current_host" }; end +-- MAY: permission_to_check +function condition_handlers.MAY(permission_to_check) + return ("module:may(%q, event)"):format(permission_to_check); +end + +function condition_handlers.TO_ROLE(role_name) + return ("get_jid_role(bare_to, current_host) == %q"):format(role_name), { "get_jid_role", "current_host", "bare_to" }; +end + +function condition_handlers.FROM_ROLE(role_name) + return ("get_jid_role(bare_from, current_host) == %q"):format(role_name), { "get_jid_role", "current_host", "bare_from" }; +end + local day_numbers = { sun = 0, mon = 2, tue = 3, wed = 4, thu = 5, fri = 6, sat = 7 }; local function current_time_check(op, hour, minute) diff -r cb19cb1c03d6 -r 84997bc3f92e mod_firewall/mod_firewall.lua --- a/mod_firewall/mod_firewall.lua Wed Jul 13 11:27:44 2022 +0100 +++ b/mod_firewall/mod_firewall.lua Thu Aug 11 17:04:53 2022 +0100 @@ -6,6 +6,9 @@ local it = require "util.iterators"; local set = require "util.set"; +local have_features, features = pcall(require, "core.features"); +features = have_features and features.available or set.new(); + -- [definition_type] = definition_factory(param) local definitions = module:shared("definitions"); @@ -181,7 +184,8 @@ group_contains = { global_code = [[local group_contains = module:depends("groups").group_contains]]; }; - is_admin = { global_code = [[local is_admin = require "core.usermanager".is_admin;]]}; + is_admin = features:contains("permissions") and { global_code = [[local is_admin = require "core.usermanager".is_admin;]]} or nil; + get_jid_role = require "core.usermanager".get_jid_role and { global_code = [[local get_jid_role = require "core.usermanager".get_jid_role;]] } or nil; core_post_stanza = { global_code = [[local core_post_stanza = prosody.core_post_stanza;]] }; zone = { global_code = function (zone) local var = zone;