Mercurial > prosody-modules
diff mod_authz_delegate/mod_authz_delegate.lua @ 5295:98d5acb93439
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.
author | Jonas Schäfer <jonas@wielicki.name> |
---|---|
date | Fri, 31 Mar 2023 16:56:42 +0200 |
parents | f61564b522f7 |
children |
line wrap: on
line diff
--- 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)