# HG changeset patch # User Jonas Schäfer # Date 1680274602 -7200 # Node ID 98d5acb93439ce223ec3d42fed5a0d9563c3ca95 # Parent 385346b6c81ddee77853e0559966b46991a0bf7c 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. diff -r 385346b6c81d -r 98d5acb93439 mod_authz_delegate/mod_authz_delegate.lua --- 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)