Compare commits

...

6 Commits

Author SHA1 Message Date
Daniel Berteaud
e749b39e13 Update to 2025-07-28 13:00 2025-07-28 13:00:23 +02:00
Daniel Berteaud
58a1a78ce5 Update to 2025-07-28 10:00 2025-07-28 10:00:34 +02:00
Daniel Berteaud
cc8300da55 Update to 2025-07-17 00:00 2025-07-17 00:00:47 +02:00
Daniel Berteaud
1d891828f0 Update to 2025-07-15 10:00 2025-07-15 10:00:16 +02:00
Daniel Berteaud
0fcd8c4297 Update to 2025-07-15 00:00 2025-07-15 00:00:22 +02:00
Daniel Berteaud
65ebcfc093 Update to 2025-07-14 23:00 2025-07-14 23:00:12 +02:00
44 changed files with 806 additions and 191 deletions

View File

@@ -1,8 +1,8 @@
---
# Version of consul to deploy
consul_version: 1.21.2
consul_version: 1.21.3
# URL from where the consul archive will be downloaded
consul_archive_url: https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_linux_amd64.zip
# Expected sha256 of the archive
consul_archive_sha256: 07a738cc8f7937f28d1418e8f289b28445e82d5cbd0aabdbcf2b5a0cacf26a29
consul_archive_sha256: ba20631037a5f63f70b0351c0875887a66c0a0d3feac2d255a768c9eb8c95e8b

View File

@@ -1,11 +1,11 @@
---
# Version of consul-template to install
consul_tpl_version: 0.41.0
consul_tpl_version: 0.41.1
# URL of the archive
consul_tpl_archive_url: https://releases.hashicorp.com/consul-template/{{ consul_tpl_version }}/consul-template_{{ consul_tpl_version }}_linux_amd64.zip
# Expected sha256 of the archive
consul_tpl_archive_sha256: 64e732cdd75a778ea6a5e16b32792a1effc88963d37e73f0088a115ea790938f
consul_tpl_archive_sha256: ab68e09642437dcc5b6e9a572a1924d3969e4fe131f50a1a3a4f782d7a21f530
# Root dir where consul-template will be installed
consul_tpl_root_dir: /opt/consul_template

View File

@@ -1,11 +1,11 @@
---
# Version to install
gitea_version: '1.24.2'
gitea_version: '1.24.3'
# URL to the binary
gitea_bin_url: https://dl.gitea.io/gitea/{{ gitea_version }}/gitea-{{ gitea_version }}-linux-amd64
# sha256 of the binary
gitea_bin_sha256: 760604743561692fec3f008960e2f30100ae1b632d35199436d3ccc7e613fc91
gitea_bin_sha256: a454176defd183788f2e1334834fbae7c16a62de142bd71ee4c9b01700e55f6d
# Handle updates. If set to false, ansible will only install
# Gitea and then won't touch an existing installation
gitea_manage_upgrade: True

View File

@@ -16,5 +16,6 @@ transforms:
if (.file == "/var/log/httpd/error_log"){
.http = parse_apache_log!(.message, format:"error")
}
.timestamp = parse_timestamp(del(.http.timestamp), format: "%d/%h/%Y:%H:%M:%S %z") ?? now()
.service = "httpd"
.group = "web"

View File

@@ -9,16 +9,16 @@ jitsi_user: jitsi
jitsi_web_src_ip:
- 0.0.0.0/0
jitsi_version: 10314
jitsi_version: 10431
jitsi_jicofo_archive_url: https://github.com/jitsi/jicofo/archive/refs/tags/stable/jitsi-meet_{{ jitsi_version }}.tar.gz
jitsi_jicofo_archive_sha256: 0e081653d525462bfa1358ff6a25b091636792c4ac4a4fbf0b6235951d7cc4ac
jitsi_jicofo_archive_sha256: 5a575f97a4f5f24b2406712cd25196083ac33535bde998d72bb0acf07d727592
# Jigasi has no release, nor tags, so use master
jitsi_jigasi_archive_url: https://github.com/jitsi/jigasi/archive/refs/heads/master.tar.gz
jitsi_meet_archive_url: https://github.com/jitsi/jitsi-meet/archive/refs/tags/stable/jitsi-meet_{{ jitsi_version }}.tar.gz
jitsi_meet_archive_sha256: 04770928b232fb794206083f9f4cdfe24112ce8dd57e84c253380afb39ebc5d3
jitsi_meet_archive_sha256: 7402386e8ecb77ef3f6029b169aa07e6a56011d59ac0cb7019bfa1fdb3d8fcb3
jitsi_excalidraw_version: 2025.2.2
jitsi_excalidraw_archive_url: https://github.com/jitsi/excalidraw-backend/archive/refs/tags/{{ jitsi_excalidraw_version }}.tar.gz

View File

@@ -1,6 +1,6 @@
local avmoderation_component = module:get_option_string('av_moderation_component', 'avmoderation.'..module.host);
-- TODO: Remove this file after several stable releases when people update their configs
module:log('warn', 'mod_av_moderation is deprecated and will be removed in a future release. '
.. 'Please update your config by removing this module from the list of loaded modules.');
-- Advertise AV Moderation so client can pick up the address and use it
module:add_identity('component', 'av_moderation', avmoderation_component);
module:depends("jitsi_session");
module:depends('jitsi_session');
module:depends('features_identity');

View File

