comparison 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
comparison
equal deleted inserted replaced
5294:385346b6c81d 5295:98d5acb93439
1 local target_host = assert(module:get_option("authz_delegate_to")); 1 local target_host = assert(module:get_option("authz_delegate_to"));
2 local this_host = module:get_host(); 2 local this_host = module:get_host();
3 3
4 local array = require"util.array";
4 local jid_split = import("prosody.util.jid", "split"); 5 local jid_split = import("prosody.util.jid", "split");
5 6
6 local hosts = prosody.hosts; 7 local hosts = prosody.hosts;
7 8
8 function get_jids_with_role(role) --luacheck: ignore 212/role 9 function get_jids_with_role(role) --luacheck: ignore 212/role
51 function set_jid_role(jid) --luacheck: ignore 212/jid 52 function set_jid_role(jid) --luacheck: ignore 212/jid
52 -- TODO: figure out if there are actually legitimate uses for this... 53 -- TODO: figure out if there are actually legitimate uses for this...
53 return nil, "cannot set jid role on delegation target" 54 return nil, "cannot set jid role on delegation target"
54 end 55 end
55 56
57 local default_permission_queue = array{};
58
56 function add_default_permission(role_name, action, policy) 59 function add_default_permission(role_name, action, policy)
57 return hosts[target_host].authz.add_default_permission(role_name, action, policy) 60 -- NOTE: we always record default permissions, because the delegated-to
61 -- host may be re-activated.
62 default_permission_queue:push({
63 role_name = role_name,
64 action = action,
65 policy = policy,
66 });
67 local target_host_object = hosts[target_host];
68 local authz = target_host_object and target_host_object.authz;
69 if not authz then
70 module:log("debug", "queueing add_default_permission call for later, %s is not active yet", target_host);
71 return;
72 end
73 return authz.add_default_permission(role_name, action, policy)
58 end 74 end
59 75
60 function get_role_by_name(role_name) 76 function get_role_by_name(role_name)
61 return hosts[target_host].authz.get_role_by_name(role_name) 77 return hosts[target_host].authz.get_role_by_name(role_name)
62 end 78 end
63 79
64 function get_all_roles() 80 function get_all_roles()
65 return hosts[target_host].authz.get_all_roles() 81 return hosts[target_host].authz.get_all_roles()
66 end 82 end
83
84 module:hook_global("host-activated", function(host)
85 if host == target_host then
86 local authz = hosts[target_host].authz;
87 module:log("debug", "replaying %d queued permission changes", #default_permission_queue);
88 assert(authz);
89 -- replay default permission changes, if any
90 for i, item in ipairs(default_permission_queue) do
91 authz.add_default_permission(item.role_name, item.action, item.policy);
92 end
93 -- NOTE: we do not clear that array here -- in case the target_host is
94 -- re-activated
95 end
96 end, -10000)