mirror of
https://git.lapiole.org/dani/ansible-roles.git
synced 2025-08-02 23:05:41 +02:00
246 lines
8.5 KiB
Lua
246 lines
8.5 KiB
Lua
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);
|