@@ -5,6 +5,7 @@ local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
local room_jid_match_rewrite = util.room_jid_match_rewrite;
local process_host_module = util.process_host_module;
local table_shallow_copy = util.table_shallow_copy;
local is_admin = util.is_admin;
local array = require "util.array";
local json = require 'cjson.safe';
local st = require 'util.stanza';
@@ -15,6 +16,12 @@ if muc_component_host == nil then
return;
end
local main_virtual_host = module:get_option_string('muc_mapper_domain_base');
if not main_virtual_host then
module:log('warn', 'No "muc_mapper_domain_base" option set, disabling AV moderation.');
return ;
end
module:log('info', 'Starting av_moderation for %s', muc_component_host);
-- Returns the index of the given element in the table
@@ -84,7 +91,7 @@ function notify_whitelist_change(jid, moderators, room, mediaType, removed)
body_json.mediaType = mediaType;
-- sanitize, make sure we don't have an empty array as it will encode it as {} not as []
for _,mediaType in pairs({'audio', 'video'}) do
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
if body_json.whitelists[mediaType] and #body_json.whitelists[mediaType] == 0 then
body_json.whitelists[mediaType] = nil;
end
@@ -145,6 +152,36 @@ function notify_jid_approved(jid, from, room, mediaType)
send_json_message(jid, json_message);
end
function start_av_moderation(room, mediaType, occupant)
if not room.av_moderation then
room.av_moderation = {};
room.av_moderation_actors = {};
end
room.av_moderation[mediaType] = array();
-- add all current moderators to the new whitelist
for _, room_occupant in room:each_occupant() do
if room_occupant.role == 'moderator' and not ends_with(room_occupant.nick, '/focus') then
room.av_moderation[mediaType]:push(internal_room_jid_match_rewrite(room_occupant.nick));
end
end
-- We want to set startMuted policy in metadata, in case of new participants are joining to respect
-- it, that will be enforced by jicofo
local startMutedMetadata = room.jitsiMetadata.startMuted or {};
-- We want to keep the previous value of startMuted for this mediaType if av moderation is disabled
-- to be able to restore
local av_moderation_startMuted_restore = room.av_moderation_startMuted_restore or {};
av_moderation_startMuted_restore[mediaType] = startMutedMetadata[mediaType];
room.av_moderation_startMuted_restore = av_moderation_startMuted_restore;
startMutedMetadata[mediaType] = true;
room.jitsiMetadata.startMuted = startMutedMetadata;
room.av_moderation_actors[mediaType] = occupant.nick;
end
-- receives messages from clients to the component sending A/V moderation enable/disable commands or adding
-- jids to the whitelist
function on_message(event)
@@ -185,7 +222,7 @@ function on_message(event)
local mediaType = moderation_command.attr.mediaType;
if mediaType then
if mediaType ~= 'audio' and mediaType ~= 'video' then
if mediaType ~= 'audio' and mediaType ~= 'video' and mediaType ~= 'desktop' then
module:log('warn', 'Wrong mediaType %s for %s', mediaType, room.jid);
return false;
end
@@ -202,26 +239,7 @@ function on_message(event)
module:log('warn', 'Concurrent moderator enable/disable request or something is out of sync');
return true;
else
if not room.av_moderation then
room.av_moderation = {};
room.av_moderation_actors = {};
end
room.av_moderation[mediaType] = array{};
-- We want to set startMuted policy in metadata, in case of new participants are joining to respect
-- it, that will be enforced by jicofo
local startMutedMetadata = room.jitsiMetadata.startMuted or {};
-- We want to keep the previous value of startMuted for this mediaType if av moderation is disabled
-- to be able to restore
local av_moderation_startMuted_restore = room.av_moderation_startMuted_restore or {};
av_moderation_startMuted_restore = startMutedMetadata[mediaType];
room.av_moderation_startMuted_restore = av_moderation_startMuted_restore;
startMutedMetadata[mediaType] = true;
room.jitsiMetadata.startMuted = startMutedMetadata;
room.av_moderation_actors[mediaType] = occupant.nick;
start_av_moderation(room, mediaType, occupant);
end
else
enabled = false;
@@ -251,6 +269,12 @@ function on_message(event)
-- send message to all occupants
notify_occupants_enable(nil, enabled, room, occupant.nick, mediaType);
if enabled then
-- inform all moderators for the newly created whitelist
notify_whitelist_change(nil, true, room, mediaType);
end
return true;
elseif moderation_command.attr.jidToWhitelist then
local occupant_jid = moderation_command.attr.jidToWhitelist;
@@ -311,12 +335,32 @@ end
function occupant_joined(event)
local room, occupant = event.room, event.occupant;
if is_healthcheck_room(room.jid) then
if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) then
return;
end
-- when first moderator joins if av_can_unmute from password preset is set to false, we enable av moderation for both
-- audio and video, and set the first moderator as the actor that enabled it
if room._data.av_can_unmute ~= nil
and not room._data.av_first_moderator_joined
-- occupant.role is not reflecting the actual role after set_affiliation is used in same occupant_joined event
and room:get_role(occupant.nick) == 'moderator' then
if not room._data.av_can_unmute then
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
start_av_moderation(room, mediaType, occupant);
notify_occupants_enable(nil, true, room, occupant.nick, mediaType);
end
room._data.av_first_moderator_joined = true;
return;
end
end
if room.av_moderation then
for _,mediaType in pairs({'audio', 'video'}) do
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
if room.av_moderation[mediaType] then
notify_occupants_enable(
occupant.jid, true, room, room.av_moderation_actors[mediaType], mediaType);
@@ -326,9 +370,13 @@ function occupant_joined(event)
-- NOTE for some reason event.occupant.role is not reflecting the actual occupant role (when changed
-- from allowners module) but iterating over room occupants returns the correct role
for _, room_occupant in room:each_occupant() do
-- if moderator send the whitelist
if room_occupant.nick == occupant.nick and room_occupant.role == 'moderator' then
notify_whitelist_change(room_occupant.jid, false, room);
-- if it is a moderator, send the whitelist to every moderator
if room_occupant.nick == occupant.nick and room_occupant.role == 'moderator' then
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
if room.av_moderation[mediaType] then
notify_whitelist_change(nil, true, room, mediaType);
end
end
end
end
end
@@ -336,14 +384,30 @@ end
-- when a occupant was granted moderator we need to update him with the whitelist
function occupant_affiliation_changed(event)
local room = event.room;
if not room.av_moderation or is_healthcheck_room(room.jid) or is_admin(event.jid)
or event.affiliation ~= 'owner' then
return;
end
-- in any enabled media type add the new moderator to the whitelist
for _, room_occupant in room:each_occupant() do
if room_occupant.bare_jid == event.jid then
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
if room.av_moderation[mediaType] then
room.av_moderation[mediaType]:push(internal_room_jid_match_rewrite(room_occupant.nick));
end
end
end
end
-- the actor can be nil if is coming from allowners or similar module we want to skip it here
-- as we will handle it in occupant_joined
if event.actor and event.affiliation == 'owner' and event.room.av_moderation then
local room = event.room;
-- event.jid is the bare jid of participant
for _, occupant in room:each_occupant() do
if occupant.bare_jid == event.jid then
notify_whitelist_change(occupant.jid, false, room);
if event.actor and event.affiliation == 'owner' then
-- notify all moderators for the new grant moderator and the change in whitelists
for _,mediaType in pairs({'audio', 'video', 'desktop'}) do
if room.av_moderation[mediaType] then
notify_whitelist_change(nil, true, room, mediaType);
end
end
end
@@ -357,3 +421,9 @@ process_host_module(muc_component_host, function(host_module, host)
host_module:hook('muc-occupant-joined', occupant_joined, -2); -- make sure it runs after allowners or similar
host_module:hook('muc-set-affiliation', occupant_affiliation_changed, -1);
end);
process_host_module(main_virtual_host, function(host_module)
module:context(host_module.host):fire_event('jitsi-add-identity', {
name = 'av_moderation'; host = module.host;
});
end);

View File

@@ -1,24 +1,21 @@
-- This module is added under the main virtual host domain
--
-- VirtualHost "jitmeet.example.com"
-- modules_enabled = {
-- "end_conference"
-- }
-- end_conference_component = "endconference.jitmeet.example.com"
--
-- Component "endconference.jitmeet.example.com" "end_conference"
-- muc_component = muc.jitmeet.example.com
--
local get_room_by_name_and_subdomain = module:require 'util'.get_room_by_name_and_subdomain;
local util = module:require 'util';
local get_room_by_name_and_subdomain = util.get_room_by_name_and_subdomain;
local process_host_module = util.process_host_module;
local END_CONFERENCE_REASON = 'The meeting has been terminated';
-- Since this file serves as both the host module and the component, we rely on the assumption that
-- end_conference_component var would only be define for the host and not in the end_conference component
-- TODO: Remove this if block after several stable releases when people update their configs
local end_conference_component = module:get_option_string('end_conference_component');
if end_conference_component then
-- Advertise end conference so client can pick up the address and use it
module:add_identity('component', 'end_conference', end_conference_component);
module:log('warn', 'Please update your config by removing muc_end_conference module from '
.. 'the list of loaded modules in the main virtual host.');
module:depends("features_identity");
return; -- nothing left to do if called as host module
end
@@ -32,6 +29,12 @@ if muc_component_host == nil then
return;
end
local main_virtual_host = module:get_option_string('muc_mapper_domain_base');
if not main_virtual_host then
module:log('warn', 'No "muc_mapper_domain_base" option set, disabling end conference component.');
return ;
end
module:log('info', 'Starting end_conference for %s', muc_component_host);
-- receives messages from clients to the component to end a conference
@@ -84,3 +87,9 @@ end
-- we will receive messages from the clients
module:hook('message/host', on_message);
process_host_module(main_virtual_host, function(host_module)
module:context(host_module.host):fire_event('jitsi-add-identity', {
name = 'end_conference'; host = module.host;
});
end);

View File

@@ -0,0 +1,8 @@
-- Other components can use the event 'jitsi-add-identity' to attach identity which
-- will be advertised by the main virtual host and discovered by clients.
-- With this we avoid having an almost empty module to just add identity with an extra config
module:hook('jitsi-add-identity', function(event)
module:log('info', 'Adding identity %s for host %s', event.name, event.host);
module:add_identity('component', event.name, event.host);
end);

View File

