mirror of
https://git.lapiole.org/dani/ansible-roles.git
synced 2025-08-03 15:16:58 +02:00
Update to 2025-06-16 16:00
This commit is contained in:
201
roles/jitsi/files/prosody/modules/mod_jitsi_permissions.lua
Normal file
201
roles/jitsi/files/prosody/modules/mod_jitsi_permissions.lua
Normal file
@@ -0,0 +1,201 @@
|
||||
-- this is auto loaded by meeting_id
|
||||
local filters = require 'util.filters';
|
||||
local jid = require 'util.jid';
|
||||
|
||||
local util = module:require 'util';
|
||||
local is_admin = util.is_admin;
|
||||
local get_room_from_jid = util.get_room_from_jid;
|
||||
local is_healthcheck_room = util.is_healthcheck_room;
|
||||
local room_jid_match_rewrite = util.room_jid_match_rewrite;
|
||||
local ends_with = util.ends_with;
|
||||
local presence_check_status = util.presence_check_status;
|
||||
|
||||
local MUC_NS = 'http://jabber.org/protocol/muc';
|
||||
|
||||
local muc_domain_prefix = module:get_option_string('muc_mapper_domain_prefix', 'conference');
|
||||
|
||||
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.');
|
||||
return ;
|
||||
end
|
||||
|
||||
-- only the visitor prosody has main_domain setting
|
||||
local is_visitor_prosody = module:get_option_string('main_domain') ~= nil;
|
||||
|
||||
-- load it only on the main muc component as it is loaded by muc_meeting_id which is loaded and for the breakout room muc
|
||||
if muc_domain_prefix..'.'..muc_domain_base ~= module.host or is_visitor_prosody then
|
||||
return;
|
||||
end
|
||||
|
||||
local sessions = prosody.full_sessions;
|
||||
local default_permissions;
|
||||
|
||||
local function load_config()
|
||||
default_permissions = module:get_option('jitsi_default_permissions', {
|
||||
livestreaming = true;
|
||||
recording = true;
|
||||
transcription = true;
|
||||
['outbound-call'] = true;
|
||||
['create-polls'] = true;
|
||||
['send-groupchat'] = true;
|
||||
flip = true;
|
||||
});
|
||||
end
|
||||
load_config();
|
||||
|
||||
function process_set_affiliation(event)
|
||||
local actor, affiliation, jid, previous_affiliation, room
|
||||
= event.actor, event.affiliation, event.jid, event.previous_affiliation, event.room;
|
||||
local actor_session = sessions[actor];
|
||||
|
||||
if is_admin(jid) or is_healthcheck_room(room.jid) or not actor or not previous_affiliation
|
||||
or not actor_session or not actor_session.jitsi_meet_context_features then
|
||||
return;
|
||||
end
|
||||
|
||||
local occupant;
|
||||
for _, o in room:each_occupant() do
|
||||
if o.bare_jid == jid then
|
||||
occupant = o;
|
||||
end
|
||||
end
|
||||
|
||||
if not occupant then
|
||||
return;
|
||||
end
|
||||
|
||||
local occupant_session = sessions[occupant.jid];
|
||||
if not occupant_session then
|
||||
return;
|
||||
end
|
||||
|
||||
if previous_affiliation == 'none' and affiliation == 'owner' then
|
||||
occupant_session.granted_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;
|
||||
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;
|
||||
|
||||
-- on revoke
|
||||
if not session.auth_token then
|
||||
occupant_session.jitsi_meet_context_features = nil;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Detects when sending self-presence because of role change
|
||||
-- we can end up here because of the following cases:
|
||||
-- 1. user joins the room and is granted moderator by another moderator or jicofo
|
||||
-- 2. Some module changes the role of the user by using set_affiliation method
|
||||
-- In cases where authentication is 'anonymous', 'jitsi-anonymous', 'internal_hashed', 'internal_plain', 'cyrus' we
|
||||
-- want to send default permissions all to indicate UI that everything is allowed (to not relay on the UI to check
|
||||
-- is participant moderator or not), to allow finer control over the permissions.
|
||||
-- In case the authentication is 'token' based we want to send permissions only if the token of the user does not include
|
||||
-- features in the user.context.
|
||||
-- In case of allowners we want to send the permissions, no matter of the authentication method.
|
||||
-- In case permissions were granted we want to send the granted permissions in all cases except when the user is
|
||||
-- using token that has features pre-defined (authentication is 'token').
|
||||
function filter_stanza(stanza, session)
|
||||
if not stanza.attr or not stanza.attr.to or stanza.name ~= 'presence'
|
||||
or stanza.attr.type == 'unavailable' or ends_with(stanza.attr.from, '/focus') then
|
||||
return stanza;
|
||||
end
|
||||
|
||||
local bare_to = jid.bare(stanza.attr.to);
|
||||
if is_admin(bare_to) then
|
||||
return stanza;
|
||||
end
|
||||
|
||||
local muc_x = stanza:get_child('x', MUC_NS..'#user');
|
||||
if not muc_x or not presence_check_status(muc_x, '110') then
|
||||
return stanza;
|
||||
end
|
||||
|
||||
local room = get_room_from_jid(room_jid_match_rewrite(jid.bare(stanza.attr.from)));
|
||||
|
||||
if not room or is_healthcheck_room(room.jid) then
|
||||
return stanza;
|
||||
end
|
||||
|
||||
if not room.send_default_permissions_to then
|
||||
room.send_default_permissions_to = {};
|
||||
end
|
||||
|
||||
if not session.force_permissions_update then
|
||||
if session.auth_token and session.jitsi_meet_context_features then -- token and features are set so skip
|
||||
room.send_default_permissions_to[bare_to] = nil;
|
||||
return stanza;
|
||||
end
|
||||
|
||||
-- we are sending permissions only when becoming a member
|
||||
local is_moderator = false;
|
||||
for item in muc_x:childtags('item') do
|
||||
if item.attr.role == 'moderator' then
|
||||
is_moderator = true;
|
||||
break;
|
||||
end
|
||||
end
|
||||
|
||||
if not is_moderator then
|
||||
return stanza;
|
||||
end
|
||||
|
||||
if not room.send_default_permissions_to[bare_to] then
|
||||
return stanza;
|
||||
end
|
||||
end
|
||||
|
||||
session.force_permissions_update = false;
|
||||
|
||||
local permissions_to_send
|
||||
= session.jitsi_meet_context_features or session.granted_jitsi_meet_context_features or default_permissions;
|
||||
|
||||
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
|
||||
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();
|
||||
|
||||
return stanza;
|
||||
end
|
||||
|
||||
-- we need to indicate that we will send permissions if we need to
|
||||
-- we need to handle granted features and stuff in the pre-set hook so they are unavailable
|
||||
-- when the self presence is set, so we can update the client, the checks
|
||||
-- whether the actor is allowed to set the affiliation are done before pre-set hook is fired
|
||||
module:hook('muc-pre-set-affiliation', function(event)
|
||||
local jid, room = event.jid, event.room;
|
||||
|
||||
if not room.send_default_permissions_to then
|
||||
room.send_default_permissions_to = {};
|
||||
end
|
||||
room.send_default_permissions_to[jid] = true;
|
||||
|
||||
process_set_affiliation(event);
|
||||
end);
|
||||
|
||||
function filter_session(session)
|
||||
-- domain mapper is filtering on default priority 0
|
||||
-- allowners is -1 and we need it after that
|
||||
filters.add_filter(session, 'stanzas/out', filter_stanza, -2);
|
||||
end
|
||||
|
||||
-- enable filtering presences
|
||||
filters.add_filter_hook(filter_session);
|
Reference in New Issue
Block a user