util/roles.lua
author Matthew Wild <mwild1@gmail.com>
Sun, 17 Mar 2024 10:10:24 +0000
changeset 13464 a688947fab1e
parent 12991 2cf8d98d8a28
permissions -rw-r--r--
mod_bosh: Set base_type on session This fixes a traceback with mod_saslauth. Ideally we move this to util.session at some point, though.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12979
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12752
diff changeset
     1
local array = require "prosody.util.array";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12752
diff changeset
     2
local it = require "prosody.util.iterators";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12752
diff changeset
     3
local new_short_id = require "prosody.util.id".short;
12651
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
local role_methods = {};
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
local role_mt = {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
	__index = role_methods;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
	__name = "role";
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     9
	__add = nil;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
};
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
local function is_role(o)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	local mt = getmetatable(o);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	return mt == role_mt;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
local function _new_may(permissions, inherited_mays)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
	local n_inherited = inherited_mays and #inherited_mays;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
	return function (role, action, context)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
		-- Note: 'role' may be a descendent role, not only the one we're attached to
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
		local policy = permissions[action];
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
		if policy ~= nil then
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
			return policy;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
		end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
		if n_inherited then
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
			for i = 1, n_inherited do
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
				policy = inherited_mays[i](role, action, context);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
				if policy ~= nil then
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
					return policy;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
				end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
			end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
		end
12750
7eabf8d78978 util.roles: Return nil if the role has no explicit policy (fixes inheritance)
Matthew Wild <mwild1@gmail.com>
parents: 12651
diff changeset
    33
		return nil;
12651
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
	end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
local permissions_key = {};
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
-- {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
-- Required:
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
--   name = "My fancy role";
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
--
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
-- Optional:
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
--   inherits = { role_obj... }
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
--   default = true
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
--   priority = 100
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
--   permissions = {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
--     ["foo"] = true; -- allow
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
--     ["bar"] = false; -- deny
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
--   }
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
-- }
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
local function new(base_config, overrides)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
	local config = setmetatable(overrides or {}, { __index = base_config });
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
	local permissions = {};
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
	local inherited_mays;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	if config.inherits then
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
		inherited_mays = array.pluck(config.inherits, "may");
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
	end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
	local new_role = {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
		id = new_short_id();
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
		name = config.name;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
		description = config.description;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
		default = config.default;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
		priority = config.priority;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
		may = _new_may(permissions, inherited_mays);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
		inherits = config.inherits;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
		[permissions_key] = permissions;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	};
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
	local desired_permissions = config.permissions or config[permissions_key];
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
	for k, v in pairs(desired_permissions or {}) do
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
		permissions[k] = v;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
	end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
	return setmetatable(new_role, role_mt);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
12991
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    76
function role_mt:__freeze()
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    77
	local t = {
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    78
		id = self.id;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    79
		name = self.name;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    80
		description = self.description;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    81
		default = self.default;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    82
		priority = self.priority;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    83
		inherits = self.inherits;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    84
		permissions = self[permissions_key];
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    85
	};
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    86
	return t;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    87
end
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    88
12651
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
function role_methods:clone(overrides)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
	return new(self, overrides);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
function role_methods:set_permission(permission_name, policy, overwrite)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
	local permissions = self[permissions_key];
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
	if overwrite ~= true and permissions[permission_name] ~= nil and permissions[permission_name] ~= policy then
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
		return false, "policy-already-exists";
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    97
	end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    98
	permissions[permission_name] = policy;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    99
	return true;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   101
12752
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   102
function role_methods:policies()
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   103
	local policy_iterator, s, v = it.join(pairs(self[permissions_key]));
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   104
	if self.inherits then
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   105
		for _, inherited_role in ipairs(self.inherits) do
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   106
			policy_iterator:append(inherited_role:policies());
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   107
		end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   108
	end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   109
	return policy_iterator, s, v;
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   110
end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12750
diff changeset
   111
12651
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   112
function role_mt.__tostring(self)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   113
	return ("role<[%s] %s>"):format(self.id or "nil", self.name or "[no name]");
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   114
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   115
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   116
function role_mt.__pairs(self)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   117
	return it.filter(permissions_key, next, self);
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   118
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   119
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   120
return {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   121
	is_role = is_role;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   122
	new = new;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   123
};