# HG changeset patch # User Maxime “pep” Buquet # Date 1563122710 -7200 # Node ID cfe0907808e13f2a1945ba2539e95b3ad9fe8de5 # Parent 2444fb3b05b72a1b645dd542150e3947c44cb610 mod_muc_occupant_id: initial commit Implementation of XEP-XXXX: Anonymous unique occupant identifiers for MUCs. https://dino.im/xeps/occupant-id.html diff -r 2444fb3b05b7 -r cfe0907808e1 mod_muc_occupant_id/README.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_occupant_id/README.markdown Sun Jul 14 18:45:10 2019 +0200 @@ -0,0 +1,19 @@ +--- +labels: +- 'Stage-Alpha' +summary: 'Anonymous unique occupant identifiers for MUCs' +... + +Introduction +============ + +This module implements [XEP-XXXX: Anonymous unique occupant identifiers for +MUCs](https://dino.im/xeps/occupant-id.html). + +Compatibility +============= + + ------- ------------------ + trunk Works + 0.11 Works + ------- ------------------ diff -r 2444fb3b05b7 -r cfe0907808e1 mod_muc_occupant_id/mod_muc_occupant_id.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_occupant_id/mod_muc_occupant_id.lua Sun Jul 14 18:45:10 2019 +0200 @@ -0,0 +1,59 @@ + +-- Implementation of https://dino.im/xeps/occupant-id.html +-- XEP-XXXX: Anonymous unique occupant identifiers for MUCs + +local uuid = require "util.uuid"; +local hmac_sha256 = require "util.hashes".hmac_sha256; +local b64encode = require "util.encodings".base64.encode; + +local xmlns_occupant_id = "urn:xmpp:occupant-id:0"; + +local function edit_occupant(event) + local occupant, room = event.occupant, event.room; + local bare = occupant.bare_jid; + + -- TODO: Move the salt on the MUC component. Setting the salt on the room + -- can be problematic when the room is destroyed. Next time it's recreated + -- the salt will be different and so will be the unique_id. Or maybe we want + -- this anyway? + if room._data.occupant_id_salt == nil then + local salt = uuid.generate(); + room._data.occupant_id_salt = salt; + end + + local unique_id = b64encode(hmac_sha256(bare, room._data.occupant_id_salt)); + + -- TODO: Store this only once per bare jid and not once per occupant? + local stanza = event.stanza; + stanza:tag("occupant-id", { xmlns = xmlns_occupant_id }) + :text(unique_id) + :up(); +end + +local function handle_stanza(event) + local stanza, occupant = event.stanza, event.occupant; + + if stanza.name == "presence" and stanza.attr.type == "unavailable" then -- not required here + return; + end + + -- strip any existing tags to avoid forgery + stanza:remove_children("occupant-id", xmlns_occupant_id); + + if not occupant then return; end + + local unique_id = occupant.sessions[stanza.attr.from] + :get_child("occupant-id", xmlns_occupant_id) + :get_text(); + stanza:tag("occupant-id", { xmlns = xmlns_occupant_id }) + :text(unique_id) + :up(); +end + +module:add_feature(xmlns_occupant_id); +module:hook("muc-disco#info", function (event) + event.reply:tag("feature", { var = xmlns_occupant_id }):up(); +end); + +module:hook("muc-occupant-pre-join", edit_occupant); +module:hook("muc-occupant-groupchat", handle_stanza);