Annotate

util/roles.lua @ 12987:2cf8d98d8a28

util.roles: Implement a serialization preparation metamethod Should be able to roundtrip trough serialization. Also nice for debug and logging purposes where you might want more details than what the __tostring method provides.
author Kim Alvefur <zash@zash.se>
date Sun, 26 Mar 2023 13:13:31 +0200
parent 12975:d10957394a3c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12975
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12748
diff changeset
1 local array = require "prosody.util.array";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12748
diff changeset
2 local it = require "prosody.util.iterators";
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12748
diff changeset
3 local new_short_id = require "prosody.util.id".short;
12647
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
12746
7eabf8d78978 util.roles: Return nil if the role has no explicit policy (fixes inheritance)
Matthew Wild <mwild1@gmail.com>
parents: 12647
diff changeset
33 return nil;
12647
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
12987
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
76 function role_mt:__freeze()
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
77 local t = {
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
78 id = self.id;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
79 name = self.name;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
80 description = self.description;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
81 default = self.default;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
82 priority = self.priority;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
83 inherits = self.inherits;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
84 permissions = self[permissions_key];
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
85 };
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
86 return t;
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
87 end
2cf8d98d8a28 util.roles: Implement a serialization preparation metamethod
Kim Alvefur <zash@zash.se>
parents: 12975
diff changeset
88
12647
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
12748
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12746
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: 12746
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: 12746
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: 12746
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: 12746
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: 12746
diff changeset
107 end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12746
diff changeset
108 end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12746
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: 12746
diff changeset
110 end
7b9de8109a90 util.roles: Add a :policies() method to iterate through available policies
Matthew Wild <mwild1@gmail.com>
parents: 12746
diff changeset
111
12647
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 };