net.unbound: Show canonical name in textual format (e.g. in shell)
libunbound does not tell us the whole chain of CNAMEs, only the final
canonical name.
This is to aid in debugging since it will only be shown in the shell.
local array = require "prosody.util.array";
local it = require "prosody.util.iterators";
local new_short_id = require "prosody.util.id".short;
local role_methods = {};
local role_mt = {
__index = role_methods;
__name = "role";
__add = nil;
};
local function is_role(o)
local mt = getmetatable(o);
return mt == role_mt;
end
local function _new_may(permissions, inherited_mays)
local n_inherited = inherited_mays and #inherited_mays;
return function (role, action, context)
-- Note: 'role' may be a descendent role, not only the one we're attached to
local policy = permissions[action];
if policy ~= nil then
return policy;
end
if n_inherited then
for i = 1, n_inherited do
policy = inherited_mays[i](role, action, context);
if policy ~= nil then
return policy;
end
end
end
return nil;
end
end
local permissions_key = {};
-- {
-- Required:
-- name = "My fancy role";
--
-- Optional:
-- inherits = { role_obj... }
-- default = true
-- priority = 100
-- permissions = {
-- ["foo"] = true; -- allow
-- ["bar"] = false; -- deny
-- }
-- }
local function new(base_config, overrides)
local config = setmetatable(overrides or {}, { __index = base_config });
local permissions = {};
local inherited_mays;
if config.inherits then
inherited_mays = array.pluck(config.inherits, "may");
end
local new_role = {
id = new_short_id();
name = config.name;
description = config.description;
default = config.default;
priority = config.priority;
may = _new_may(permissions, inherited_mays);
inherits = config.inherits;
[permissions_key] = permissions;
};
local desired_permissions = config.permissions or config[permissions_key];
for k, v in pairs(desired_permissions or {}) do
permissions[k] = v;
end
return setmetatable(new_role, role_mt);
end
function role_mt:__freeze()
local t = {
id = self.id;
name = self.name;
description = self.description;
default = self.default;
priority = self.priority;
inherits = self.inherits;
permissions = self[permissions_key];
};
return t;
end
function role_methods:clone(overrides)
return new(self, overrides);
end
function role_methods:set_permission(permission_name, policy, overwrite)
local permissions = self[permissions_key];
if overwrite ~= true and permissions[permission_name] ~= nil and permissions[permission_name] ~= policy then
return false, "policy-already-exists";
end
permissions[permission_name] = policy;
return true;
end
function role_methods:policies()
local policy_iterator, s, v = it.join(pairs(self[permissions_key]));
if self.inherits then
for _, inherited_role in ipairs(self.inherits) do
policy_iterator:append(inherited_role:policies());
end
end
return policy_iterator, s, v;
end
function role_mt.__tostring(self)
return ("role<[%s] %s>"):format(self.id or "nil", self.name or "[no name]");
end
function role_mt.__pairs(self)
return it.filter(permissions_key, next, self);
end
return {
is_role = is_role;
new = new;
};