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 }; |