Update to 2025-06-16 16:00

This commit is contained in:
Daniel Berteaud
2025-06-16 16:00:13 +02:00
parent ffe9caded5
commit eb0714be6f
37 changed files with 1718 additions and 393 deletions

View File

@@ -1,7 +1,15 @@
local http_server = require "net.http.server";
local jid = require "util.jid";
local st = require 'util.stanza';
local timer = require "util.timer";
local http = require "net.http";
local cache = require "util.cache";
local array = require "util.array";
local is_set = require 'util.set'.is_set;
local usermanager = require 'core.usermanager';
local config_global_admin_jids = module:context('*'):get_option_set('admins', {}) / jid.prep;
local config_admin_jids = module:get_option_inherited_set('admins', {}) / jid.prep;
local http_timeout = 30;
local have_async, async = pcall(require, "util.async");
@@ -28,6 +36,8 @@ local roomless_iqs = {};
local OUTBOUND_SIP_JIBRI_PREFIXES = { 'outbound-sip-jibri@', 'sipjibriouta@', 'sipjibrioutb@' };
local INBOUND_SIP_JIBRI_PREFIXES = { 'inbound-sip-jibri@', 'sipjibriina@', 'sipjibriina@' };
local RECORDER_PREFIXES = module:get_option_inherited_set('recorder_prefixes', { 'recorder@recorder.', 'jibria@recorder.', 'jibrib@recorder.' });
local TRANSCRIBER_PREFIXES = module:get_option_inherited_set('transcriber_prefixes', { 'transcriber@recorder.', 'transcribera@recorder.', 'transcriberb@recorder.' });
local split_subdomain_cache = cache.new(1000);
local extract_subdomain_cache = cache.new(1000);
@@ -122,11 +132,7 @@ function get_room_from_jid(room_jid)
local component = hosts[host];
if component then
local muc = component.modules.muc
if muc and rawget(muc,"rooms") then
-- We're running 0.9.x or 0.10 (old MUC API)
return muc.rooms[room_jid];
elseif muc and rawget(muc,"get_room_from_jid") then
-- We're running >0.10 (new MUC API)
if muc then
return muc.get_room_from_jid(room_jid);
else
return
@@ -202,8 +208,7 @@ end
-- @param creator_group the group of the user who created the user which
-- presence we are updating (this is the poltergeist case, where a user creates
-- a poltergeist), optional.
function update_presence_identity(
stanza, user, group, creator_user, creator_group)
function update_presence_identity(stanza, user, group, creator_user, creator_group)
-- First remove any 'identity' element if it already
-- exists, so it cannot be spoofed by a client
@@ -216,7 +221,11 @@ function update_presence_identity(
end
return tag
end
)
);
if not user then
return;
end
stanza:tag("identity"):tag("user");
for k, v in pairs(user) do
@@ -250,28 +259,36 @@ end
-- Utility function to check whether feature is present and enabled. Allow
-- a feature if there are features present in the session(coming from
-- the token) and the value of the feature is true.
-- If features is not present in the token we skip feature detection and allow
-- everything.
function is_feature_allowed(features, ft)
if (features == nil or features[ft] == "true" or features[ft] == true) then
return true;
-- If features are missing but we have granted_features check that
-- if features are missing from the token we check whether it is moderator
function is_feature_allowed(ft, features, granted_features, is_moderator)
if features then
return features[ft] == "true" or features[ft] == true;
elseif granted_features then
return granted_features[ft] == "true" or granted_features[ft] == true;
else
return false;
return is_moderator;
end
end
--- Extracts the subdomain and room name from internal jid node [foo]room1
-- @return subdomain(optional, if extracted or nil), the room name
-- @return subdomain(optional, if extracted or nil), the room name, the customer_id in case of vpaas
function extract_subdomain(room_node)
local ret = extract_subdomain_cache:get(room_node);
if ret then
return ret.subdomain, ret.room;
return ret.subdomain, ret.room, ret.customer_id;
end
local subdomain, room_name = room_node:match("^%[([^%]]+)%](.+)$");
local cache_value = {subdomain=subdomain, room=room_name};
if not subdomain then
room_name = room_node;
end
local _, customer_id = subdomain and subdomain:match("^(vpaas%-magic%-cookie%-)(.*)$") or nil, nil;
local cache_value = { subdomain=subdomain, room=room_name, customer_id=customer_id };
extract_subdomain_cache:set(room_node, cache_value);
return subdomain, room_name;
return subdomain, room_name, customer_id;
end
function starts_with(str, start)
@@ -282,19 +299,33 @@ function starts_with(str, start)
end
function starts_with_one_of(str, prefixes)
if not str then
if not str or not prefixes then
return false;
end
for i=1,#prefixes do
if starts_with(str, prefixes[i]) then
return prefixes[i];
if is_set(prefixes) then
-- set is a table with keys and value of true
for k, _ in prefixes:items() do
if starts_with(str, k) then
return k;
end
end
else
for _, v in pairs(prefixes) do
if starts_with(str, v) then
return v;
end
end
end
return false
end
function ends_with(str, ending)
if not str then
return false;
end
return ending == "" or str:sub(-#ending) == ending
end
@@ -468,9 +499,38 @@ end
-- Returns the initiator extension if the stanza is coming from a sip jigasi
function is_sip_jigasi(stanza)
if not stanza then
return false;
end
return stanza:get_child('initiator', 'http://jitsi.org/protocol/jigasi');
end
-- This requires presence stanza being passed
function is_transcriber_jigasi(stanza)
if not stanza then
return false;
end
local features = stanza:get_child('features');
if not features then
return false;
end
for i = 1, #features do
local feature = features[i];
if feature.attr and feature.attr.var and feature.attr.var == 'http://jitsi.org/protocol/transcriber' then
return true;
end
end
return false;
end
function is_transcriber(jid)
return starts_with_one_of(jid, TRANSCRIBER_PREFIXES);
end
function get_sip_jibri_email_prefix(email)
if not email then
return nil;
@@ -508,6 +568,10 @@ function is_sip_jibri_join(stanza)
return false
end
function is_jibri(occupant)
return starts_with_one_of(type(occupant) == "string" and occupant or occupant.jid, RECORDER_PREFIXES)
end
-- process a host module directly if loaded or hooks to wait for its load
function process_host_module(name, callback)
local function process_host(host)
@@ -535,30 +599,107 @@ function table_shallow_copy(t)
return t2
end
local function table_find(tab, val)
if not tab then
return nil
end
for i, v in ipairs(tab) do
if v == val then
return i
end
end
return nil
end
-- Adds second table values to the first table
local function table_add(t1, t2)
for _,v in ipairs(t2) do
table.insert(t1, v);
end
end
-- Splits a string using delimiter
function split_string(str, delimiter)
str = str .. delimiter;
local result = array();
for w in str:gmatch("(.-)" .. delimiter) do
result:push(w);
end
return result;
end
-- send iq result that the iq was received and will be processed
function respond_iq_result(origin, stanza)
-- respond with successful receiving the iq
origin.send(st.iq({
type = 'result';
from = stanza.attr.to;
to = stanza.attr.from;
id = stanza.attr.id
}));
end
-- Note: http_server.get_request_from_conn() was added in Prosody 0.12.3,
-- this code provides backwards compatibility with older versions
local get_request_from_conn = http_server.get_request_from_conn or function (conn)
local response = conn and conn._http_open_response;
return response and response.request or nil;
end;
-- Discover real remote IP of a session
function get_ip(session)
local request = get_request_from_conn(session.conn);
return request and request.ip or session.ip;
end
-- Checks whether the provided jid is in the list of admins
-- we are not using the new permissions and roles api as we have few global modules which need to be
-- refactored into host modules, as that api needs to be executed in host context
local function is_admin(_jid)
local bare_jid = jid.bare(_jid);
if config_global_admin_jids:contains(bare_jid) or config_admin_jids:contains(bare_jid) then
return true;
end
return false;
end
return {
OUTBOUND_SIP_JIBRI_PREFIXES = OUTBOUND_SIP_JIBRI_PREFIXES;
INBOUND_SIP_JIBRI_PREFIXES = INBOUND_SIP_JIBRI_PREFIXES;
RECORDER_PREFIXES = RECORDER_PREFIXES;
extract_subdomain = extract_subdomain;
is_admin = is_admin;
is_feature_allowed = is_feature_allowed;
is_jibri = is_jibri;
is_healthcheck_room = is_healthcheck_room;
is_moderated = is_moderated;
is_sip_jibri_join = is_sip_jibri_join;
is_sip_jigasi = is_sip_jigasi;
is_transcriber = is_transcriber;
is_transcriber_jigasi = is_transcriber_jigasi;
is_vpaas = is_vpaas;
get_focus_occupant = get_focus_occupant;
get_ip = get_ip;
get_room_from_jid = get_room_from_jid;
get_room_by_name_and_subdomain = get_room_by_name_and_subdomain;
get_sip_jibri_email_prefix = get_sip_jibri_email_prefix;
async_handler_wrapper = async_handler_wrapper;
presence_check_status = presence_check_status;
process_host_module = process_host_module;
respond_iq_result = respond_iq_result;
room_jid_match_rewrite = room_jid_match_rewrite;
room_jid_split_subdomain = room_jid_split_subdomain;
internal_room_jid_match_rewrite = internal_room_jid_match_rewrite;
update_presence_identity = update_presence_identity;
http_get_with_retry = http_get_with_retry;
ends_with = ends_with;
split_string = split_string;
starts_with = starts_with;
starts_with_one_of = starts_with_one_of;
table_add = table_add;
table_shallow_copy = table_shallow_copy;
table_find = table_find;
};