util/roles.lua
author Matthew Wild <mwild1@gmail.com>
Tue, 19 Jul 2022 17:44:26 +0100
changeset 12651 a661292d074a
child 12750 7eabf8d78978
permissions -rw-r--r--
util.roles: Add new utility module to consolidate role objects and methods
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12651
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local array = require "util.array";
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local it = require "util.iterators";
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local new_short_id = require "util.id".short;
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
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
		return false;
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
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
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
    77
	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
    78
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
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
    81
	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
    82
	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
    83
		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
    84
	end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    85
	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
    86
	return true;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
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
    90
	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
    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_mt.__pairs(self)
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
	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
    95
end
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    96
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    97
return {
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    98
	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
    99
	new = new;
a661292d074a util.roles: Add new utility module to consolidate role objects and methods
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   100
};