plugins/mod_authz_internal.lua
changeset 12652 f299e570a0fe
parent 12646 9061f9621330
child 12666 07424992d7fc
equal deleted inserted replaced
12651:a661292d074a 12652:f299e570a0fe
     1 local array = require "util.array";
     1 local array = require "util.array";
     2 local it = require "util.iterators";
     2 local it = require "util.iterators";
     3 local set = require "util.set";
     3 local set = require "util.set";
     4 local jid_split, jid_bare = require "util.jid".split, require "util.jid".bare;
     4 local jid_split, jid_bare = require "util.jid".split, require "util.jid".bare;
     5 local normalize = require "util.jid".prep;
     5 local normalize = require "util.jid".prep;
       
     6 local roles = require "util.roles";
       
     7 
     6 local config_global_admin_jids = module:context("*"):get_option_set("admins", {}) / normalize;
     8 local config_global_admin_jids = module:context("*"):get_option_set("admins", {}) / normalize;
     7 local config_admin_jids = module:get_option_inherited_set("admins", {}) / normalize;
     9 local config_admin_jids = module:get_option_inherited_set("admins", {}) / normalize;
     8 local host = module.host;
    10 local host = module.host;
     9 local role_store = module:open_store("roles");
    11 local role_store = module:open_store("roles");
    10 local role_map_store = module:open_store("roles", "map");
    12 local role_map_store = module:open_store("roles", "map");
    11 
    13 
    12 local role_methods = {};
    14 local role_registry = {};
    13 local role_mt = { __index = role_methods };
    15 
    14 
    16 function register_role(role)
    15 local role_registry = {
    17 	if role_registry[role.name] ~= nil then
    16 	["prosody:operator"] = {
    18 		return error("A role '"..role.name.."' is already registered");
    17 		default = true;
    19 	end
    18 		priority = 75;
    20 	if not roles.is_role(role) then
    19 		includes = { "prosody:admin" };
    21 		-- Convert table syntax to real role object
    20 	};
    22 		for i, inherited_role in ipairs(role.inherits or {}) do
    21 	["prosody:admin"] = {
    23 			if type(inherited_role) == "string" then
    22 		default = true;
    24 				role.inherits[i] = assert(role_registry[inherited_role], "The named role '"..inherited_role.."' is not registered");
    23 		priority = 50;
    25 			end
    24 		includes = { "prosody:user" };
    26 		end
    25 	};
    27 		if not role.permissions then role.permissions = {}; end
    26 	["prosody:user"] = {
    28 		for _, allow_permission in ipairs(role.allow or {}) do
    27 		default = true;
    29 			role.permissions[allow_permission] = true;
    28 		priority = 25;
    30 		end
    29 		includes = { "prosody:restricted" };
    31 		for _, deny_permission in ipairs(role.deny or {}) do
    30 	};
    32 			role.permissions[deny_permission] = false;
    31 	["prosody:restricted"] = {
    33 		end
    32 		default = true;
    34 		role = roles.new(role);
    33 		priority = 15;
    35 	end
    34 	};
    36 	role_registry[role.name] = role;
    35 };
    37 end
    36 
    38 
    37 -- Some processing on the role registry
    39 -- Default roles
    38 for role_name, role_info in pairs(role_registry) do
    40 register_role {
    39 	role_info.name = role_name;
    41 	name = "prosody:restricted";
    40 	role_info.includes = set.new(role_info.includes) / function (included_role_name)
    42 	priority = 15;
    41 		return role_registry[included_role_name];
    43 };
    42 	end;
    44 
    43 	if not role_info.permissions then
    45 register_role {
    44 		role_info.permissions = {};
    46 	name = "prosody:user";
    45 	end
    47 	priority = 25;
    46 	setmetatable(role_info, role_mt);
    48 	inherits = { "prosody:restricted" };
    47 end
    49 };
    48 
    50 
    49 function role_methods:may(action, context)
    51 register_role {
    50 	local policy = self.permissions[action];
    52 	name = "prosody:admin";
    51 	if policy ~= nil then
    53 	priority = 50;
    52 		return policy;
    54 	inherits = { "prosody:user" };
    53 	end
    55 };
    54 	for inherited_role in self.includes do
    56 
    55 		module:log("debug", "Checking included role '%s' for %s", inherited_role.name, action);
    57 register_role {
    56 		policy = inherited_role:may(action, context);
    58 	name = "prosody:operator";
    57 		if policy ~= nil then
    59 	priority = 75;
    58 			return policy;
    60 	inherits = { "prosody:admin" };
    59 		end
    61 };
    60 	end
    62 
    61 	return false;
    63 
       
    64 -- Process custom roles from config
       
    65 
       
    66 local custom_roles = module:get_option("custom_roles", {});
       
    67 for n, role_config in ipairs(custom_roles) do
       
    68 	local ok, err = pcall(register_role, role_config);
       
    69 	if not ok then
       
    70 		module:log("error", "Error registering custom role %s: %s", role_config.name or tostring(n), err);
       
    71 	end
       
    72 end
       
    73 
       
    74 -- Process custom permissions from config
       
    75 
       
    76 local config_add_perms = module:get_option("add_permissions", {});
       
    77 local config_remove_perms = module:get_option("remove_permissions", {});
       
    78 
       
    79 for role_name, added_permissions in pairs(config_add_perms) do
       
    80 	if not role_registry[role_name] then
       
    81 		module:log("error", "Cannot add permissions to unknown role '%s'", role_name);
       
    82 	else
       
    83 		for _, permission in ipairs(added_permissions) do
       
    84 			role_registry[role_name]:set_permission(permission, true, true);
       
    85 		end
       
    86 	end
       
    87 end
       
    88 
       
    89 for role_name, removed_permissions in pairs(config_remove_perms) do
       
    90 	if not role_registry[role_name] then
       
    91 		module:log("error", "Cannot remove permissions from unknown role '%s'", role_name);
       
    92 	else
       
    93 		for _, permission in ipairs(removed_permissions) do
       
    94 			role_registry[role_name]:set_permission(permission, false, true);
       
    95 		end
       
    96 	end
    62 end
    97 end
    63 
    98 
    64 -- Public API
    99 -- Public API
    65 
   100 
    66 local config_operator_role_set = {
   101 local config_operator_role_set = {
    67 	["prosody:operator"] = role_registry["prosody:operator"];
   102 	["prosody:operator"] = role_registry["prosody:operator"];
    68 };
   103 };
    69 local config_admin_role_set = {
   104 local config_admin_role_set = {
    70 	["prosody:admin"] = role_registry["prosody:admin"];
   105 	["prosody:admin"] = role_registry["prosody:admin"];
       
   106 };
       
   107 local default_role_set = {
       
   108 	["prosody:user"] = role_registry["prosody:user"];
    71 };
   109 };
    72 
   110 
    73 function get_user_roles(user)
   111 function get_user_roles(user)
    74 	local bare_jid = user.."@"..host;
   112 	local bare_jid = user.."@"..host;
    75 	if config_global_admin_jids:contains(bare_jid) then
   113 	if config_global_admin_jids:contains(bare_jid) then
    76 		return config_operator_role_set;
   114 		return config_operator_role_set;
    77 	elseif config_admin_jids:contains(bare_jid) then
   115 	elseif config_admin_jids:contains(bare_jid) then
    78 		return config_admin_role_set;
   116 		return config_admin_role_set;
    79 	end
   117 	end
    80 	local role_names = role_store:get(user);
   118 	local role_names = role_store:get(user);
    81 	if not role_names then return {}; end
   119 	if not role_names then return default_role_set; end
    82 	local roles = {};
   120 	local user_roles = {};
    83 	for role_name in pairs(role_names) do
   121 	for role_name in pairs(role_names) do
    84 		roles[role_name] = role_registry[role_name];
   122 		user_roles[role_name] = role_registry[role_name];
    85 	end
   123 	end
    86 	return roles;
   124 	return user_roles;
    87 end
   125 end
    88 
   126 
    89 function set_user_roles(user, roles)
   127 function set_user_roles(user, user_roles)
    90 	role_store:set(user, roles)
   128 	role_store:set(user, user_roles)
    91 	return true;
   129 	return true;
    92 end
   130 end
    93 
   131 
    94 function get_user_default_role(user)
   132 function get_user_default_role(user)
    95 	local roles = get_user_roles(user);
   133 	local user_roles = get_user_roles(user);
    96 	if not roles then return nil; end
   134 	if not user_roles then return nil; end
    97 	local default_role;
   135 	local default_role;
    98 	for role_name, role_info in pairs(roles) do --luacheck: ignore 213/role_name
   136 	for role_name, role_info in pairs(user_roles) do --luacheck: ignore 213/role_name
    99 		if role_info.default and (not default_role or role_info.priority > default_role.priority) then
   137 		if role_info.default ~= false and (not default_role or role_info.priority > default_role.priority) then
   100 			default_role = role_info;
   138 			default_role = role_info;
   101 		end
   139 		end
   102 	end
   140 	end
   103 	if not default_role then return nil; end
   141 	if not default_role then return nil; end
   104 	return default_role;
   142 	return default_role;
   132 		return role_registry["prosody:admin"];
   170 		return role_registry["prosody:admin"];
   133 	end
   171 	end
   134 	return nil;
   172 	return nil;
   135 end
   173 end
   136 
   174 
   137 function set_jid_role(jid) -- luacheck: ignore 212
   175 function set_jid_role(jid, role_name) -- luacheck: ignore 212
   138 	return false;
   176 	return false;
   139 end
   177 end
   140 
   178 
   141 function get_jids_with_role(role_name)
   179 function get_jids_with_role(role_name)
   142 	-- Fetch role users from storage
   180 	-- Fetch role users from storage
   155 	local role = role_registry[role_name];
   193 	local role = role_registry[role_name];
   156 	if not role then
   194 	if not role then
   157 		module:log("warn", "Attempt to add default permission for unknown role: %s", role_name);
   195 		module:log("warn", "Attempt to add default permission for unknown role: %s", role_name);
   158 		return nil, "no-such-role";
   196 		return nil, "no-such-role";
   159 	end
   197 	end
   160 	if role.permissions[action] == nil then
   198 	if policy == nil then policy = true; end
   161 		if policy == nil then
   199 	module:log("debug", "Adding policy %s for permission %s on role %s", policy, action, role_name);
   162 			policy = true;
   200 	return role:set_permission(action, policy);
   163 		end
   201 end
   164 		module:log("debug", "Adding permission, role '%s' may '%s': %s", role_name, action, policy and "allow" or "deny");
   202 
   165 		role.permissions[action] = policy;
   203 function get_role_by_name(role_name)
   166 	end
   204 	return assert(role_registry[role_name], role_name);
   167 	return true;
   205 end
   168 end
       
   169 
       
   170 function get_role_info(role_name)
       
   171 	return role_registry[role_name];
       
   172 end