@@ -0,0 +1,245 @@
local json = require 'cjson.safe';
local jid = require 'util.jid';
local st = require 'util.stanza';
local util = module:require 'util';
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
local is_admin = util.is_admin;
local process_host_module = util.process_host_module;
local FILE_SHARING_IDENTITY_TYPE = 'file-sharing';
local JSON_TYPE_ADD_FILE = 'add';
local JSON_TYPE_REMOVE_FILE = 'remove';
local JSON_TYPE_LIST_FILES = 'list';
local NICK_NS = 'http://jabber.org/protocol/nick';
-- this is the main virtual host of the main prosody that this vnode serves
local main_domain = module:get_option_string('main_domain');
-- only the visitor prosody has main_domain setting
local is_visitor_prosody = main_domain ~= nil;
local muc_component_host = module:get_option_string('muc_component');
if muc_component_host == nil then
module:log('error', 'No muc_component specified. No muc to operate on!');
return;
end
local muc_domain_base = module:get_option_string("muc_mapper_domain_base");
if not muc_domain_base then
module:log("warn", "No 'muc_domain_base' option set, disabling file sharing component.");
return ;
end
-- receives messages from clients to the component sending file sharing commands for adding or removing files
function on_message(event)
local session, stanza = event.origin, event.stanza;
-- Check the type of the incoming stanza to avoid loops:
if stanza.attr.type == 'error' then
return; -- We do not want to reply to these, so leave.
end
if not session or not session.jitsi_web_query_room then
return false;
end
local message = stanza:get_child(FILE_SHARING_IDENTITY_TYPE, 'http://jitsi.org/jitmeet');
if not message then
return false;
end
-- get room name with tenant and find room
local room = get_room_by_name_and_subdomain(session.jitsi_web_query_room, session.jitsi_web_query_prefix);
if not room then
module:log('warn', 'No room found for %s/%s', session.jitsi_web_query_prefix, session.jitsi_web_query_room);
return false;
end
-- check that the participant sending the message is an occupant in the room
local from = stanza.attr.from;
local occupant = room:get_occupant_by_real_jid(from);
if not occupant then
module:log('warn', 'No occupant %s found for %s', from, room.jid);
return false;
end
if not is_feature_allowed(
'file-upload',
session.jitsi_meet_context_features,
room:get_affiliation(stanza.attr.from) == 'owner') then
session.send(st.error_reply(stanza, 'auth', 'forbidden'));
return true;
end
if message.attr.type == JSON_TYPE_ADD_FILE then
local msg_obj, error = json.decode(message:get_text());
if error then
module:log('error','Error decoding data error:%s %s', error, stanza);
return false;
end
if not msg_obj.fileId then
module:log('error', 'Error missing required field: %s', stanza);
return false;
end
-- make sure we overwrite data for sender so we avoid spoofing
msg_obj.authorParticipantId = jid.resource(occupant.nick);
msg_obj.authorParticipantJid = from;
local nick_element = occupant:get_presence():get_child('nick', NICK_NS);
if nick_element then
msg_obj.authorParticipantName = nick_element:get_text();
else
msg_obj.authorParticipantName = 'anonymous';
end
msg_obj.conferenceFullName = internal_room_jid_match_rewrite(room.jid);
module:context(muc_domain_base):fire_event('jitsi-filesharing-add', {
room = room; file = msg_obj; actor = occupant.nick;
});
module:context(muc_domain_base):fire_event('jitsi-filesharing-updated', {
room = room;
});
return true;
elseif message.attr.type == JSON_TYPE_REMOVE_FILE then
if not message.attr.fileId then
module:log('error', 'Error missing required field: %s', stanza);
return true;
end
module:context(muc_domain_base):fire_event('jitsi-filesharing-remove', {
room = room; id = message.attr.fileId; actor = occupant.nick;
});
module:context(muc_domain_base):fire_event('jitsi-filesharing-updated', {
room = room;
});
return true;
else
-- return error.
return false;
end
end
-- handles new occupants to inform them about any file shared by other participants
function occupant_joined(event)
local room, occupant = event.room, event.occupant;
-- healthcheck rooms does not have shared files
if not room.jitsi_shared_files
or is_admin(occupant.bare_jid)
or not room.jitsi_shared_files
or next(room.jitsi_shared_files) == nil then
return;
end
-- send file list to the new occupant
local json_msg, error = json.encode({
type = FILE_SHARING_IDENTITY_TYPE,
event = JSON_TYPE_LIST_FILES,
files = room.jitsi_shared_files
});
local stanza = st.message({ from = module.host; to = occupant.jid; })
:tag('json-message', { xmlns = 'http://jitsi.org/jitmeet' })
:text(json_msg):up();
module:send(stanza);
end
process_host_module(muc_component_host, function(host_module, host)
module:log('info','Hook to muc events on %s', host);
host_module:hook('muc-occupant-joined', occupant_joined, -10); -- make sure it runs after allowners or similar
end);
-- we will receive messages from the clients
module:hook('message/host', on_message);
process_host_module(muc_domain_base, function(host_module, host)
module:context(muc_domain_base):fire_event('jitsi-add-identity', {
name = FILE_SHARING_IDENTITY_TYPE; host = module.host;
});
module:context(muc_domain_base):hook('jitsi-filesharing-add', function(event)
local actor, file, room = event.actor, event.file, event.room;
if not room.jitsi_shared_files then
room.jitsi_shared_files = {};
end
room.jitsi_shared_files[file.fileId] = file;
local json_msg, error = json.encode({
type = FILE_SHARING_IDENTITY_TYPE,
event = JSON_TYPE_ADD_FILE,
file = file
});
if not json_msg then
module:log('error', 'skip sending add request room:%s error:%s', room.jid, error);
return false
end
local stanza = st.message({ from = module.host; }):tag('json-message', { xmlns = 'http://jitsi.org/jitmeet' })
:text(json_msg):up();
-- send add file to all occupants except jicofo and sender
-- if this is visitor prosody send it only to visitors
for _, room_occupant in room:each_occupant() do
local send_event = not is_admin(room_occupant.bare_jid) and room_occupant.nick ~= actor;
if is_visitor_prosody then
send_event = room_occupant.role == 'visitor';
end
if send_event then
local to_send = st.clone(stanza);
to_send.attr.to = room_occupant.jid;
module:send(to_send);
end
end
end);
module:context(muc_domain_base):hook('jitsi-filesharing-remove', function(event)
local actor, id, room = event.actor, event.id, event.room;
if not room.jitsi_shared_files then
return;
end
room.jitsi_shared_files[id] = nil;
local json_msg, error = json.encode({
type = FILE_SHARING_IDENTITY_TYPE,
event = JSON_TYPE_REMOVE_FILE,
fileId = id
});
if not json_msg then
module:log('error', 'skip sending remove request room:%s error:%s', room.jid, error);
return false
end
local stanza = st.message({ from = module.host; }):tag('json-message', { xmlns = 'http://jitsi.org/jitmeet' })
:text(json_msg):up();
-- send remove file to all occupants except jicofo and sender
-- if this is visitor prosody send it only to visitors
for _, room_occupant in room:each_occupant() do
local send_event = not is_admin(room_occupant.bare_jid) and room_occupant.nick ~= actor;
if is_visitor_prosody then
send_event = room_occupant.role == 'visitor';
end
if send_event then
local to_send = st.clone(stanza);
to_send.attr.to = room_occupant.jid;
module:send(to_send);
end
end
end);
end);

View File

