Compare commits

...

3 Commits

Author SHA1 Message Date
damencho
0cfed44976 feat: Adds event to allow joining a visitor enabled room.
Fire event and if other modules return true this will allow joining, otherwise the standard path is used.
2024-04-19 07:57:37 -05:00
damencho
9c11d87198 feat: Extract flip check in a function. 2024-04-19 07:57:34 -05:00
damencho
bf202f828d feat: Drop some commented code and small simplification. 2024-04-19 06:20:41 -05:00
2 changed files with 85 additions and 59 deletions

View File

@@ -1,6 +1,7 @@
-- Allows flipping device. When a presence contains flip_device tag
-- and the used jwt matches the id(session.jitsi_meet_context_user.id) of another user this is indication that the user
-- and the used jwt matches the id(session.jitsi_meet_context_user.id) of another user - this is indication that the user
-- is moving from one device to another. The flip feature should be present and enabled in the token features.
-- Should be enabled under the main muc component
-- Copyright (C) 2023-present 8x8, Inc.
local oss_util = module:require "util";
@@ -28,7 +29,6 @@ end
local function remove_flip_tag(stanza)
stanza:maptags(function(tag)
if tag and tag.name == "flip_device" then
-- module:log("debug", "Removing %s tag from presence stanza!", tag.name);
return nil;
else
return tag;
@@ -40,71 +40,96 @@ end
-- A user is considered to join from another device if the
-- id from jwt is the same as another occupant and the presence
-- stanza has flip_device tag
module:hook("muc-occupant-pre-join", function(event)
local room, occupant = event.room, event.occupant;
local session = event.origin;
local stanza = event.stanza;
if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) then
return ;
local function process_checks_flip(room, occupant, session, stanza)
if is_healthcheck_room(room.jid) or is_admin(occupant.bare_jid) or stanza._flip_processed then
return;
end
local flip_device_tag = stanza:get_child("flip_device");
if not flip_device_tag then
return;
end
if session.jitsi_meet_context_user and session.jitsi_meet_context_user.id then
local participants = room._data.participants_details or {};
local id = session.jitsi_meet_context_user.id;
local first_device_occ_nick = participants[id];
if flip_device_tag then
if first_device_occ_nick and session.jitsi_meet_context_features.flip and (session.jitsi_meet_context_features.flip == true or session.jitsi_meet_context_features.flip == "true") then
room._data.kicked_participant_nick = first_device_occ_nick;
room._data.flip_participant_nick = occupant.nick;
-- allow participant from flip device to bypass Lobby
local occupant_jid = stanza.attr.from;
local affiliation = room:get_affiliation(occupant_jid);
if not affiliation or affiliation == 'none' or affiliation == 'member' then
-- module:log("debug", "Bypass lobby invitee %s", occupant_jid)
occupant.role = "participant";
room:set_affiliation(true, jid_bare(occupant_jid), "member")
room:save_occupant(occupant);
end
-- bypass password on the flip device
local join = stanza:get_child("x", MUC_NS);
if not join then
join = stanza:tag("x", { xmlns = MUC_NS });
end
local password = join:get_child("password", MUC_NS);
if password then
join:maptags(
function(tag)
for k, v in pairs(tag) do
if k == "name" and v == "password" then
return nil
end
end
return tag
end);
end
join:tag("password", { xmlns = MUC_NS }):text(room:get_password());
elseif not session.jitsi_meet_context_features.flip or session.jitsi_meet_context_features.flip == false or session.jitsi_meet_context_features.flip == "false" then
module:log("warn", "Flip device tag present without jwt permission")
--remove flip_device tag if somebody wants to abuse this feature
remove_flip_tag(stanza)
else
module:log("warn", "Flip device tag present without user from different device")
--remove flip_device tag if somebody wants to abuse this feature
remove_flip_tag(stanza)
local is_feature_flip_allowed = session.jitsi_meet_context_features
and (session.jitsi_meet_context_features.flip == true
or session.jitsi_meet_context_features.flip == "true");
if first_device_occ_nick and is_feature_flip_allowed then
room._data.kicked_participant_nick = first_device_occ_nick;
room._data.flip_participant_nick = occupant.nick;
-- allow participant from flip device to bypass Lobby
local occupant_jid = stanza.attr.from;
local affiliation = room:get_affiliation(occupant_jid);
if not affiliation or affiliation == 'none' or affiliation == 'member' then
occupant.role = "participant";
room:set_affiliation(true, jid_bare(occupant_jid), "member")
room:save_occupant(occupant);
end
end
-- update authenticated participant list
participants[id] = occupant.nick;
room._data.participants_details = participants
-- module:log("debug", "current details list %s", inspect(participants))
else
if flip_device_tag then
module:log("warn", "Flip device tag present for a guest user")
-- remove flip_device tag because a guest want to do a sneaky join
-- bypass password on the flip device
local join = stanza:get_child("x", MUC_NS);
if not join then
join = stanza:tag("x", { xmlns = MUC_NS });
end
local password = join:get_child("password", MUC_NS);
if password then
join:maptags(
function(tag)
for k, v in pairs(tag) do
if k == "name" and v == "password" then
return nil
end
end
return tag
end);
end
join:tag("password", { xmlns = MUC_NS }):text(room:get_password());
-- avoid processing it twice, muc-occupant-pre-join in visitors may fire jitsi-visitors-allow-join
-- and if it passes it through, this module will execute same check for the pre-join event
stanza._flip_processed = true;
return true;
elseif not is_feature_flip_allowed then
module:log("warn", "Flip device tag present without jwt permission")
--remove flip_device tag if somebody wants to abuse this feature
remove_flip_tag(stanza)
else
module:log("warn", "Flip device tag present without user from different device")
--remove flip_device tag if somebody wants to abuse this feature
remove_flip_tag(stanza)
end
else
module:log("warn", "Flip device tag present for a guest user")
-- remove flip_device tag because a guest want to do a sneaky join
remove_flip_tag(stanza)
end
end)
end
module:hook("muc-occupant-pre-join", function(event)
local room, occupant = event.room, event.occupant;
local session = event.origin;
local stanza = event.stanza;
process_checks_flip(room, occupant, session, stanza);
if session.jitsi_meet_context_user and session.jitsi_meet_context_user.id then
local id = session.jitsi_meet_context_user.id;
local participants = room._data.participants_details or {};
-- update authenticated participant list
participants[id] = occupant.nick;
room._data.participants_details = participants;
end
end);
module:hook('jitsi-visitors-allow-join', function(e)
local room, stanza, occupant, session = e.room, e.stanza, e.occupant, e.session;
return process_checks_flip(room, occupant, session, stanza);
end);
-- Kick participant from the the first device from the main room and lobby if applies
-- and transfer role from the previous participant, this will take care of the grant
@@ -126,7 +151,6 @@ module:hook("muc-occupant-joined", function(event)
end
local initial_affiliation = room:get_affiliation(kicked_occupant.jid) or "member";
-- module:log("debug", "Transfer affiliation %s to occupant jid %s", initial_affiliation, occupant.jid)
room:set_affiliation(true, occupant.bare_jid, initial_affiliation)
if initial_affiliation == "owner" then
event.occupant.role = "moderator";

View File

@@ -336,7 +336,9 @@ process_host_module(muc_domain_prefix..'.'..muc_domain_base, function(host_modul
if visitors_promotion_map[room.jid] then
-- now let's check for jid
if visitors_promotion_map[room.jid][jid.node(stanza.attr.from)] -- promotion was approved
or ignore_list:contains(jid.host(stanza.attr.from)) then -- jibri or other domains to ignore
or ignore_list:contains(jid.host(stanza.attr.from)) -- jibri or other domains to ignore
or host_module:fire_event('jitsi-visitors-allow-join',
{ room = room; stanza = stanza; occupant = occupant; session = origin; }) then
-- allow join
return;
end