Mercurial > prosody-modules
view mod_vcard_muc/mod_vcard_muc.lua @ 5298:12f7d8b901e0
mod_audit: Support for adding location (GeoIP) to audit events
This can be more privacy-friendly than logging full IP addresses, and also
more informative to a user - IP addresses don't mean much to the average
person, however if they see activity from outside their expected country, they
can immediately identify suspicious activity.
As with IPs, this field is configurable for deployments that would like to
disable it. Location is also not logged when the geoip library is not
available.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sat, 01 Apr 2023 13:11:53 +0100 |
parents | dddac5a3f447 |
children | 6fb26b6691c0 |
line wrap: on
line source
-- Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain -- Copyright (C) 2018 Michel Le Bihan -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- local st = require "util.stanza" local jid_split = require "util.jid".split; local base64 = require"util.encodings".base64; local sha1 = require"util.hashes".sha1; local mod_muc = module:depends"muc"; local vcards = module:open_store(); module:add_feature("vcard-temp"); local get_room_from_jid = rawget(mod_muc, "get_room_from_jid") or function (jid) local rooms = rawget(mod_muc, "rooms"); return rooms[jid]; end local function get_photo_hash(room) local room_node = jid_split(room.jid); local vcard = st.deserialize(vcards:get(room_node)); if vcard then local photo = vcard:get_child("PHOTO"); if photo then local photo_b64 = photo:get_child_text("BINVAL"); local photo_raw = photo_b64 and base64.decode(photo_b64); return sha1(photo_raw, true); end end end local function broadcast_presence(room, to) local photo_hash = get_photo_hash(room); local presence_vcard = st.presence({to = to, from = room.jid}) :tag("x", { xmlns = "vcard-temp:x:update" }) :tag("photo"):text(photo_hash):up(); if to == nil then room:broadcast_message(presence_vcard); else module:send(presence_vcard); end end local function handle_vcard(event) local session, stanza = event.origin, event.stanza; local room_jid = stanza.attr.to; local room_node = jid_split(room_jid); local room = get_room_from_jid(room_jid); if not room then session.send(st.error_reply(stanza, "cancel", "item-not-found")) return true; end local from = stanza.attr.from; local from_affiliation = room:get_affiliation(from); if stanza.attr.type == "get" then local vCard; vCard = st.deserialize(vcards:get(room_node)); if vCard then session.send(st.reply(stanza):add_child(vCard)); -- send vCard! else session.send(st.error_reply(stanza, "cancel", "item-not-found")); end else if from_affiliation == "owner" or (module.may and module:may("muc:automatic-ownership", from)) then if vcards:set(room_node, st.preserialize(stanza.tags[1])) then session.send(st.reply(stanza):tag("vCard", { xmlns = "vcard-temp" })); broadcast_presence(room, nil) room:broadcast_message(st.message({ from = room.jid, type = "groupchat" }) :tag("x", { xmlns = "http://jabber.org/protocol/muc#user" }) :tag("status", { code = "104" })); else -- TODO unable to write file, file may be locked, etc, what's the correct error? session.send(st.error_reply(stanza, "wait", "internal-server-error")); end else session.send(st.error_reply(stanza, "auth", "forbidden")); end end return true; end module:hook("iq/bare/vcard-temp:vCard", handle_vcard); module:hook("iq/host/vcard-temp:vCard", handle_vcard); module:hook("muc-disco#info", function(event) event.reply:tag("feature", { var = "vcard-temp" }):up(); table.insert(event.form, { name = "{http://modules.prosody.im/mod_vcard_muc}avatar#sha1", type = "text-single", }); event.formdata["{http://modules.prosody.im/mod_vcard_muc}avatar#sha1"] = get_photo_hash(event.room); end); module:hook("muc-occupant-session-new", function(event) broadcast_presence(event.room, event.jid); end)