@@ -38,7 +38,6 @@ module:hook("pre-iq/full", function(event)
local is_allowed = is_feature_allowed(
feature,
session.jitsi_meet_context_features,
session.granted_jitsi_meet_context_features,
occupant.role == 'moderator');
if jibri.attr.action == 'start' or jibri.attr.action == 'stop' then

View File

@@ -107,7 +107,6 @@ module:hook("pre-iq/full", function(event)
local is_session_allowed = is_feature_allowed(
feature,
session.jitsi_meet_context_features,
session.granted_jitsi_meet_context_features,
room:get_affiliation(stanza.attr.from) == 'owner');
if roomName == nil

View File

@@ -16,6 +16,7 @@ local new_id = require 'util.id'.medium;
local filters = require 'util.filters';
local array = require 'util.array';
local set = require 'util.set';
local json = require 'cjson.safe';
local util = module:require 'util';
local is_admin = util.is_admin;
@@ -27,6 +28,7 @@ local get_focus_occupant = util.get_focus_occupant;
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
local presence_check_status = util.presence_check_status;
local respond_iq_result = util.respond_iq_result;
local table_compare = util.table_compare;
local PARTICIPANT_PROP_RAISE_HAND = 'jitsi_participant_raisedHand';
local PARTICIPANT_PROP_REQUEST_TRANSCRIPTION = 'jitsi_participant_requestingTranscription';
@@ -672,6 +674,29 @@ local function iq_from_main_handler(event)
end
end
local files = node:get_child('files');
if files then
local received_files = {};
for _, child in ipairs(files.tags) do
if child.name == 'file' then
received_files[child.attr.id] = json.decode(child:get_text());
end
end
-- fire events so file sharing component will add/remove files and will notify clients
local removed, added = table_compare(room.jitsi_shared_files or {}, received_files)
for _, id in ipairs(removed) do
module:context(local_domain):fire_event('jitsi-filesharing-remove', {
room = room; id = id;
});
end
for _, id in ipairs(added) do
module:context(local_domain):fire_event('jitsi-filesharing-add', {
room = room; file = received_files[id];
});
end
end
if fire_jicofo_unlock then
-- everything is connected allow participants to join
module:fire_event('jicofo-unlock-room', { room = room; fmuc_fired = true; });

View File

@@ -16,7 +16,7 @@ local muc_domain_prefix = module:get_option_string('muc_mapper_domain_prefix', '
local muc_domain_base = module:get_option_string('muc_mapper_domain_base');
if not muc_domain_base then
module:log('warn', 'No "muc_domain_base" option set, disabling kick check endpoint.');
module:log('warn', 'No "muc_domain_base" option set, disabling module.');
return ;
end
@@ -71,15 +71,16 @@ function process_set_affiliation(event)
end
if previous_affiliation == 'none' and affiliation == 'owner' then
occupant_session.granted_jitsi_meet_context_features = actor_session.jitsi_meet_context_features;
occupant_session.jitsi_meet_context_features = actor_session.jitsi_meet_context_features;
if actor_session.jitsi_meet_context_user then
occupant_session.granted_jitsi_meet_context_user_id = actor_session.jitsi_meet_context_user['id']
or actor_session.granted_jitsi_meet_context_user_id;
end
occupant_session.granted_jitsi_meet_context_group_id = actor_session.jitsi_meet_context_group
or actor_session.granted_jitsi_meet_context_group_id;
-- even if token and features are set we may want to re-send permissions
occupant_session.force_permissions_update = true;
elseif previous_affiliation == 'owner' and ( affiliation == 'member' or affiliation == 'none' ) then
occupant_session.granted_jitsi_meet_context_features = nil;
occupant_session.granted_jitsi_meet_context_user_id = nil;
occupant_session.granted_jitsi_meet_context_group_id = nil;
@@ -154,22 +155,16 @@ function filter_stanza(stanza, session)
session.force_permissions_update = false;
local permissions_to_send
= session.jitsi_meet_context_features or session.granted_jitsi_meet_context_features or default_permissions;
if not session.jitsi_meet_context_features then
session.jitsi_meet_context_features = default_permissions;
end
room.send_default_permissions_to[bare_to] = nil;
if not session.granted_jitsi_meet_context_features and not session.jitsi_meet_context_features then
session.jitsi_meet_context_features = {};
end
stanza:tag('permissions', { xmlns='http://jitsi.org/jitmeet' });
for k, v in pairs(permissions_to_send) do
for k, v in pairs(session.jitsi_meet_context_features) do
local val = tostring(v);
stanza:tag('p', { name = k, val = val }):up();
if session.jitsi_meet_context_features then
session.jitsi_meet_context_features[k] = val;
end
end
stanza:up();

View File

@@ -23,7 +23,7 @@ load_config();
-- List of the bare_jids of all occupants that are currently joining (went through pre-join) and will be promoted
-- as moderators. As pre-join (where added) and joined event (where removed) happen one after another this list should
-- have length of 1
local joining_moderator_participants = {};
local joining_moderator_participants = module:shared('moderators/joining_moderator_participants');
module:hook("muc-room-created", function(event)
local room = event.room;

View File

@@ -0,0 +1,56 @@
--- This module removes identity information from presence stanzas when the
--- hideDisplayNameForAll or hideDisplayNameForGuests options are enabled
--- for a room.
--- To be enabled under the main muc component
local filters = require 'util.filters';
local st = require 'util.stanza';
local util = module:require 'util';
local filter_identity_from_presence = util.filter_identity_from_presence;
local get_room_by_name_and_subdomain = util.get_room_by_name_and_subdomain;
local is_admin = util.is_admin;
local ends_with = util.ends_with;
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
-- we need to get the shared resource for joining moderators, as participants are marked as moderators
-- after joining which is after the filter for stanza/out, but we need to know will this participant be a moderator
local joining_moderator_participants = module:shared('moderators/joining_moderator_participants');
--- Filter presence sent to non-moderator members of a room when the hideDisplayNameForGuests option is set.
function filter_stanza_out(stanza, session)
if stanza.name ~= 'presence' or stanza.attr.type == 'error'
or stanza.attr.type == 'unavailable' or ends_with(stanza.attr.from, '/focus') then
return stanza;
end
local room = get_room_by_name_and_subdomain(session.jitsi_web_query_room, session.jitsi_web_query_prefix);
local shouldFilter = false;
if room and (room._data.hideDisplayNameForGuests == true or room._data.hideDisplayNameForAll == true) then
local occupant = room:get_occupant_by_real_jid(stanza.attr.to);
-- don't touch self-presence
if occupant and stanza.attr.from ~= internal_room_jid_match_rewrite(occupant.nick) then
local isModerator = (occupant.role == 'moderator' or joining_moderator_participants[occupant.bare_jid]);
shouldFilter = room._data.hideDisplayNameForAll or not isModerator;
end
end
if shouldFilter then
return filter_identity_from_presence(stanza);
else
return stanza;
end
end
function filter_session(session)
filters.add_filter(session, 'stanzas/out', filter_stanza_out, -100);
end
function module.load()
filters.add_filter_hook(filter_session);
end
function module.unload()
filters.remove_filter_hook(filter_session);
end

View File

@@ -184,7 +184,8 @@ module:hook('message/bare', function(event)
return;
end
local json_message = stanza:get_child_text('json-message', 'http://jitsi.org/jitmeet');
local json_message = stanza:get_child_text('json-message', 'http://jitsi.org/jitmeet')
or stanza:get_child_text('json-message');
if not json_message then
return;
end

View File

@@ -17,7 +17,7 @@ local disable_auto_owners = module:get_option_boolean('wait_for_host_disable_aut
local muc_domain_base = module:get_option_string('muc_mapper_domain_base');
if not muc_domain_base then
module:log('warn', "No 'muc_mapper_domain_base' option set, disabling muc_mapper plugin inactive");
module:log('warn', "No 'muc_mapper_domain_base' option set, disabling module");
return
end

View File

@@ -1,10 +1,6 @@
-- Generic room metadata
-- See mod_room_metadata_component.lua
local COMPONENT_IDENTITY_TYPE = 'room_metadata';
local room_metadata_component_host = module:get_option_string('room_metadata_component', 'metadata.'..module.host);
-- TODO: Remove this file after several stable releases when people update their configs
module:log('warn', 'mod_room_metadata is deprecated and will be removed in a future release. '
.. 'Please update your config by removing this module from the list of loaded modules.');
module:depends("jitsi_session");
-- Advertise the component so clients can pick up the address and use it
module:add_identity('component', COMPONENT_IDENTITY_TYPE, room_metadata_component_host);
module:depends("features_identity");

View File

@@ -1,18 +1,12 @@
-- This module implements a generic metadata storage system for rooms.
--
-- VirtualHost "jitmeet.example.com"
-- modules_enabled = {
-- "room_metadata"
-- }
-- room_metadata_component = "metadata.jitmeet.example.com"
-- main_muc = "conference.jitmeet.example.com"
--
-- Component "metadata.jitmeet.example.com" "room_metadata_component"
-- muc_component = "conference.jitmeet.example.com"
-- breakout_rooms_component = "breakout.jitmeet.example.com"
local array = require 'util.array';
local filters = require 'util.filters';
local jid_node = require 'util.jid'.node;
local json = require 'cjson.safe';
local json = require 'util.json';
local st = require 'util.stanza';
local jid = require 'util.jid';
@@ -25,6 +19,7 @@ local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
local process_host_module = util.process_host_module;
local table_shallow_copy = util.table_shallow_copy;
local table_add = util.table_add;
local table_equals = util.table_equals;
local MUC_NS = 'http://jabber.org/protocol/muc';
local COMPONENT_IDENTITY_TYPE = 'room_metadata';
@@ -37,9 +32,9 @@ if muc_component_host == nil then
return;
end
local muc_domain_base = module:get_option_string('muc_mapper_domain_base');
if not muc_domain_base then
module:log('warn', 'No muc_domain_base option set.');
local main_virtual_host = module:get_option_string('muc_mapper_domain_base');
if not main_virtual_host then
module:log('warn', 'No muc_mapper_domain_base option set.');
return;
end
@@ -85,24 +80,25 @@ function send_metadata(occupant, room, json_msg)
-- we want to send the main meeting participants only to jicofo
if is_admin(occupant.bare_jid) then
local participants = {};
local participants;
local moderators = array();
if room._data.mainMeetingParticipants then
table_add(participants, room._data.mainMeetingParticipants);
if room._data.participants then
participants = array();
participants:append(room._data.participants);
end
if room._data.moderator_id then
table.insert(participants, room._data.moderator_id);
moderators:push(room._data.moderator_id);
end
if room._data.moderators then
table_add(participants, room._data.moderators);
moderators:append(room._data.moderators);
end
if #participants > 0 then
metadata_to_send = table_shallow_copy(metadata_to_send);
metadata_to_send.mainMeetingParticipants = participants;
end
metadata_to_send = table_shallow_copy(metadata_to_send);
metadata_to_send.participants = participants;
metadata_to_send.moderators = moderators;
end
json_msg = getMetadataJSON(room, metadata_to_send);
@@ -182,7 +178,7 @@ function on_message(event)
if occupant.role ~= 'moderator' then
-- will return a non nil filtered data to use, if it is nil, it is not allowed
local res = module:context(muc_domain_base):fire_event('jitsi-metadata-allow-moderation',
local res = module:context(main_virtual_host):fire_event('jitsi-metadata-allow-moderation',
{ room = room; actor = occupant; key = jsonData.key ; data = jsonData.data; session = session; });
if not res then
@@ -193,12 +189,15 @@ function on_message(event)
jsonData.data = res;
end
room.jitsiMetadata[jsonData.key] = jsonData.data;
local old_value = room.jitsiMetadata[jsonData.key];
if not table_equals(old_value, jsonData.data) then
room.jitsiMetadata[jsonData.key] = jsonData.data;
broadcastMetadata(room);
broadcastMetadata(room);
-- fire and event for the change
main_muc_module:fire_event('jitsi-metadata-updated', { room = room; actor = occupant; key = jsonData.key; });
-- fire and event for the change
main_muc_module:fire_event('jitsi-metadata-updated', { room = room; actor = occupant; key = jsonData.key; });
end
return true;
end
@@ -243,12 +242,24 @@ function process_main_muc_loaded(main_muc, host_module)
local startMutedMetadata = room.jitsiMetadata.startMuted or {};
startMutedMetadata.audio = startMuted.attr.audio == 'true';
startMutedMetadata.video = startMuted.attr.video == 'true';
local audioNewValue = startMuted.attr.audio == 'true';
local videoNewValue = startMuted.attr.video == 'true';
local send_update = false;
room.jitsiMetadata.startMuted = startMutedMetadata;
if startMutedMetadata.audio ~= audioNewValue then
startMutedMetadata.audio = audioNewValue;
send_update = true;
end
if startMutedMetadata.video ~= videoNewValue then
startMutedMetadata.video = videoNewValue;
send_update = true;
end
host_module:fire_event('room-metadata-changed', { room = room; });
if send_update then
room.jitsiMetadata.startMuted = startMutedMetadata;
host_module:fire_event('room-metadata-changed', { room = room; });
end
end);
end
@@ -342,3 +353,9 @@ end
-- enable filtering presences
filters.add_filter_hook(filter_session);
process_host_module(main_virtual_host, function(host_module)
module:context(host_module.host):fire_event('jitsi-add-identity', {
name = 'room_metadata'; host = module.host;
});
end);

View File

@@ -62,19 +62,19 @@ function generateToken(session, audience, room, occupant)
exp = exp,
sub = session.jitsi_web_query_prefix or module.host,
context = {
group = session.jitsi_meet_context_group or session.granted_jitsi_meet_context_group,
group = session.jitsi_meet_context_group or session.granted_jitsi_meet_context_group_id,
user = session.jitsi_meet_context_user or {
id = session.full_jid,
name = presence:get_child_text('nick', 'http://jabber.org/protocol/nick'),
email = presence:get_child_text("email") or nil,
nick = jid.resource(occupant.nick)
},
features = session.jitsi_meet_context_features or session.granted_jitsi_meet_context_features
features = session.jitsi_meet_context_features
},
room = session.jitsi_web_query_room,
meeting_id = room._data.meetingId,
granted_from = session.granted_jitsi_meet_context_user_id,
customer_id = id or session.jitsi_meet_context_group or session.granted_jitsi_meet_context_group,
customer_id = id or session.jitsi_meet_context_group or session.granted_jitsi_meet_context_group_id,
backend_region = server_region_name,
user_region = session.user_region
};
@@ -115,6 +115,8 @@ module:hook('external_service/credentials', function (event)
password = generateToken(session, host, room, occupant);
expires = os.time() + options.ttl_seconds;
restricted = true;
transport = 'https';
port = 443;
});
end
end

View File

@@ -1,6 +1,6 @@
local speakerstats_component
= module:get_option_string("speakerstats_component", "speakerstats."..module.host);
-- TODO: Remove this file after several stable releases when people update their configs
module:log('warn', 'mod_speakerstats is deprecated and will be removed in a future release. '
.. 'Please update your config by removing this module from the list of loaded modules.');
-- Advertise speaker stats so client can pick up the address and start sending
-- dominant speaker events
module:add_identity("component", "speakerstats", speakerstats_component);
module:depends('jitsi_session');
module:depends('features_identity');

View File

@@ -20,13 +20,13 @@ if not have_async then
end
local muc_component_host = module:get_option_string("muc_component");
local muc_domain_base = module:get_option_string("muc_mapper_domain_base");
local main_virtual_host = module:get_option_string("muc_mapper_domain_base");
if muc_component_host == nil or muc_domain_base == nil then
if muc_component_host == nil or main_virtual_host == nil then
module:log("error", "No muc_component specified. No muc to operate on!");
return;
end
local breakout_room_component_host = "breakout." .. muc_domain_base;
local breakout_room_component_host = "breakout." .. main_virtual_host;
module:log("info", "Starting speakerstats for %s", muc_component_host);
@@ -376,3 +376,9 @@ process_host_module(breakout_room_component_host, function(host_module, host)
end);
end
end);
process_host_module(main_virtual_host, function(host_module)
module:context(host_module.host):fire_event('jitsi-add-identity', {
name = 'speakerstats'; host = module.host;
});
end);

View File

@@ -12,10 +12,15 @@ local st = require 'util.stanza';
local jid = require 'util.jid';
local new_id = require 'util.id'.medium;
local util = module:require 'util';
local filter_identity_from_presence = util.filter_identity_from_presence;
local is_admin = util.is_admin;
local presence_check_status = util.presence_check_status;
local process_host_module = util.process_host_module;
local is_transcriber_jigasi = util.is_transcriber_jigasi;
local json = require 'cjson.safe';
-- Debug flag
local DEBUG = false;
local MUC_NS = 'http://jabber.org/protocol/muc';
@@ -78,6 +83,17 @@ local function send_visitors_iq(conference_service, room, type)
end
visitors_iq:up();
-- files that are shared in the room
if room.jitsi_shared_files then
visitors_iq:tag('files', { xmlns = 'jitsi:visitors' });
for k, v in pairs(room.jitsi_shared_files) do
visitors_iq:tag('file', {
id = k
}):text(json.encode(v)):up();
end
visitors_iq:up();
end
end
visitors_iq:up();
@@ -85,6 +101,25 @@ local function send_visitors_iq(conference_service, room, type)
module:send(visitors_iq);
end
-- Filter out identity information (nick name, email, etc) from a presence stanza,
-- if the hideDisplayNameForGuests option for the room is set (note that the
-- hideDisplayNameForAll option is implemented in a diffrent way and does not
-- require filtering here)
-- This is applied to presence of main room participants before it is sent out to
-- vnodes.
local function filter_stanza_nick_if_needed(stanza, room)
if not stanza or stanza.name ~= 'presence' or stanza.attr.type == 'error' or stanza.attr.type == 'unavailable' then
return stanza;
end
-- if hideDisplayNameForGuests we want to drop any display name from the presence stanza
if room and (room._data.hideDisplayNameForGuests or room._data.hideDisplayNameForAll) then
return filter_identity_from_presence(stanza);
end
return stanza;
end
-- an event received from visitors component, which receives iqs from jicofo
local function connect_vnode(event)
local room, vnode = event.room, event.vnode;
@@ -111,7 +146,7 @@ local function connect_vnode(event)
for _, o in room:each_occupant() do
if not is_admin(o.bare_jid) then
local fmuc_pr = st.clone(o:get_presence());
local fmuc_pr = filter_stanza_nick_if_needed(st.clone(o:get_presence()), room);
local user, _, res = jid.split(o.nick);
fmuc_pr.attr.to = jid.join(user, conference_service , res);
fmuc_pr.attr.from = o.jid;
@@ -194,7 +229,8 @@ end, 900);
process_host_module(main_muc_component_config, function(host_module, host)
-- detects presence change in a main participant and propagate it to the used visitor nodes
host_module:hook('muc-occupant-pre-change', function (event)
local room, stanza, occupant = event.room, event.stanza, event.dest_occupant;
local room, stanzaEv, occupant = event.room, event.stanza, event.dest_occupant;
local stanza = filter_stanza_nick_if_needed(stanzaEv, room);
-- filter focus and configured domains (used for jibri and transcribers)
if is_admin(stanza.attr.from) or visitors_nodes[room.jid] == nil
@@ -215,7 +251,8 @@ process_host_module(main_muc_component_config, function(host_module, host)
-- when a main participant leaves inform the visitor nodes
host_module:hook('muc-occupant-left', function (event)
local room, stanza, occupant = event.room, event.stanza, event.occupant;
local room, stanzaEv, occupant = event.room, event.stanza, event.occupant;
local stanza = filter_stanza_nick_if_needed(stanzaEv, room);
-- ignore configured domains (jibri and transcribers)
if is_admin(occupant.bare_jid) or visitors_nodes[room.jid] == nil or visitors_nodes[room.jid].nodes == nil
@@ -258,7 +295,8 @@ process_host_module(main_muc_component_config, function(host_module, host)
-- detects new participants joining main room and sending them to the visitor nodes
host_module:hook('muc-occupant-joined', function (event)
local room, stanza, occupant = event.room, event.stanza, event.occupant;
local room, stanzaEv, occupant = event.room, event.stanza, event.occupant;
local stanza = filter_stanza_nick_if_needed(stanzaEv, room);
-- filter focus, ignore configured domains (jibri and transcribers)
if is_admin(stanza.attr.from) or visitors_nodes[room.jid] == nil
@@ -282,7 +320,8 @@ process_host_module(main_muc_component_config, function(host_module, host)
end);
-- forwards messages from main participants to vnodes
host_module:hook('muc-occupant-groupchat', function(event)
local room, stanza, occupant = event.room, event.stanza, event.occupant;
local room, stanzaEv, occupant = event.room, event.stanza, event.occupant;
local stanza = filter_stanza_nick_if_needed(stanzaEv, room);
-- filter sending messages from transcribers/jibris to visitors
if not visitors_nodes[room.jid] then
@@ -302,7 +341,8 @@ process_host_module(main_muc_component_config, function(host_module, host)
-- receiving messages from visitor nodes and forward them to local main participants
-- and forward them to the rest of visitor nodes
host_module:hook('muc-occupant-groupchat', function(event)
local occupant, room, stanza = event.occupant, event.room, event.stanza;
local occupant, room, stanzaEv = event.occupant, event.room, event.stanza;
local stanza = filter_stanza_nick_if_needed(stanzaEv, room);
local to = stanza.attr.to;
local from = stanza.attr.from;
local from_vnode = jid.host(from);
@@ -370,23 +410,17 @@ process_host_module(main_muc_component_config, function(host_module, host)
end, -2);
end);
module:hook('jitsi-lobby-enabled', function(event)
local function update_vnodes_for_room(event)
local room = event.room;
if visitors_nodes[room.jid] then
-- we need to update all vnodes
local vnodes = visitors_nodes[room.jid].nodes;
for conference_service in pairs(vnodes) do
send_visitors_iq(conference_service, room, 'update');
if visitors_nodes[room.jid] then
-- we need to update all vnodes
local vnodes = visitors_nodes[room.jid].nodes;
for conference_service in pairs(vnodes) do
send_visitors_iq(conference_service, room, 'update');
end
end
end
end);
module:hook('jitsi-lobby-disabled', function(event)
local room = event.room;
if visitors_nodes[room.jid] then
-- we need to update all vnodes
local vnodes = visitors_nodes[room.jid].nodes;
for conference_service in pairs(vnodes) do
send_visitors_iq(conference_service, room, 'update');
end
end
end);
end
module:hook('jitsi-lobby-enabled', update_vnodes_for_room);
module:hook('jitsi-lobby-disabled', update_vnodes_for_room);
module:hook('jitsi-filesharing-updated', update_vnodes_for_room);

View File

@@ -23,6 +23,9 @@ local new_id = require 'util.id'.medium;
local json = require 'cjson.safe';
local inspect = require 'inspect';
-- Debug flag
local DEBUG = false;
-- will be initialized once the main virtual host module is initialized
local token_util;
@@ -63,6 +66,17 @@ local visitors_promotion_requests = {};
local cache = require 'util.cache';
local sent_iq_cache = cache.new(200);
-- Function to get visitors room metadata
local function get_visitors_room_metadata(room)
if not room.jitsiMetadata then
room.jitsiMetadata = {};
end
if not room.jitsiMetadata.visitors then
room.jitsiMetadata.visitors = {};
end
return room.jitsiMetadata.visitors;
end
-- Sends a json-message to the destination jid
-- @param to_jid the destination jid
-- @param json_message the message content to send
@@ -73,9 +87,14 @@ function send_json_message(to_jid, json_message)
end
local function request_promotion_received(room, from_jid, from_vnode, nick, time, user_id, group_id, force_promote_requested)
if DEBUG then
module:log('debug', 'Received promotion request from %s for room %s, nick: %s, time: %s, user_id: %s, group_id: %s, force_promote_requested: %s',
from_jid, room.jid, nick, time, user_id, group_id, force_promote_requested);
end
-- if visitors is enabled for the room
if visitors_promotion_map[room.jid] then
local force_promote = auto_allow_promotion;
local force_promote = auto_allow_promotion or get_visitors_room_metadata(room).autoPromote;
if not force_promote and force_promote_requested == 'true' then
-- Let's do the force_promote checks if requested
-- if it is vpaas meeting we trust the moderator computation from visitor node (value of force_promote_requested)
@@ -231,16 +250,6 @@ function get_visitors_languages(room)
return count, languages:sort():concat(',');
end
local function get_visitors_room_metadata(room)
if not room.jitsiMetadata then
room.jitsiMetadata = {};
end
if not room.jitsiMetadata.visitors then
room.jitsiMetadata.visitors = {};
end
return room.jitsiMetadata.visitors;
end
-- listens for iq request for promotion and forward it to moderators in the meeting for approval
-- or auto-allow it if such the config is set enabling it
local function stanza_handler(event)
@@ -250,6 +259,10 @@ local function stanza_handler(event)
return;
end
if DEBUG then
module:log('debug', 'Received stanza %s from %s', stanza, origin.full_jid);
end
if stanza.attr.type == 'result' and sent_iq_cache:get(stanza.attr.id) then
sent_iq_cache:set(stanza.attr.id, nil);
return true;
@@ -367,6 +380,11 @@ local function process_promotion_response(room, id, approved)
return;
end
if DEBUG then
module:log('debug', 'Processing promotion response for room %s, id %s, approved %s',
room.jid, id, approved);
end
-- lets reply to participant that requested promotion
local username = new_id():lower();
visitors_promotion_map[room.jid][username] = {
@@ -400,13 +418,24 @@ end
-- if room metadata does not have visitors.live set to `true` and there are no occupants in the meeting
-- it will skip calling goLive endpoint
local function go_live(room)
if DEBUG then
module:log('debug', 'Checking if room %s is live', room.jid);
end
if room._jitsi_go_live_sent then
if DEBUG then
module:log('debug', 'Room %s already sent go live request, skipping', room.jid);
end
return;
end
-- if missing we assume room is live, only skip if it is marked explicitly as false
if room.jitsiMetadata and room.jitsiMetadata.visitors
and room.jitsiMetadata.visitors.live ~= nil and room.jitsiMetadata.visitors.live == false then
if DEBUG then
module:log('debug', 'Room %s is not live, skipping go live request', room.jid);
end
return;
end
@@ -420,6 +449,9 @@ local function go_live(room)
-- when there is an occupant then go live
if not has_occupant then
if DEBUG then
module:log('debug', 'Room %s has no occupants, skipping go live request', room.jid);
end
return;
end
@@ -461,6 +493,10 @@ process_host_module(muc_domain_prefix..'.'..muc_domain_base, function(host_modul
local room, stanza, occupant, session = event.room, event.stanza, event.occupant, event.origin;
if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) then
if DEBUG then
module:log('debug', 'Skipping visitor checks for healthcheck room %s or admin %s',
room.jid, occupant.bare_jid);
end
return;
end
@@ -472,12 +508,20 @@ process_host_module(muc_domain_prefix..'.'..muc_domain_base, function(host_modul
join:tag('password', { xmlns = MUC_NS }):text(room:get_password());
end
-- we skip any checks when auto-allow is enabled
if auto_allow_promotion
local is_live = get_visitors_room_metadata(room).live;
-- we skip any checks when auto-allow is enabled and room is live
if (auto_allow_promotion or get_visitors_room_metadata(room).autoPromote and (is_live or is_live == nil))
or ignore_list:contains(jid.host(stanza.attr.from)) -- jibri or other domains to ignore
or is_sip_jigasi(stanza)
or is_sip_jibri_join(stanza) then
return;
or is_sip_jibri_join(stanza)
or table_find(room._data.moderators, session.jitsi_meet_context_user and session.jitsi_meet_context_user.id)
or (room._data.moderator_id and room._data.moderator_id == (session.jitsi_meet_context_user and session.jitsi_meet_context_user.id))
or table_find(room._data.participants, session.jitsi_meet_context_user and session.jitsi_meet_context_user.id) then
if DEBUG then
module:log('debug', 'Auto-allowing visitor %s in room %s', stanza.attr.from, room.jid);
end
return;
end
if visitors_promotion_map[room.jid] then
@@ -514,6 +558,16 @@ process_host_module(muc_domain_prefix..'.'..muc_domain_base, function(host_modul
:tag('no-main-participants', { xmlns = 'jitsi:visitors' }));
return true;
end
elseif room._data.participants then
-- This is non jaas room which has a list of participants allowed to participate in the main room
-- but this occupant is not one of them and the room is either not live or has no participants joined
session.log('warn',
'Deny user join in the main not live meeting, not in the list of main participants');
session.send(st.error_reply(
stanza, 'cancel', 'not-allowed',
'Tried to join the main (not live or without main participants) room')
:tag('not-live-room', { xmlns = 'jitsi:visitors' }));
return true;
end
end, 7); -- after muc_meeting_id, the logic for not joining before jicofo
@@ -525,8 +579,16 @@ process_host_module(muc_domain_prefix..'.'..muc_domain_base, function(host_modul
host_module:hook('muc-occupant-joined', function (event)
local room, occupant = event.room, event.occupant;
if DEBUG then
module:log('debug', 'Occupant %s joined room %s', occupant.jid, room.jid);
end
if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) or occupant.role ~= 'moderator' -- luacheck: ignore
or not visitors_promotion_requests[event.room.jid] then
if DEBUG then
module:log('debug', 'Skipping visitor checks for healthcheck room %s or admin %s or not moderator %s',
room.jid, occupant.bare_jid, occupant.role);
end
return;
end

View File

@@ -259,13 +259,10 @@ 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 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)
function is_feature_allowed(ft, 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 is_moderator;
end
@@ -585,7 +582,7 @@ function process_host_module(name, callback)
module:log('info', 'No host/component found, will wait for it: %s', name)
-- when a host or component is added
prosody.events.add_handler('host-activated', process_host);
prosody.events.add_handler('host-activated', process_host, -100); -- make sure everything is loaded
else
process_host(name);
end
@@ -600,7 +597,7 @@ function table_shallow_copy(t)
end
local function table_find(tab, val)
if not tab then
if not tab or val == nil then
return nil
end
@@ -619,6 +616,44 @@ local function table_add(t1, t2)
end
end
-- Returns as a first result the removed items and as a second the added items
local function table_compare(old_table, new_table)
local removed = {}
local added = {}
local modified = {}
-- Find removed items (in old but not in new)
for id, value in pairs(old_table) do
if new_table[id] == nil then
table.insert(removed, id)
elseif new_table[id] ~= value then
table.insert(modified, id)
end
end
-- Find added items (in new but not in old)
for id, _ in pairs(new_table) do
if old_table[id] == nil then
table.insert(added, id)
end
end
return removed, added, modified
end
local function table_equals(t1, t2)
if t1 == nil then
return t2 == nil;
end
if t2 == nil then
return t1 == nil;
end
local removed, added, modified = table_compare(t1, t2);
return next(removed) == nil and next(added) == nil and next(modified) == nil
end
-- Splits a string using delimiter
function split_string(str, delimiter)
str = str .. delimiter;
@@ -666,11 +701,35 @@ local function is_admin(_jid)
return false;
end
-- Filter out identity information (nick name, email, etc) from a presence stanza.
local function filter_identity_from_presence(orig_stanza)
local stanza = st.clone(orig_stanza);
stanza:remove_children('nick', 'http://jabber.org/protocol/nick');
stanza:remove_children('email');
stanza:remove_children('stats-id');
local identity = stanza:get_child('identity');
if identity then
local user = identity:get_child('user');
local name = identity:get_child('name');
if user then
user:remove_children('email');
user:remove_children('name');
end
if name then
name:remove_children('name'); -- Remove name with no namespace
end
end
return stanza;
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;
filter_identity_from_presence = filter_identity_from_presence;
is_admin = is_admin;
is_feature_allowed = is_feature_allowed;
is_jibri = is_jibri;
@@ -700,6 +759,8 @@ return {
starts_with = starts_with;
starts_with_one_of = starts_with_one_of;
table_add = table_add;
table_compare = table_compare;
table_shallow_copy = table_shallow_copy;
table_find = table_find;
table_equals = table_equals;
};

View File

@@ -3,9 +3,9 @@
jitsi_root_dir: /opt/jitsi
jitsi_user: jitsi
jitsi_videobridge_version: "{{ jitsi_version | default('10314') }}"
jitsi_videobridge_version: "{{ jitsi_version | default('10431') }}"
jitsi_videobridge_archive_url: https://github.com/jitsi/jitsi-videobridge/archive/refs/tags/stable/jitsi-meet_{{ jitsi_videobridge_version }}.tar.gz
jitsi_videobridge_archive_sha256: 55ffb62de63c7280b4e2a6c25045da9c6f3e07c20f28d1b697510231ae56f8bf
jitsi_videobridge_archive_sha256: 57d29c7d24c5f0657efbadabd54d3efa34c587a05c7a2196dca5e3c56141b44a
jitsi_videobridge_rtp_port: 10000
jitsi_videobridge_src_ip:

View File

@@ -31,6 +31,8 @@ metabase_db_server: "{{ (metabase_db_engine == 'mysql') | ternary(mysql_server,
metabase_db_port: "{{ (metabase_db_engine == 'mysql') | ternary('3306', '5432') }}"
metabase_db_name: metabase
metabase_db_user: metabase
# Should ansible try to create user and db on the server. If false, the user and the database must already exist
metabase_db_create: true
# A random pass will be generated and stored in the meta dir if not defined
# metabase_db_pass: S3cr3t.

View File

@@ -92,10 +92,14 @@
- db_user: "{{ metabase_db_user }}"
- db_server: "{{ metabase_db_server }}"
- db_pass: "{{ metabase_db_pass }}"
when: metabase_db_engine == 'mysql'
when:
- metabase_db_engine == 'mysql'
- metabase_db_create
tags: metabase
- when: metabase_db_engine == 'postgres'
- when:
- metabase_db_engine == 'postgres'
- metabase_db_create
block:
- name: Install postgresql client
package: name=postgresql16

View File

@@ -34,4 +34,4 @@
- name: Create vector config dir
file: path=/etc/vector/conf.d state=directory
tags: log,mkdir
tags: log,mkdir,vector

View File

@@ -18,5 +18,6 @@ transforms:
} else if (.file == "/var/log/nginx/error.log"){
.http = parse_nginx_log!(.message, format:"error")
}
.timestamp = parse_timestamp(del(.http.timestamp), format: "%d/%h/%Y:%H:%M:%S %z") ?? now()
.service = "nginx"
.group = "web"

View File

@@ -5,9 +5,6 @@ nomad_plugins:
podman:
archive_url: https://releases.hashicorp.com/nomad-driver-podman/0.6.3/nomad-driver-podman_0.6.3_linux_amd64.zip
sha256: 56b85d844385b4b5b96936fe6af06d623e87b5939f26de9fbad963f72af1e4a1
containerd:
archive_url: https://github.com/Roblox/nomad-driver-containerd/releases/download/v0.9.4/containerd-driver
sha256: 337e1bab178071500bfbe46a59946e0e3bafc652906ed1b755d2aa4d35990982
exec2:
archive_url: https://releases.hashicorp.com/nomad-driver-exec2/0.1.0/nomad-driver-exec2_0.1.0_linux_amd64.zip
sha256: 13edd022ac793f3ca8cbd413015a13d7d396141d11234faaf72bdf34b08cae50

View File

@@ -1,9 +1,9 @@
---
# Version of Nomad to install
nomad_version: 1.10.2
nomad_version: 1.10.3
# URL of the archive
nomad_archive_url: https://releases.hashicorp.com/nomad/{{ nomad_version }}/nomad_{{ nomad_version }}_linux_amd64.zip
# Expected sha256 of the archive
nomad_archive_sha256: f6aa335261637574c00ce39519ab1fede41493d369b2a0eb17052dba830ff8df
nomad_archive_sha256: a161b8d59b42555d97d37f7a75c122831be485e89dfb97d16d6b60cfaec8d88b

View File

@@ -7,6 +7,7 @@ sources:
- /var/log/pve-firewall.log
- /var/log/pveproxy/access.log
- /var/log/vzdump/*
- /var/log/ceph/*.log
transforms:
format_logs_pve:

View File

@@ -1,3 +1,3 @@
---
nodejs_major_version: 18
nodejs_major_version: 22

View File

@@ -1,7 +1,7 @@
[nodejs]
baseurl = https://rpm.nodesource.com/pub_{{ nodejs_major_version }}.x/el/{{ ansible_distribution_major_version }}/$basearch
baseurl = https://rpm.nodesource.com/pub_{{ nodejs_major_version }}.x/nodistro/nodejs/$basearch
gpgcheck = 1
gpgkey = https://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL
gpgkey = https://rpm.nodesource.com/gpgkey/ns-operations-public.key
name = Node.js Packages for Enterprise Linux
{% if ansible_os_family == 'RedHat' and ansible_distribution_major_version is version('8', '>=') %}
# Workaround a bug in dnf which would make the default module mask

View File

@@ -17,4 +17,5 @@ transforms:
.message = string!(.message)
if (is_json(.message)) {
.samba = parse_json!(.message)
.timestamp = parse_timestamp(del(.samba.timestamp), format: "%FT%H:%M:%S%.f%z") ?? now()
}

View File

@@ -6,6 +6,7 @@ download.dokuwiki.org
raw.githubusercontent.com
objects.githubusercontent.com
github-releases.githubusercontent.com
release-assets.githubusercontent.com
packagecloud.io
.cloudfront.net
packagist.org

View File

@@ -14,9 +14,12 @@ transforms:
type: remap
inputs: ["in_logs_squid"]
source: |
.group = "proxy"
if (.file == "/var/log/squid/access.log"){
.squid = parse_grok!(
.message,
"%{HTTPDATE:timestamp}\\s+%{NUMBER:response_time} %{IPORHOST:src_ip} %{NOTSPACE:squid_request_status}/%{NUMBER:http_status_code} %{NUMBER:transfer_size} %{NOTSPACE:http_method} (%{URIPROTO:url_scheme}://)?(?<url_host>\\S+?)(:%{INT:url_port})?(/%{NOTSPACE:url_path})?\\s+%{NOTSPACE:client_identity}\\s+%{NOTSPACE:peer_code}/%{NOTSPACE:peerhost}\\s+%{NOTSPACE:content_type}"
)
.timestamp = parse_timestamp(del(.squid.timestamp), format: "%d/%h/%Y:%H:%M:%S %z") ?? now()
.service = "squid"
}

View File

@@ -25,3 +25,5 @@
- include_tasks: cleanup.yml
tags: always
- include_tasks: vector.yml
tags: always

View File

@@ -0,0 +1,5 @@
---
- name: Deploy vector configuration
template: src=vector.yml dest=/etc/vector/conf.d/vault.yml
tags: log,vault,vector

View File

@@ -0,0 +1,18 @@
---
sources:
in_logs_vault:
type: file
include:
- /opt/vault/log/audit.json
transforms:
format_logs_vault:
type: remap
inputs: ["in_logs_vault"]
source: |
.message = string!(.message)
if (is_json(.message)) {
.vault = parse_json!(.message)
.timestamp = parse_timestamp(del(.vault.time), format: "%FT%H:%M:%S%.fZ", timezone: "UTC") ?? now()
}

View File

@@ -1,7 +1,7 @@
# Version of Vault to install
vault_version: 1.20.0
vault_version: 1.20.1
# URL of the archive
vault_archive_url: https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_amd64.zip
# Expected sha256 of the archive
vault_archive_sha256: 25e9f1f9a6dd9866219d6a37c6d1af1d26d0e73aa95a4e755188751de133dea7
vault_archive_sha256: e3ce3e678421c0d56f726952ab100875168c2e1eb1db751ed5a2b25b6b2ea96f

View File

@@ -15,12 +15,6 @@ vector_base_conf:
dummy: exists(.dummy) && .dummy == "true"
iptables: exists(._TRANSPORT) && ._TRANSPORT == "kernel" && starts_with(string!(.message), "Firewall:")
parse_journald_dummy:
type: remap
inputs: ["route_journald.dummy"]
source: |
# Nothing to do
parse_journald_iptables:
type: remap
inputs: ["route_journald.iptables"]
@@ -37,7 +31,7 @@ vector_base_conf:
logs_out:
type: remap
inputs: ['format_logs_*', 'route_*._unmatched']
inputs: ['format_logs_*']
source: |
# Nothing to do
@@ -45,7 +39,7 @@ vector_base_conf:
sink_blackhole:
type: blackhole
inputs:
- format_logs_out
- logs_out
vector_extra_conf: {}
vector_host_conf: {}