mod_muc_occupant_id/mod_muc_occupant_id.lua
author Maxime “pep” Buquet <pep@bouah.net>
Thu, 12 Sep 2019 01:16:26 +0200
changeset 3674 6a437d6eb69f
parent 3658 7b02b8de6d27
child 3779 d60efdb947fd
permissions -rw-r--r--
mod_muc_occupant_id: add TODO regarding MAM handling
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3633
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
     1
3635
d6164ae6179c mod_muc_occupant_id: Update links to the XEP inbox.
Maxime “pep” Buquet <pep@bouah.net>
parents: 3634
diff changeset
     2
-- Implementation of https://xmpp.org/extensions/inbox/occupant-id.html
3658
7b02b8de6d27 mod_muc_occupant_id: Update XEP number (XEP-0421)
Maxime “pep” Buquet <pep@bouah.net>
parents: 3636
diff changeset
     3
-- XEP-0421: Anonymous unique occupant identifiers for MUCs
3633
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
     4
3636
83a68f5fde1d mod_muc_occupant_id: depend on muc.
Maxime “pep” Buquet <pep@bouah.net>
parents: 3635
diff changeset
     5
module:depends("muc");
83a68f5fde1d mod_muc_occupant_id: depend on muc.
Maxime “pep” Buquet <pep@bouah.net>
parents: 3635
diff changeset
     6
3633
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
     7
local uuid = require "util.uuid";
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
     8
local hmac_sha256 = require "util.hashes".hmac_sha256;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
     9
local b64encode = require "util.encodings".base64.encode;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    10
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    11
local xmlns_occupant_id = "urn:xmpp:occupant-id:0";
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    12
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    13
local function edit_occupant(event)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    14
	local occupant, room = event.occupant, event.room;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    15
	local bare = occupant.bare_jid;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    16
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    17
	-- TODO: Move the salt on the MUC component. Setting the salt on the room
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    18
	-- can be problematic when the room is destroyed. Next time it's recreated
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    19
	-- the salt will be different and so will be the unique_id. Or maybe we want
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    20
	-- this anyway?
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    21
	if room._data.occupant_id_salt == nil then
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    22
		local salt = uuid.generate();
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    23
		room._data.occupant_id_salt = salt;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    24
	end
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    25
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    26
	local unique_id = b64encode(hmac_sha256(bare, room._data.occupant_id_salt));
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    27
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    28
	-- TODO: Store this only once per bare jid and not once per occupant?
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    29
	local stanza = event.stanza;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    30
	stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    31
		:text(unique_id)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    32
		:up();
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    33
end
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    34
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    35
local function handle_stanza(event)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    36
	local stanza, occupant = event.stanza, event.occupant;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    37
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    38
	if stanza.name == "presence" and stanza.attr.type == "unavailable" then -- not required here
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    39
		return;
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    40
	end
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    41
3674
6a437d6eb69f mod_muc_occupant_id: add TODO regarding MAM handling
Maxime “pep” Buquet <pep@bouah.net>
parents: 3658
diff changeset
    42
	-- TODO: Handle MAM.
6a437d6eb69f mod_muc_occupant_id: add TODO regarding MAM handling
Maxime “pep” Buquet <pep@bouah.net>
parents: 3658
diff changeset
    43
3633
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    44
	-- strip any existing <occupant-id/> tags to avoid forgery
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    45
	stanza:remove_children("occupant-id", xmlns_occupant_id);
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    46
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    47
	local unique_id = occupant.sessions[stanza.attr.from]
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    48
		:get_child("occupant-id", xmlns_occupant_id)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    49
		:get_text();
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    50
	stanza:tag("occupant-id", { xmlns = xmlns_occupant_id })
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    51
		:text(unique_id)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    52
		:up();
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    53
end
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    54
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    55
module:add_feature(xmlns_occupant_id);
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    56
module:hook("muc-disco#info", function (event)
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    57
	event.reply:tag("feature", { var = xmlns_occupant_id }):up();
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    58
end);
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    59
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    60
module:hook("muc-occupant-pre-join", edit_occupant);
cfe0907808e1 mod_muc_occupant_id: initial commit
Maxime “pep” Buquet <pep@bouah.net>
parents:
diff changeset
    61
module:hook("muc-occupant-groupchat", handle_stanza);