Mercurial > prosody-hg
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 |
| parents | 0278987b8687 |
| children | 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 }; |
