util.startup: Check root after detecting platform and reading config (thanks SigmaTel71)
Ensures that startup.detect_platform() runs so know whether to use the
POSIX method of checking the current user or something else. Also after
reading the config so we know whether the root override setting is set.
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;
};