comparison plugins/muc/muc.lib.lua @ 13906:0749265327d2

MUC: Record timestamps and actors of affiliation changes This can help with things like timed affiliations or cleanup of obsolete affiliations, identifying recent changes (e.g. to allow efficient catch-up by clients when changes to the affiliation list occur), and such, as well as simple auditing.
author Matthew Wild <mwild1@gmail.com>
date Thu, 26 Jun 2025 14:39:45 +0100
parents f8779be95156
children
comparison
equal deleted inserted replaced
13905:0e346f4d88ce 13906:0749265327d2
22 local resourceprep = require "prosody.util.encodings".stringprep.resourceprep; 22 local resourceprep = require "prosody.util.encodings".stringprep.resourceprep;
23 local st = require "prosody.util.stanza"; 23 local st = require "prosody.util.stanza";
24 local base64 = require "prosody.util.encodings".base64; 24 local base64 = require "prosody.util.encodings".base64;
25 local hmac_sha256 = require "prosody.util.hashes".hmac_sha256; 25 local hmac_sha256 = require "prosody.util.hashes".hmac_sha256;
26 local new_id = require "prosody.util.id".medium; 26 local new_id = require "prosody.util.id".medium;
27 local time = require "prosody.util.time";
27 28
28 local log = module._log; 29 local log = module._log;
29 30
30 local occupant_lib = module:require "muc/occupant" 31 local occupant_lib = module:require "muc/occupant"
31 local muc_util = module:require "muc/util"; 32 local muc_util = module:require "muc/util";
1455 -- Can't demote owners or other admins 1456 -- Can't demote owners or other admins
1456 return nil, "cancel", "not-allowed"; 1457 return nil, "cancel", "not-allowed";
1457 end 1458 end
1458 end 1459 end
1459 1460
1461 data = data or {};
1462 local old_data = self._affiliation_data[jid];
1463
1464 local current_time = time.now();
1465 data.affiliation_created_at = old_data and old_data.affiliation_created_at or current_time;
1466 data.affiliation_created_by = old_data and old_data.affiliation_created_by or actor;
1467 data.affiliation_modified_at = current_time;
1468 data.affiliation_modified_by = actor;
1469
1460 local event_data = { 1470 local event_data = {
1461 room = self; 1471 room = self;
1462 actor = actor; 1472 actor = actor;
1463 jid = jid; 1473 jid = jid;
1464 affiliation = affiliation or "none"; 1474 affiliation = affiliation or "none";
1465 reason = reason; 1475 reason = reason;
1466 previous_affiliation = target_affiliation or "none"; 1476 previous_affiliation = target_affiliation or "none";
1467 data = data and data or nil; -- coerce false to nil 1477 data = data;
1468 previous_data = self._affiliation_data[jid] or nil; 1478 previous_data = self._affiliation_data[jid] or nil;
1469 }; 1479 };
1470 1480
1471 module:fire_event("muc-pre-set-affiliation", event_data); 1481 module:fire_event("muc-pre-set-affiliation", event_data);
1472 if event_data.allowed == false then 1482 if event_data.allowed == false then
1473 local err = event_data.error or { type = "cancel", condition = "not-allowed" }; 1483 local err = event_data.error or { type = "cancel", condition = "not-allowed" };
1474 return nil, err.type, err.condition; 1484 return nil, err.type, err.condition;
1475 end
1476 if affiliation and not data and event_data.data then
1477 -- Allow handlers to add data when none was going to be set
1478 data = event_data.data;
1479 end 1485 end
1480 1486
1481 -- Set in 'database' 1487 -- Set in 'database'
1482 self._affiliations[jid] = affiliation; 1488 self._affiliations[jid] = affiliation;
1483 if not affiliation or data == false or (data ~= nil and next(data) == nil) then 1489 if not affiliation or data == false or (data ~= nil and next(data) == nil) then