mod_authz_delegate: make resistant against startup order issues
There is no guarantee that the target_host gets activated and
initialized before the host this module is loaded on. As
add_default_permission is called during load time by many modules,
we need to be prepared to queue stuff.
--- a/mod_authz_delegate/mod_authz_delegate.lua Thu Mar 30 11:32:50 2023 +0100
+++ b/mod_authz_delegate/mod_authz_delegate.lua Fri Mar 31 16:56:42 2023 +0200
@@ -1,6 +1,7 @@
local target_host = assert(module:get_option("authz_delegate_to"));
local this_host = module:get_host();
+local array = require"util.array";
local jid_split = import("prosody.util.jid", "split");
local hosts = prosody.hosts;
@@ -53,8 +54,23 @@
return nil, "cannot set jid role on delegation target"
end
+local default_permission_queue = array{};
+
function add_default_permission(role_name, action, policy)
- return hosts[target_host].authz.add_default_permission(role_name, action, policy)
+ -- NOTE: we always record default permissions, because the delegated-to
+ -- host may be re-activated.
+ default_permission_queue:push({
+ role_name = role_name,
+ action = action,
+ policy = policy,
+ });
+ local target_host_object = hosts[target_host];
+ local authz = target_host_object and target_host_object.authz;
+ if not authz then
+ module:log("debug", "queueing add_default_permission call for later, %s is not active yet", target_host);
+ return;
+ end
+ return authz.add_default_permission(role_name, action, policy)
end
function get_role_by_name(role_name)
@@ -64,3 +80,17 @@
function get_all_roles()
return hosts[target_host].authz.get_all_roles()
end
+
+module:hook_global("host-activated", function(host)
+ if host == target_host then
+ local authz = hosts[target_host].authz;
+ module:log("debug", "replaying %d queued permission changes", #default_permission_queue);
+ assert(authz);
+ -- replay default permission changes, if any
+ for i, item in ipairs(default_permission_queue) do
+ authz.add_default_permission(item.role_name, item.action, item.policy);
+ end
+ -- NOTE: we do not clear that array here -- in case the target_host is
+ -- re-activated
+ end
+end, -10000)