filter to notify user

This commit is contained in:
2026-09-30 13:04:02 +02:00
parent b14213c6d7
commit 0e3fe51b12
+63 -1
View File
@@ -212,6 +212,56 @@ Notifications.sendsms = async (data, tribeId) => {
}
*/
};
/**
* Preprod gate shared by every smatchit notification.
*
* Notifications.filternoitif(tribe, tpl, alias, channel, topics) -> true = send, false = simulate
*
* Reads tribe/objects/tribes/itm/{tribe}.json .notify on every call (a require()
* would be cached and the flag could not be toggled without a pm2 restart):
* { "test": true, "aliasprefix": "smatchit" }
*
* A notification is sent when, in order:
* 1. the tribe has no notify block, or notify.test !== true -> production, never filtered
* 2. tpl.nofilterpreprod === true -> transactional (identification, key recovery)
* 3. alias starts with notify.aliasprefix (defaults to tribeId)
* and every topic it would be published on also starts with the prefix.
*
* Missing alias is refused, not sent: an authenticated caller that forgets to
* propagate the alias must not be able to escape the preprod gate.
* Tribes without a notify block (okwo, ndda) are unaffected.
*/
Notifications.filternoitif = (tribe, tpl, alias, channel = "push", topics = []) => {
const file = path.resolve(__dirname, `../../objects/tribes/itm/${tribe}.json`);
let confnotif = null;
try {
confnotif = fs.existsSync(file) ? fs.readJSONSync(file).notify : null;
} catch (err) {
// unreadable conf must not silently disable the gate
console.log(currentmod, "filternoitif confreadfail:", err.message);
return false;
}
if (!confnotif || confnotif.test !== true) return true;
if (tpl && tpl.nofilterpreprod === true) return true;
const prefix = confnotif.aliasprefix || tribe;
if (typeof alias !== "string" || alias === "") {
if (log)
console.log(
currentmod,
`filternoitif REFUSED ${channel} noalias`,
{ tribe, template: tpl && tpl.tplname }
);
return false;
}
const ok =
alias.startsWith(prefix) &&
topics.every((t) => typeof t === "string" && t.startsWith(prefix));
if (!ok && log)
console.log(currentmod, `filternoitif REFUSED ${channel}`, { tribe, alias, topics });
return ok;
};
Notifications.manageemail = async (
data,
templatename,
@@ -263,7 +313,7 @@ Notifications.manageemail = async (
data: { template: tplpath },
};
}
const results = { fail: [], success: [] };
const results = { fail: [], success: [], simulated: [] };
const emailtosend = {};
// init with common propertie
Object.keys(data).forEach((k) => {
@@ -324,6 +374,16 @@ Notifications.manageemail = async (
if (email.attachments) {
email.attachments.forEach((a) => tplemail.attachments.push(a));
}
// call site 1 of 2 for the preprod gate. The alias is carried by each
// emailsto entry (Jobads.js already builds it) but was never propagated
// into emailtosend, which is what sendmail receives. Assigned (not ||-ed)
// because emailtosend is reused across iterations: an entry without an
// alias must not inherit the previous recipient's.
emailtosend.alias = email.alias;
if (!Notifications.filternoitif(tribe, tplemail, emailtosend.alias, "email")) {
results.simulated.push({ to: emailtosend.to, alias: emailtosend.alias });
continue;
}
//console.log(emailtosend)
sendit = await Notifications.sendmail(emailtosend, tribe);
//const sendit={status:200}
@@ -351,7 +411,9 @@ Notifications.manageemail = async (
data: {
emailsucces: results.success.length,
emailfail: results.fail.length,
emailsimulated: results.simulated.length,
failsdetail: results.fail,
simulateddetail: results.simulated,
timems: Date.now() - start,
},
};