Comparison

core/usermanager.lua @ 12674:72f431b4dc2c

Merge role-auth->trunk
author Matthew Wild <mwild1@gmail.com>
date Mon, 22 Aug 2022 13:53:35 +0100
parent 12667:0278987b8687
child 12683:75f0c69eba71
comparison
equal deleted inserted replaced
12639:6d9ee0a3eb4b 12674:72f431b4dc2c
7 -- 7 --
8 8
9 local modulemanager = require "core.modulemanager"; 9 local modulemanager = require "core.modulemanager";
10 local log = require "util.logger".init("usermanager"); 10 local log = require "util.logger".init("usermanager");
11 local type = type; 11 local type = type;
12 local it = require "util.iterators";
13 local jid_bare = require "util.jid".bare;
14 local jid_split = require "util.jid".split; 12 local jid_split = require "util.jid".split;
15 local jid_prep = require "util.jid".prep;
16 local config = require "core.configmanager"; 13 local config = require "core.configmanager";
17 local sasl_new = require "util.sasl".new; 14 local sasl_new = require "util.sasl".new;
18 local storagemanager = require "core.storagemanager"; 15 local storagemanager = require "core.storagemanager";
19 local set = require "util.set";
20 16
21 local prosody = _G.prosody; 17 local prosody = _G.prosody;
22 local hosts = prosody.hosts; 18 local hosts = prosody.hosts;
23 19
24 local setmetatable = setmetatable; 20 local setmetatable = setmetatable;
25 21
26 local default_provider = "internal_hashed"; 22 local default_provider = "internal_hashed";
23
24 local debug = debug;
27 25
28 local _ENV = nil; 26 local _ENV = nil;
29 -- luacheck: std none 27 -- luacheck: std none
30 28
31 local function new_null_provider() 29 local function new_null_provider()
34 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, { 32 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, {
35 __index = function(self, method) return dummy; end --luacheck: ignore 212 33 __index = function(self, method) return dummy; end --luacheck: ignore 212
36 }); 34 });
37 end 35 end
38 36
39 local global_admins_config = config.get("*", "admins"); 37 local fallback_authz_provider = {
40 if type(global_admins_config) ~= "table" then 38 -- luacheck: ignore 212
41 global_admins_config = nil; -- TODO: factor out moduleapi magic config handling and use it here 39 get_jids_with_role = function (role) end;
42 end 40
43 local global_admins = set.new(global_admins_config) / jid_prep; 41 get_user_role = function (user) end;
44 42 set_user_role = function (user, role_name) end;
45 local admin_role = { ["prosody:admin"] = true }; 43
46 local global_authz_provider = { 44 get_user_secondary_roles = function (user) end;
47 get_user_roles = function (user) end; --luacheck: ignore 212/user 45 add_user_secondary_role = function (user, host, role_name) end;
48 get_jid_roles = function (jid) 46 remove_user_secondary_role = function (user, host, role_name) end;
49 if global_admins:contains(jid) then 47
50 return admin_role; 48 user_can_assume_role = function(user, role_name) end;
51 end 49
52 end; 50 get_jid_role = function (jid) end;
53 get_jids_with_role = function (role) 51 set_jid_role = function (jid, role) end;
54 if role ~= "prosody:admin" then return {}; end 52
55 return it.to_array(global_admins); 53 get_users_with_role = function (role_name) end;
56 end; 54 add_default_permission = function (role_name, action, policy) end;
57 set_user_roles = function (user, roles) end; -- luacheck: ignore 212 55 get_role_by_name = function (role_name) end;
58 set_jid_roles = function (jid, roles) end; -- luacheck: ignore 212
59 }; 56 };
60 57
61 local provider_mt = { __index = new_null_provider() }; 58 local provider_mt = { __index = new_null_provider() };
62 59
63 local function initialize_host(host) 60 local function initialize_host(host)
64 local host_session = hosts[host]; 61 local host_session = hosts[host];
65 62
66 local authz_provider_name = config.get(host, "authorization") or "internal"; 63 local authz_provider_name = config.get(host, "authorization") or "internal";
67 64
68 local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name); 65 local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name);
69 host_session.authz = authz_mod or global_authz_provider; 66 host_session.authz = authz_mod or fallback_authz_provider;
70 67
71 if host_session.type ~= "local" then return; end 68 if host_session.type ~= "local" then return; end
72 69
73 host_session.events.add_handler("item-added/auth-provider", function (event) 70 host_session.events.add_handler("item-added/auth-provider", function (event)
74 local provider = event.item; 71 local provider = event.item;
114 prosody.events.fire_event("user-password-changed", { username = username, host = host, resource = resource }); 111 prosody.events.fire_event("user-password-changed", { username = username, host = host, resource = resource });
115 end 112 end
116 return ok, err; 113 return ok, err;
117 end 114 end
118 115
116 local function get_account_info(username, host)
117 local method = hosts[host].users.get_account_info;
118 if not method then return nil, "method-not-supported"; end
119 return method(username);
120 end
121
119 local function user_exists(username, host) 122 local function user_exists(username, host)
120 if hosts[host].sessions[username] then return true; end 123 if hosts[host].sessions[username] then return true; end
121 return hosts[host].users.user_exists(username); 124 return hosts[host].users.user_exists(username);
122 end 125 end
123 126
142 145
143 local function get_provider(host) 146 local function get_provider(host)
144 return hosts[host].users; 147 return hosts[host].users;
145 end 148 end
146 149
147 local function get_roles(jid, host) 150 local function get_user_role(user, host)
148 if host and not hosts[host] then return false; end 151 if host and not hosts[host] then return false; end
149 if type(jid) ~= "string" then return false; end 152 if type(user) ~= "string" then return false; end
150 153
151 jid = jid_bare(jid); 154 return hosts[host].authz.get_user_role(user);
152 host = host or "*"; 155 end
153 156
154 local actor_user, actor_host = jid_split(jid); 157 local function set_user_role(user, host, role_name)
155 local roles; 158 if host and not hosts[host] then return false; end
156 159 if type(user) ~= "string" then return false; end
157 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; 160
158 161 local role, err = hosts[host].authz.set_user_role(user, role_name);
159 if actor_user and actor_host == host then -- Local user 162 if role then
160 roles = authz_provider.get_user_roles(actor_user); 163 prosody.events.fire_event("user-role-changed", {
161 else -- Remote user/JID 164 username = user, host = host, role = role;
162 roles = authz_provider.get_jid_roles(jid); 165 });
163 end 166 end
164 167 return role, err;
165 return roles; 168 end
166 end 169
167 170 local function user_can_assume_role(user, host, role_name)
168 local function set_roles(jid, host, roles) 171 if host and not hosts[host] then return false; end
169 if host and not hosts[host] then return false; end 172 if type(user) ~= "string" then return false; end
170 if type(jid) ~= "string" then return false; end 173
171 174 return hosts[host].authz.user_can_assume_role(user, role_name);
172 jid = jid_bare(jid); 175 end
173 host = host or "*"; 176
174 177 local function add_user_secondary_role(user, host, role_name)
175 local actor_user, actor_host = jid_split(jid); 178 if host and not hosts[host] then return false; end
176 179 if type(user) ~= "string" then return false; end
177 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; 180
178 if actor_user and actor_host == host then -- Local user 181 local role, err = hosts[host].authz.add_user_secondary_role(user, role_name);
179 local ok, err = authz_provider.set_user_roles(actor_user, roles); 182 if role then
180 if ok then 183 prosody.events.fire_event("user-role-added", {
181 prosody.events.fire_event("user-roles-changed", { 184 username = user, host = host, role = role;
182 username = actor_user, host = actor_host 185 });
183 }); 186 end
184 end 187 return role, err;
185 return ok, err; 188 end
186 else -- Remote entity 189
187 return authz_provider.set_jid_roles(jid, roles) 190 local function remove_user_secondary_role(user, host, role_name)
188 end 191 if host and not hosts[host] then return false; end
189 end 192 if type(user) ~= "string" then return false; end
190 193
194 local ok, err = hosts[host].authz.remove_user_secondary_role(user, role_name);
195 if ok then
196 prosody.events.fire_event("user-role-removed", {
197 username = user, host = host, role_name = role_name;
198 });
199 end
200 return ok, err;
201 end
202
203 local function get_user_secondary_roles(user, host)
204 if host and not hosts[host] then return false; end
205 if type(user) ~= "string" then return false; end
206
207 return hosts[host].authz.get_user_secondary_roles(user);
208 end
209
210 local function get_jid_role(jid, host)
211 local jid_node, jid_host = jid_split(jid);
212 if host == jid_host and jid_node then
213 return hosts[host].authz.get_user_role(jid_node);
214 end
215 return hosts[host].authz.get_jid_role(jid);
216 end
217
218 local function set_jid_role(jid, host, role_name)
219 local _, jid_host = jid_split(jid);
220 if host == jid_host then
221 return nil, "unexpected-local-jid";
222 end
223 return hosts[host].authz.set_jid_role(jid, role_name)
224 end
225
226 local strict_deprecate_is_admin;
227 local legacy_admin_roles = { ["prosody:admin"] = true, ["prosody:operator"] = true };
191 local function is_admin(jid, host) 228 local function is_admin(jid, host)
192 local roles = get_roles(jid, host); 229 if strict_deprecate_is_admin == nil then
193 return roles and roles["prosody:admin"]; 230 strict_deprecate_is_admin = (config.get("*", "strict_deprecate_is_admin") == true);
231 end
232 if strict_deprecate_is_admin then
233 log("error", "Attempt to use deprecated is_admin() API: %s", debug.traceback());
234 return false;
235 end
236 log("warn", "Usage of legacy is_admin() API, which will be disabled in a future build: %s", debug.traceback());
237 return legacy_admin_roles[get_jid_role(jid, host)] or false;
194 end 238 end
195 239
196 local function get_users_with_role(role, host) 240 local function get_users_with_role(role, host)
197 if not hosts[host] then return false; end 241 if not hosts[host] then return false; end
198 if type(role) ~= "string" then return false; end 242 if type(role) ~= "string" then return false; end
199
200 return hosts[host].authz.get_users_with_role(role); 243 return hosts[host].authz.get_users_with_role(role);
201 end 244 end
202 245
203 local function get_jids_with_role(role, host) 246 local function get_jids_with_role(role, host)
204 if host and not hosts[host] then return false; end 247 if host and not hosts[host] then return false; end
205 if type(role) ~= "string" then return false; end 248 if type(role) ~= "string" then return false; end
206 249 return hosts[host].authz.get_jids_with_role(role);
207 host = host or "*"; 250 end
208 251
209 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; 252 local function get_role_by_name(role_name, host)
210 return authz_provider.get_jids_with_role(role); 253 if host and not hosts[host] then return false; end
254 if type(role_name) ~= "string" then return false; end
255 return hosts[host].authz.get_role_by_name(role_name);
211 end 256 end
212 257
213 return { 258 return {
214 new_null_provider = new_null_provider; 259 new_null_provider = new_null_provider;
215 initialize_host = initialize_host; 260 initialize_host = initialize_host;
216 test_password = test_password; 261 test_password = test_password;
217 get_password = get_password; 262 get_password = get_password;
218 set_password = set_password; 263 set_password = set_password;
264 get_account_info = get_account_info;
219 user_exists = user_exists; 265 user_exists = user_exists;
220 create_user = create_user; 266 create_user = create_user;
221 delete_user = delete_user; 267 delete_user = delete_user;
222 users = users; 268 users = users;
223 get_sasl_handler = get_sasl_handler; 269 get_sasl_handler = get_sasl_handler;
224 get_provider = get_provider; 270 get_provider = get_provider;
225 get_roles = get_roles; 271 get_user_role = get_user_role;
226 set_roles = set_roles; 272 set_user_role = set_user_role;
273 user_can_assume_role = user_can_assume_role;
274 add_user_secondary_role = add_user_secondary_role;
275 remove_user_secondary_role = remove_user_secondary_role;
276 get_user_secondary_roles = get_user_secondary_roles;
277 get_users_with_role = get_users_with_role;
278 get_jid_role = get_jid_role;
279 set_jid_role = set_jid_role;
280 get_jids_with_role = get_jids_with_role;
281 get_role_by_name = get_role_by_name;
282
283 -- Deprecated
227 is_admin = is_admin; 284 is_admin = is_admin;
228 get_users_with_role = get_users_with_role;
229 get_jids_with_role = get_jids_with_role;
230 }; 285 };