diff options
Diffstat (limited to 'core/usermanager.lua')
-rw-r--r-- | core/usermanager.lua | 112 |
1 files changed, 82 insertions, 30 deletions
diff --git a/core/usermanager.lua b/core/usermanager.lua index bb5669cf..55faa0c9 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -9,12 +9,14 @@ local modulemanager = require "core.modulemanager"; local log = require "util.logger".init("usermanager"); local type = type; -local ipairs = ipairs; +local it = require "util.iterators"; local jid_bare = require "util.jid".bare; +local jid_split = require "util.jid".split; local jid_prep = require "util.jid".prep; local config = require "core.configmanager"; local sasl_new = require "util.sasl".new; local storagemanager = require "core.storagemanager"; +local set = require "util.set"; local prosody = _G.prosody; local hosts = prosody.hosts; @@ -34,10 +36,36 @@ local function new_null_provider() }); end +local global_admins_config = config.get("*", "admins"); +if type(global_admins_config) ~= "table" then + global_admins_config = nil; -- TODO: factor out moduleapi magic config handling and use it here +end +local global_admins = set.new(global_admins_config) / jid_prep; + +local admin_role = { ["prosody:admin"] = true }; +local global_authz_provider = { + get_user_roles = function (user) end; --luacheck: ignore 212/user + get_jid_roles = function (jid) + if global_admins:contains(jid) then + return admin_role; + end + end; + get_jids_with_role = function (role) + if role ~= "prosody:admin" then return {}; end + return it.to_array(global_admins); + end; +}; + local provider_mt = { __index = new_null_provider() }; local function initialize_host(host) local host_session = hosts[host]; + + local authz_provider_name = config.get(host, "authorization") or "internal"; + + local authz_mod = modulemanager.load(host, "authz_"..authz_provider_name); + host_session.authz = authz_mod or global_authz_provider; + if host_session.type ~= "local" then return; end host_session.events.add_handler("item-added/auth-provider", function (event) @@ -66,6 +94,7 @@ local function initialize_host(host) if auth_provider ~= "null" then modulemanager.load(host, "auth_"..auth_provider); end + end; prosody.events.add_handler("host-activated", initialize_host, 100); @@ -113,45 +142,64 @@ local function get_provider(host) return hosts[host].users; end -local function is_admin(jid, host) +local function get_roles(jid, host) if host and not hosts[host] then return false; end if type(jid) ~= "string" then return false; end jid = jid_bare(jid); host = host or "*"; - local host_admins = config.get(host, "admins"); - local global_admins = config.get("*", "admins"); - - if host_admins and host_admins ~= global_admins then - if type(host_admins) == "table" then - for _,admin in ipairs(host_admins) do - if jid_prep(admin) == jid then - return true; - end - end - elseif host_admins then - log("error", "Option 'admins' for host '%s' is not a list", host); - end - end + local actor_user, actor_host = jid_split(jid); + local roles; - if global_admins then - if type(global_admins) == "table" then - for _,admin in ipairs(global_admins) do - if jid_prep(admin) == jid then - return true; - end - end - elseif global_admins then - log("error", "Global option 'admins' is not a list"); - end + local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; + + if actor_user and actor_host == host then -- Local user + roles = authz_provider.get_user_roles(actor_user); + else -- Remote user/JID + roles = authz_provider.get_jid_roles(jid); end - -- Still not an admin, check with auth provider - if host ~= "*" and hosts[host].users and hosts[host].users.is_admin then - return hosts[host].users.is_admin(jid); + return roles; +end + +local function set_roles(jid, host, roles) + if host and not hosts[host] then return false; end + if type(jid) ~= "string" then return false; end + + jid = jid_bare(jid); + host = host or "*"; + + local actor_user, actor_host = jid_split(jid); + + local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; + if actor_user and actor_host == host then -- Local user + return authz_provider.set_user_roles(actor_user, roles) + else -- Remote entity + return authz_provider.set_jid_roles(jid, roles) end - return false; +end + +local function is_admin(jid, host) + local roles = get_roles(jid, host); + return roles and roles["prosody:admin"]; +end + +local function get_users_with_role(role, host) + if not hosts[host] then return false; end + if type(role) ~= "string" then return false; end + + return hosts[host].authz.get_users_with_role(role); +end + +local function get_jids_with_role(role, host) + if host and not hosts[host] then return false; end + if type(role) ~= "string" then return false; end + + host = host or "*"; + + local authz_provider = (host ~= "*" and hosts[host].authz) or global_authz_provider; + return authz_provider.get_jids_with_role(role); end return { @@ -166,5 +214,9 @@ return { users = users; get_sasl_handler = get_sasl_handler; get_provider = get_provider; + get_roles = get_roles; + set_roles = set_roles; is_admin = is_admin; + get_users_with_role = get_users_with_role; + get_jids_with_role = get_jids_with_role; }; |