Comparison

mod_muc_occupant_id/mod_muc_occupant_id.lua @ 3629:cfe0907808e1

mod_muc_occupant_id: initial commit Implementation of XEP-XXXX: Anonymous unique occupant identifiers for MUCs. https://dino.im/xeps/occupant-id.html
author Maxime “pep” Buquet <pep@bouah.net>
date Sun, 14 Jul 2019 18:45:10 +0200
child 3630:c05e157d987c
comparison
equal deleted inserted replaced
3628:2444fb3b05b7 3629:cfe0907808e1
1
2 -- Implementation of https://dino.im/xeps/occupant-id.html
3 -- XEP-XXXX: Anonymous unique occupant identifiers for MUCs
4
5 local uuid = require "util.uuid";
6 local hmac_sha256 = require "util.hashes".hmac_sha256;
7 local b64encode = require "util.encodings".base64.encode;
8
9 local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
10
11 local function edit_occupant(event)
12 local occupant, room = event.occupant, event.room;
13 local bare = occupant.bare_jid;
14
15 -- TODO: Move the salt on the MUC component. Setting the salt on the room
16 -- can be problematic when the room is destroyed. Next time it's recreated
17 -- the salt will be different and so will be the unique_id. Or maybe we want
18 -- this anyway?
19 if room._data.occupant_id_salt == nil then
20 local salt = uuid.generate();
21 room._data.occupant_id_salt = salt;
22 end
23
24 local unique_id = b64encode(hmac_sha256(bare, room._data.occupant_id_salt));
25
26 -- TODO: Store this only once per bare jid and not once per occupant?
27 local stanza = event.stanza;
28 stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
29 :text(unique_id)
30 :up();
31 end
32
33 local function handle_stanza(event)
34 local stanza, occupant = event.stanza, event.occupant;
35
36 if stanza.name == "presence" and stanza.attr.type == "unavailable" then -- not required here
37 return;
38 end
39
40 -- strip any existing <occupant-id/> tags to avoid forgery
41 stanza:remove_children("occupant-id", xmlns_occupant_id);
42
43 if not occupant then return; end
44
45 local unique_id = occupant.sessions[stanza.attr.from]
46 :get_child("occupant-id", xmlns_occupant_id)
47 :get_text();
48 stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
49 :text(unique_id)
50 :up();
51 end
52
53 module:add_feature(xmlns_occupant_id);
54 module:hook("muc-disco#info", function (event)
55 event.reply:tag("feature", { var = xmlns_occupant_id }):up();
56 end);
57
58 module:hook("muc-occupant-pre-join", edit_occupant);
59 module:hook("muc-occupant-groupchat", handle_stanza);