Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(visitors): Propagate moderator role to visitor nodes. #15363

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions resources/prosody-plugins/mod_fmuc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ local jid = require 'util.jid';
local st = require 'util.stanza';
local new_id = require 'util.id'.medium;
local filters = require 'util.filters';
local array = require"util.array";
local array = require 'util.array';
local set = require 'util.set';

local util = module:require 'util';
local ends_with = util.ends_with;
Expand Down Expand Up @@ -69,13 +70,11 @@ end

local function send_transcriptions_update(room)
-- let's notify main prosody
local lang_array = array{};
local lang_array = array();
local count = 0;

for k, v in pairs(room._transcription_languages) do
if not lang_array[v] then
lang_array:push(v);
end
lang_array:push(v);
count = count + 1;
end

Expand All @@ -90,7 +89,7 @@ local function send_transcriptions_update(room)
room = jid.join(jid.node(room.jid), muc_domain_prefix..'.'..main_domain) })
:tag('transcription-languages', {
xmlns = 'jitsi:visitors',
langs = lang_array:sort():concat(','),
langs = lang_array:unique():sort():concat(','),
count = tostring(count)
}):up());
end
Expand Down Expand Up @@ -127,15 +126,24 @@ end
module:hook('muc-occupant-pre-join', function (event)
local occupant, room, origin, stanza = event.occupant, event.room, event.origin, event.stanza;
local node, host = jid.split(occupant.bare_jid);
local resource = jid.resource(occupant.nick);

if is_admin(occupant.bare_jid) then
return;
end

if prosody.hosts[host] and not is_admin(occupant.bare_jid) then
if prosody.hosts[host] then
-- local participants which host is defined in this prosody
if room._main_room_lobby_enabled then
origin.send(st.error_reply(stanza, 'cancel', 'not-allowed', 'Visitors not allowed while lobby is on!')
:tag('no-visitors-lobby', { xmlns = 'jitsi:visitors' }));
return true;
else
occupant.role = 'visitor';
end
elseif room.moderators_list:contains(resource) then
-- remote participants, host is the main prosody
occupant.role = 'moderator';
end
end, 3);

Expand Down Expand Up @@ -399,7 +407,7 @@ local function stanza_handler(event)
local room = get_room_from_jid(room_jid_match_rewrite(room_jid));

if not room then
module:log('warn', 'No room found %s', room_jid);
module:log('warn', 'No room found %s in stanza_handler', room_jid);
return;
end

Expand Down Expand Up @@ -546,7 +554,15 @@ module:hook('jicofo-unlock-room', function(e)
return true;
end);

-- handles incoming iq connect stanzas
-- handles incoming iq visitors stanzas
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding detailed docs is always a great call.

◽ Compliment

Image of Ryan Lester <@buu700> Ryan Lester <@buu700>

-- connect - sent after sending all main participant's presences
-- disconnect - sent when main room is destroyed or when we receive a 'disconnect-vnode' iq from jicofo
-- update - sent on:
-- * room secret is changed
-- * lobby enabled or disabled
-- * initially before connect to report currently joined moderators
-- * moderator participant joins main room
-- * a participant has been granted moderator rights
local function iq_from_main_handler(event)
local origin, stanza = event.origin, event.stanza;

Expand Down Expand Up @@ -577,7 +593,7 @@ local function iq_from_main_handler(event)
local room = get_room_from_jid(room_jid_match_rewrite(room_jid));

if not room then
module:log('warn', 'No room found %s', room_jid);
module:log('warn', 'No room found %s in iq_from_main_handler for:%s', room_jid, visitors_iq);
return;
end

Expand Down Expand Up @@ -625,6 +641,28 @@ local function iq_from_main_handler(event)
room._main_room_lobby_enabled = false;
end

-- read the moderators list
room.moderators_list = room.moderators_list or set.new();
local moderators = node:get_child('moderators');

if moderators then
for _, child in ipairs(moderators.tags) do
if child.name == 'item' then
room.moderators_list:add(child.attr.epId);
end
end

-- let's check current occupants roles and promote them if needed
-- we change only main participants which are not moderators, but participant
for _, o in room:each_occupant() do
if not is_admin(o.bare_jid)
and o.role == 'participant'
and room.moderators_list:contains(jid.resource(o.nick)) then
room:set_affiliation(true, o.bare_jid, 'owner');
end
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; });
Expand Down
42 changes: 39 additions & 3 deletions resources/prosody-plugins/mod_visitors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ local function send_visitors_iq(conference_service, room, type)
-- send iq informing the vnode that the connect is done and it will allow visitors to join
local iq_id = new_id();
sent_iq_cache:set(iq_id, socket.gettime());
local connect_done = st.iq({
local visitors_iq = st.iq({
type = 'set',
to = conference_service,
from = module.host,
Expand All @@ -71,9 +71,23 @@ local function send_visitors_iq(conference_service, room, type)
meetingId = room._data.meetingId,
moderatorId = room._data.moderator_id, -- can be used from external modules to set single moderator for meetings
createdTimestamp = room.created_timestamp and tostring(room.created_timestamp) or nil
}):up();
});

module:send(connect_done);
if type == 'update' then
visitors_iq:tag('moderators', { xmlns = 'jitsi:visitors' });

for _, o in room:each_occupant() do
if not is_admin(o.bare_jid) and o.role == 'moderator' then
visitors_iq:tag('item', { epId = jid.resource(o.nick) }):up();
end
end

visitors_iq:up();
end

visitors_iq:up();

module:send(visitors_iq);
end

-- an event received from visitors component, which receives iqs from jicofo
Expand All @@ -97,6 +111,9 @@ local function connect_vnode(event)

local sent_main_participants = 0;

-- send update initially so we can report the moderators that will join
send_visitors_iq(conference_service, room, 'update');

for _, o in room:each_occupant() do
if not is_admin(o.bare_jid) then
local fmuc_pr = st.clone(o:get_presence());
Expand Down Expand Up @@ -258,6 +275,10 @@ process_host_module(main_muc_component_config, function(host_module, host)
local user, _, res = jid.split(occupant.nick);
-- a main participant we need to update all active visitor nodes
for k in pairs(vnodes) do
if occupant.role == 'moderator' then
-- first send that the participant is a moderator
send_visitors_iq(k, room, 'update');
end
local fmuc_pr = st.clone(stanza);
fmuc_pr.attr.to = jid.join(user, k, res);
fmuc_pr.attr.from = occupant.jid;
Expand Down Expand Up @@ -332,6 +353,21 @@ process_host_module(main_muc_component_config, function(host_module, host)
end
end
end, -100); -- we want to run last in order to check is the status code 104

host_module:hook('muc-set-affiliation', function (event)
if event.actor and not is_admin(event.actor) and event.affiliation == 'owner' then
local room = event.room;

if not visitors_nodes[room.jid] then
return;
end
-- 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, -2);
end);

module:hook('jitsi-lobby-enabled', function(event)
Expand Down
Loading