mod_muc_occupant_id/mod_muc_occupant_id.lua
changeset 3838 2f189f022b84
parent 3835 435f5b4ebd06
child 3839 5258f0afa8b4
equal deleted inserted replaced
3837:580862decd77 3838:2f189f022b84
    11 local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
    11 local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
    12 
    12 
    13 local function generate_id(occupant, room)
    13 local function generate_id(occupant, room)
    14 	local bare = occupant.bare_jid;
    14 	local bare = occupant.bare_jid;
    15 
    15 
    16 	-- TODO: Move the salt on the MUC component. Setting the salt on the room
       
    17 	-- can be problematic when the room is destroyed. Next time it's recreated
       
    18 	-- the salt will be different and so will be the unique_id. Or maybe we want
       
    19 	-- this anyway?
       
    20 	if room._data.occupant_id_salt == nil then
    16 	if room._data.occupant_id_salt == nil then
    21 		local salt = uuid.generate();
    17 		room._data.occupant_id_salt = uuid.generate();
    22 		room._data.occupant_id_salt = salt;
       
    23 	end
    18 	end
    24 
    19 
    25 	return b64encode(hmac_sha256(bare, room._data.occupant_id_salt));
    20 	if room._data.occupant_ids == nil then
       
    21 		room._data.occupant_ids = {};
       
    22 	end
       
    23 
       
    24 	if room._data.occupant_ids[bare] == nil then
       
    25 		local unique_id = b64encode(hmac_sha256(bare, room._data.occupant_id_salt));
       
    26 		room._data.occupant_ids[bare] = unique_id;
       
    27 	end
       
    28 
       
    29 	return room._data.occupant_ids[bare];
    26 end
    30 end
    27 
    31 
    28 local function edit_occupant(event)
    32 local function update_occupant(event)
    29 	local unique_id = generate_id(event.occupant, event.room);
       
    30 
       
    31 	-- TODO: Store this only once per bare jid and not once per occupant?
       
    32 	local stanza = event.stanza;
       
    33 	stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
       
    34 		:text(unique_id)
       
    35 		:up();
       
    36 end
       
    37 
       
    38 local function handle_stanza(event)
       
    39 	local stanza, occupant, room = event.stanza, event.occupant, event.room;
    33 	local stanza, occupant, room = event.stanza, event.occupant, event.room;
    40 
    34 
    41 	-- strip any existing <occupant-id/> tags to avoid forgery
    35 	-- strip any existing <occupant-id/> tags to avoid forgery
    42 	stanza:remove_children("occupant-id", xmlns_occupant_id);
    36 	stanza:remove_children("occupant-id", xmlns_occupant_id);
    43 
    37 
    44 	local occupant_tag = occupant.sessions[stanza.attr.from]
    38 	local unique_id = generate_id(occupant, room);
    45 		:get_child("occupant-id", xmlns_occupant_id);
       
    46 
       
    47 	local unique_id;
       
    48 	if occupant_tag == nil then
       
    49 		unique_id = generate_id(occupant, room);
       
    50 	else
       
    51 		unique_id = occupant.sessions[stanza.attr.from]
       
    52 			:get_child("occupant-id", xmlns_occupant_id)
       
    53 			:get_text();
       
    54 	end
       
    55 
       
    56 	stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
    39 	stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
    57 		:text(unique_id)
    40 		:text(unique_id)
    58 		:up();
    41 		:up();
    59 end
    42 end
    60 
    43 
    61 module:add_feature(xmlns_occupant_id);
    44 module:add_feature(xmlns_occupant_id);
    62 module:hook("muc-disco#info", function (event)
    45 module:hook("muc-disco#info", function (event)
    63 	event.reply:tag("feature", { var = xmlns_occupant_id }):up();
    46 	event.reply:tag("feature", { var = xmlns_occupant_id }):up();
    64 end);
    47 end);
    65 
    48 
    66 module:hook("muc-occupant-pre-join", edit_occupant);
    49 module:hook("muc-occupant-pre-join", update_occupant);
    67 module:hook("muc-occupant-groupchat", handle_stanza);
    50 module:hook("muc-occupant-groupchat", update_occupant);