Software /
code /
prosody
Comparison
util/roles.lua @ 12647:a661292d074a
util.roles: Add new utility module to consolidate role objects and methods
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Tue, 19 Jul 2022 17:44:26 +0100 |
child | 12746:7eabf8d78978 |
comparison
equal
deleted
inserted
replaced
12646:3f38f4735c7a | 12647:a661292d074a |
---|---|
1 local array = require "util.array"; | |
2 local it = require "util.iterators"; | |
3 local new_short_id = require "util.id".short; | |
4 | |
5 local role_methods = {}; | |
6 local role_mt = { | |
7 __index = role_methods; | |
8 __name = "role"; | |
9 __add = nil; | |
10 }; | |
11 | |
12 local function is_role(o) | |
13 local mt = getmetatable(o); | |
14 return mt == role_mt; | |
15 end | |
16 | |
17 local function _new_may(permissions, inherited_mays) | |
18 local n_inherited = inherited_mays and #inherited_mays; | |
19 return function (role, action, context) | |
20 -- Note: 'role' may be a descendent role, not only the one we're attached to | |
21 local policy = permissions[action]; | |
22 if policy ~= nil then | |
23 return policy; | |
24 end | |
25 if n_inherited then | |
26 for i = 1, n_inherited do | |
27 policy = inherited_mays[i](role, action, context); | |
28 if policy ~= nil then | |
29 return policy; | |
30 end | |
31 end | |
32 end | |
33 return false; | |
34 end | |
35 end | |
36 | |
37 local permissions_key = {}; | |
38 | |
39 -- { | |
40 -- Required: | |
41 -- name = "My fancy role"; | |
42 -- | |
43 -- Optional: | |
44 -- inherits = { role_obj... } | |
45 -- default = true | |
46 -- priority = 100 | |
47 -- permissions = { | |
48 -- ["foo"] = true; -- allow | |
49 -- ["bar"] = false; -- deny | |
50 -- } | |
51 -- } | |
52 local function new(base_config, overrides) | |
53 local config = setmetatable(overrides or {}, { __index = base_config }); | |
54 local permissions = {}; | |
55 local inherited_mays; | |
56 if config.inherits then | |
57 inherited_mays = array.pluck(config.inherits, "may"); | |
58 end | |
59 local new_role = { | |
60 id = new_short_id(); | |
61 name = config.name; | |
62 description = config.description; | |
63 default = config.default; | |
64 priority = config.priority; | |
65 may = _new_may(permissions, inherited_mays); | |
66 inherits = config.inherits; | |
67 [permissions_key] = permissions; | |
68 }; | |
69 local desired_permissions = config.permissions or config[permissions_key]; | |
70 for k, v in pairs(desired_permissions or {}) do | |
71 permissions[k] = v; | |
72 end | |
73 return setmetatable(new_role, role_mt); | |
74 end | |
75 | |
76 function role_methods:clone(overrides) | |
77 return new(self, overrides); | |
78 end | |
79 | |
80 function role_methods:set_permission(permission_name, policy, overwrite) | |
81 local permissions = self[permissions_key]; | |
82 if overwrite ~= true and permissions[permission_name] ~= nil and permissions[permission_name] ~= policy then | |
83 return false, "policy-already-exists"; | |
84 end | |
85 permissions[permission_name] = policy; | |
86 return true; | |
87 end | |
88 | |
89 function role_mt.__tostring(self) | |
90 return ("role<[%s] %s>"):format(self.id or "nil", self.name or "[no name]"); | |
91 end | |
92 | |
93 function role_mt.__pairs(self) | |
94 return it.filter(permissions_key, next, self); | |
95 end | |
96 | |
97 return { | |
98 is_role = is_role; | |
99 new = new; | |
100 }; |