Software /
code /
prosody
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 }; |