Mercurial > prosody-modules
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 |
parents | |
children | 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); |