mod_firewall: Update for role-auth (backwards compatible)
Probably worth investigating mod_compat_roles in the future.
--- 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
--- 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)
--- 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;