view mod_compat_roles/mod_compat_roles.lua @ 5627:3a5cf8d80089

mod_http_oauth2: Tweak method of centering the UI The percentage here was relative to the viewport width, which on some very wide screens may put the UI slightly outside of the view, requiring scrolling to see. By using a unit relative to the height of the viewport, this is avoided and should work better. But no guarantees, it's still possible to resize the browser or adjust font sizes so that the UI goes out of view.
author Kim Alvefur <zash@zash.se>
date Mon, 31 Jul 2023 07:28:09 +0200
parents 825c6fb76c48
children
line wrap: on
line source

-- Export a module:may() that works on Prosody 0.12 and earlier
-- (i.e. backed by is_admin).

-- This API is safe because Prosody 0.12 and earlier do not support
-- per-session roles - all authorization is based on JID alone. It is not
-- safe on versions that support per-session authorization.

module:set_global();

local moduleapi = require "core.moduleapi";

-- If module.may already exists, abort
if moduleapi.may then return; end

local jid_split = require "util.jid".split;
local um_is_admin = require "core.usermanager".is_admin;

local function get_jid_role_name(jid, host)
	if um_is_admin(jid, "*") then
		return "prosody:operator";
	elseif um_is_admin(jid, host) then
		return "prosody:admin";
	end
	return nil;
end

local function get_user_role_name(username, host)
	return get_jid_role_name(username.."@"..host, host);
end

-- permissions[host][role_name][permission_name] = is_permitted
local permissions = {};

local role_inheritance = {
	["prosody:operator"] = "prosody:admin";
	["prosody:admin"] = "prosody:member";
	["prosody:member"] = "prosody:registered";
	["prosody:registered"] = "prosody:guest";

	-- COMPAT
	["prosody:user"] = "prosody:registered";
};

local function role_may(host, role_name, permission)
	local host_roles = permissions[host];
	if not host_roles then
		return false;
	end
	local role_permissions = host_roles[role_name];
	if not role_permissions then
		return false;
	end
	local next_role = role_inheritance[role_name];
	return not not permissions[role_name][permission] or (next_role and role_may(host, next_role, permission));
end

function moduleapi.may(self, action, context)
	if action:byte(1) == 58 then -- action begins with ':'
		action = self.name..action; -- prepend module name
	end
	if type(context) == "string" then -- check JID permissions
		local role;
		local node, host = jid_split(context);
		if host == self.host then
			role = get_user_role_name(node, self.host);
		else
			role = get_jid_role_name(context, self.host);
		end
		if not role then
			self:log("debug", "Access denied: JID <%s> may not %s (no role found)", context, action);
			return false;
		end

		local permit = role_may(self.host, role, action);
		if not permit then
			self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", context, action, role.name);
		end
		return permit;
	end

	local session = context.origin or context.session;
	if type(session) ~= "table" then
		error("Unable to identify actor session from context");
	end
	if session.type == "s2sin" or (session.type == "c2s" and session.host ~= self.host) then
		local actor_jid = context.stanza.attr.from;
		local role_name = get_jid_role_name(actor_jid);
		if not role_name then
			self:log("debug", "Access denied: JID <%s> may not %s (no role found)", actor_jid, action);
			return false;
		end
		local permit = role_may(self.host, role_name, action, context);
		if not permit then
			self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", actor_jid, action, role_name);
		end
		return permit;
	end
end

function moduleapi.default_permission(self, role_name, permission)
	local p = permissions[self.host];
	if not p then
		p = {};
		permissions[self.host] = p;
	end
	local r = p[role_name];
	if not r then
		r = {};
		p[role_name] = r;
	end
	r[permission] = true;
end

function moduleapi.default_permissions(self, role_name, permission_list)
	for _, permission in ipairs(permission_list) do
		self:default_permission(role_name, permission);
	end
end

function module.add_host(host_module)
	permissions[host_module.host] = {};
	function host_module.unload()
		permissions[host_module.host] = nil;
	end
end