aboutsummaryrefslogtreecommitdiffstats
path: root/core/moduleapi.lua
diff options
context:
space:
mode:
Diffstat (limited to 'core/moduleapi.lua')
-rw-r--r--core/moduleapi.lua145
1 files changed, 121 insertions, 24 deletions
diff --git a/core/moduleapi.lua b/core/moduleapi.lua
index 870a6a50..3ee8647f 100644
--- a/core/moduleapi.lua
+++ b/core/moduleapi.lua
@@ -6,28 +6,29 @@
-- COPYING file in the source package for more information.
--
-local array = require "util.array";
-local set = require "util.set";
-local it = require "util.iterators";
-local logger = require "util.logger";
-local timer = require "util.timer";
-local resolve_relative_path = require"util.paths".resolve_relative_path;
-local st = require "util.stanza";
-local cache = require "util.cache";
-local errors = require "util.error";
-local promise = require "util.promise";
-local time_now = require "util.time".now;
-local format = require "util.format".format;
-local jid_node = require "util.jid".node;
-local jid_resource = require "util.jid".resource;
+local array = require "prosody.util.array";
+local set = require "prosody.util.set";
+local it = require "prosody.util.iterators";
+local logger = require "prosody.util.logger";
+local timer = require "prosody.util.timer";
+local resolve_relative_path = require"prosody.util.paths".resolve_relative_path;
+local st = require "prosody.util.stanza";
+local cache = require "prosody.util.cache";
+local errors = require "prosody.util.error";
+local promise = require "prosody.util.promise";
+local time_now = require "prosody.util.time".now;
+local format = require "prosody.util.format".format;
+local jid_node = require "prosody.util.jid".node;
+local jid_split = require "prosody.util.jid".split;
+local jid_resource = require "prosody.util.jid".resource;
local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat;
local error, setmetatable, type = error, setmetatable, type;
local ipairs, pairs, select = ipairs, pairs, select;
local tonumber, tostring = tonumber, tostring;
local require = require;
-local pack = table.pack or require "util.table".pack; -- table.pack is only in 5.2
-local unpack = table.unpack or unpack; --luacheck: ignore 113 -- renamed in 5.2
+local pack = table.pack;
+local unpack = table.unpack;
local prosody = prosody;
local hosts = prosody.hosts;
@@ -128,14 +129,14 @@ function api:wrap_global(event, handler)
end
function api:require(lib)
- local modulemanager = require"core.modulemanager";
+ local modulemanager = require"prosody.core.modulemanager";
local f, n = modulemanager.loader:load_code_ext(self.name, lib, "lib.lua", self.environment);
if not f then error("Failed to load plugin library '"..lib.."', error: "..n); end -- FIXME better error message
return f();
end
function api:depends(name)
- local modulemanager = require"core.modulemanager";
+ local modulemanager = require"prosody.core.modulemanager";
if self:get_option_inherited_set("modules_disabled", {}):contains(name) then
error("Dependency on disabled module mod_"..name);
end
@@ -168,6 +169,10 @@ function api:depends(name)
end
end
self.dependencies[name] = true;
+ if not mod.module.reverse_dependencies then
+ mod.module.reverse_dependencies = {};
+ end
+ mod.module.reverse_dependencies[self.name] = true;
return mod;
end
@@ -200,7 +205,7 @@ function api:shared(path)
end
function api:get_option(name, default_value)
- local config = require "core.configmanager";
+ local config = require "prosody.core.configmanager";
local value = config.get(self.host, name);
if value == nil then
value = default_value;
@@ -328,7 +333,7 @@ function api:remove_item(key, value)
end
function api:get_host_items(key)
- local modulemanager = require"core.modulemanager";
+ local modulemanager = require"prosody.core.modulemanager";
local result = modulemanager.get_items(key, self.host) or {};
return result;
end
@@ -537,11 +542,12 @@ function api:load_resource(path, mode)
end
function api:open_store(name, store_type)
- return require"core.storagemanager".open(self.host, name or self.name, store_type);
+ if self.host == "*" then return nil, "global-storage-not-supported"; end
+ return require"prosody.core.storagemanager".open(self.host, name or self.name, store_type);
end
function api:measure(name, stat_type, conf)
- local measure = require "core.statsmanager".measure;
+ local measure = require "prosody.core.statsmanager".measure;
local fixed_label_key, fixed_label_value
if self.host ~= "*" then
fixed_label_key = "host"
@@ -556,7 +562,7 @@ function api:measure(name, stat_type, conf)
end
function api:metric(type_, name, unit, description, label_keys, conf)
- local metric = require "core.statsmanager".metric;
+ local metric = require "prosody.core.statsmanager".metric;
local is_scoped = self.host ~= "*"
if is_scoped then
-- prepend `host` label to label keys if this is not a global module
@@ -578,7 +584,7 @@ local status_priorities = { error = 3, warn = 2, info = 1, core = 0 };
function api:set_status(status_type, status_message, override)
local priority = status_priorities[status_type];
if not priority then
- self:log("error", "set_status: Invalid status type '%s', assuming 'info'");
+ self:log("error", "set_status: Invalid status type '%s', assuming 'info'", status_type);
status_type, priority = "info", status_priorities.info;
end
local current_priority = status_priorities[self.status_type] or 0;
@@ -601,4 +607,95 @@ function api:get_status()
return self.status_type, self.status_message, self.status_time;
end
+function api:default_permission(role_name, permission)
+ permission = permission:gsub("^:", self.name..":");
+ if self.host == "*" then
+ for _, host in pairs(hosts) do
+ if host.authz then
+ host.authz.add_default_permission(role_name, permission);
+ end
+ end
+ return
+ end
+ hosts[self.host].authz.add_default_permission(role_name, permission);
+end
+
+function api:default_permissions(role_name, permissions)
+ for _, permission in ipairs(permissions) do
+ self:default_permission(role_name, permission);
+ end
+end
+
+function api:could(action, context)
+ return self:may(action, context, true);
+end
+
+function api:may(action, context, peek)
+ if action:byte(1) == 58 then -- action begins with ':'
+ action = self.name..action; -- prepend module name
+ end
+ if type(context) == "string" then -- check JID permissions
+ local role;
+ local node, host = jid_split(context);
+ if host == self.host then
+ role = hosts[host].authz.get_user_role(node);
+ else
+ role = hosts[self.host].authz.get_jid_role(context);
+ end
+ if not role then
+ if not peek then
+ self:log("debug", "Access denied: JID <%s> may not %s (no role found)", context, action);
+ end
+ return false;
+ end
+ local permit = role:may(action);
+ if not permit then
+ if not peek then
+ self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", context, action, role.name);
+ end
+ end
+ return permit;
+ end
+
+ local session = context.origin or context.session;
+ if type(session) ~= "table" then
+ error("Unable to identify actor session from context");
+ end
+ if session.type == "c2s" and session.host == self.host then
+ local role = session.role;
+ if not role then
+ if not peek then
+ self:log("warn", "Access denied: session %s has no role assigned");
+ end
+ return false;
+ end
+ local permit = role:may(action, context);
+ if not permit and not peek then
+ self:log("debug", "Access denied: session %s (%s) may not %s (not permitted by role %s)",
+ session.id, session.full_jid, action, role.name
+ );
+ end
+ return permit;
+ else
+ local actor_jid = context.stanza.attr.from;
+ local role = hosts[self.host].authz.get_jid_role(actor_jid);
+ if not role then
+ if not peek then
+ self:log("debug", "Access denied: JID <%s> may not %s (no role found)", actor_jid, action);
+ end
+ return false;
+ end
+ local permit = role:may(action, context);
+ if not permit and not peek then
+ self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", actor_jid, action, role.name);
+ end
+ return permit;
+ end
+end
+
+-- Execute a function, once, but only after startup is complete
+function api:once(f) --luacheck: ignore 212/self
+ return prosody.started:next(f);
+end
+
return api;