Comparison

core/usermanager.lua @ 10633:d1cc6af0fb97

usermanager, mod_authz_internal: Move admin-checking functionality into a module. Fixes #517 (ish). Note: Removes the ability for mod_auth_* providers to determine user admin status. Such modules will need to have their is_admin methods ported to be a mod_authz_* provider.
author Matthew Wild <mwild1@gmail.com>
date Mon, 27 Jan 2020 21:54:59 +0000
parent 8717:9ddd0fbbe53a
child 10634:c9e1cb7a38b8
comparison
equal deleted inserted replaced
10632:c9de8275aaf2 10633:d1cc6af0fb97
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 ipairs = ipairs;
13 local jid_bare = require "util.jid".bare; 12 local jid_bare = require "util.jid".bare;
13 local jid_split = require "util.jid".split;
14 local jid_prep = require "util.jid".prep; 14 local jid_prep = require "util.jid".prep;
15 local config = require "core.configmanager"; 15 local config = require "core.configmanager";
16 local sasl_new = require "util.sasl".new; 16 local sasl_new = require "util.sasl".new;
17 local storagemanager = require "core.storagemanager"; 17 local storagemanager = require "core.storagemanager";
18 local set = require "util.set";
18 19
19 local prosody = _G.prosody; 20 local prosody = _G.prosody;
20 local hosts = prosody.hosts; 21 local hosts = prosody.hosts;
21 22
22 local setmetatable = setmetatable; 23 local setmetatable = setmetatable;
31 local function dummy_get_sasl_handler() return sasl_new(nil, {}); end 32 local function dummy_get_sasl_handler() return sasl_new(nil, {}); end
32 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, { 33 return setmetatable({name = "null", get_sasl_handler = dummy_get_sasl_handler}, {
33 __index = function(self, method) return dummy; end --luacheck: ignore 212 34 __index = function(self, method) return dummy; end --luacheck: ignore 212
34 }); 35 });
35 end 36 end
37
38 local global_admins_config = config.get("*", "admins");
39 if type(global_admins_config) ~= "table" then
40 global_admins_config = nil; -- TODO: factor out moduleapi magic config handling and use it here
41 end
42 local global_admins = set.new(global_admins_config) / jid_prep;
43
44 local admin_role = { ["prosody:admin"] = true };
45 local global_authz_provider = {
46 get_user_roles = function (user) end; --luacheck: ignore 212/user
47 get_jid_roles = function (jid)
48 if global_admins:contains(jid) then
49 return admin_role;
50 end
51 end;
52 };
36 53
37 local provider_mt = { __index = new_null_provider() }; 54 local provider_mt = { __index = new_null_provider() };
38 55
39 local function initialize_host(host) 56 local function initialize_host(host)
40 local host_session = hosts[host]; 57 local host_session = hosts[host];
64 local auth_provider = config.get(host, "authentication") or default_provider; 81 local auth_provider = config.get(host, "authentication") or default_provider;
65 if config.get(host, "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7 82 if config.get(host, "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7
66 if auth_provider ~= "null" then 83 if auth_provider ~= "null" then
67 modulemanager.load(host, "auth_"..auth_provider); 84 modulemanager.load(host, "auth_"..auth_provider);
68 end 85 end
86
87 local authz_provider_name = config.get(host, "authorization") or "internal";
88
89 local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name);
90 host_session.authz = authz_mod or global_authz_provider;
69 end; 91 end;
70 prosody.events.add_handler("host-activated", initialize_host, 100); 92 prosody.events.add_handler("host-activated", initialize_host, 100);
71 93
72 local function test_password(username, host, password) 94 local function test_password(username, host, password)
73 return hosts[host].users.test_password(username, password); 95 return hosts[host].users.test_password(username, password);
118 if type(jid) ~= "string" then return false; end 140 if type(jid) ~= "string" then return false; end
119 141
120 jid = jid_bare(jid); 142 jid = jid_bare(jid);
121 host = host or "*"; 143 host = host or "*";
122 144
123 local host_admins = config.get(host, "admins"); 145 local actor_user, actor_host = jid_split(jid);
124 local global_admins = config.get("*", "admins"); 146 local roles;
125 147
126 if host_admins and host_admins ~= global_admins then 148 local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider;
127 if type(host_admins) == "table" then 149
128 for _,admin in ipairs(host_admins) do 150 if actor_host == host then -- Local user
129 if jid_prep(admin) == jid then 151 roles = authz_provider.get_user_roles(actor_user);
130 return true; 152 else -- Remote user/JID
131 end 153 roles = authz_provider.get_jid_roles(jid);
132 end
133 elseif host_admins then
134 log("error", "Option 'admins' for host '%s' is not a list", host);
135 end
136 end 154 end
137 155
138 if global_admins then 156 return roles and roles["prosody:admin"];
139 if type(global_admins) == "table" then
140 for _,admin in ipairs(global_admins) do
141 if jid_prep(admin) == jid then
142 return true;
143 end
144 end
145 elseif global_admins then
146 log("error", "Global option 'admins' is not a list");
147 end
148 end
149
150 -- Still not an admin, check with auth provider
151 if host ~= "*" and hosts[host].users and hosts[host].users.is_admin then
152 return hosts[host].users.is_admin(jid);
153 end
154 return false;
155 end 157 end
156 158
157 return { 159 return {
158 new_null_provider = new_null_provider; 160 new_null_provider = new_null_provider;
159 initialize_host = initialize_host; 161 initialize_host = initialize_host;