surface SMTP delivery failures and add interactive rotor compass target
This commit is contained in:
120
server/index.js
120
server/index.js
@@ -1047,12 +1047,27 @@ async function handleRequestAccess(req, res, body) {
|
||||
actionLink: link,
|
||||
actionLabel: user.status === "active" ? "Jetzt einloggen" : "E-Mail bestaetigen"
|
||||
});
|
||||
await sendEmailMessage(
|
||||
email,
|
||||
message.subject,
|
||||
message.text,
|
||||
message.html
|
||||
);
|
||||
try {
|
||||
await sendEmailMessage(
|
||||
email,
|
||||
message.subject,
|
||||
message.text,
|
||||
message.html,
|
||||
{ strictDelivery: true }
|
||||
);
|
||||
} catch (error) {
|
||||
if (isChallengeDeliveryError(error)) {
|
||||
await appendAudit("auth.request_access_failed", user, {
|
||||
status: user.status,
|
||||
requestedMethod: requestedMethod || null,
|
||||
method: "fallback-mail",
|
||||
code: error.code,
|
||||
reason: error && error.details ? error.details.reason : null
|
||||
});
|
||||
return sendError(res, 502, error.code, error.publicMessage || "E-Mail konnte nicht zugestellt werden. Bitte spaeter erneut versuchen.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
await appendAudit("auth.request_access", user, {
|
||||
status: user.status,
|
||||
requestedMethod: requestedMethod || null,
|
||||
@@ -1089,14 +1104,29 @@ async function handleRequestAccess(req, res, body) {
|
||||
actionLink: link,
|
||||
actionLabel: user.status === "active" ? "Jetzt einloggen" : "E-Mail bestaetigen"
|
||||
});
|
||||
await dispatchAuthChallenge(req, user, selectedMethod, {
|
||||
type: "link",
|
||||
subject: message.subject,
|
||||
text: message.text,
|
||||
html: message.html,
|
||||
token,
|
||||
link
|
||||
});
|
||||
try {
|
||||
await dispatchAuthChallenge(req, user, selectedMethod, {
|
||||
type: "link",
|
||||
subject: message.subject,
|
||||
text: message.text,
|
||||
html: message.html,
|
||||
token,
|
||||
link
|
||||
});
|
||||
} catch (error) {
|
||||
if (isChallengeDeliveryError(error)) {
|
||||
await appendAudit("auth.request_access_failed", user, {
|
||||
status: user.status,
|
||||
requestedMethod: requestedMethod || null,
|
||||
method: selectedMethod.id,
|
||||
challengeType,
|
||||
code: error.code,
|
||||
reason: error && error.details ? error.details.reason : null
|
||||
});
|
||||
return sendError(res, 502, error.code, error.publicMessage || "E-Mail konnte nicht zugestellt werden. Bitte spaeter erneut versuchen.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
} else if (selectedMethod.type === "otp") {
|
||||
const otpCode = await issueOtpChallenge(user.id, user.status === "active" ? "login" : "verify");
|
||||
challengeHint = `Code wurde ueber ${selectedMethod.label} gesendet.`;
|
||||
@@ -1107,13 +1137,28 @@ async function handleRequestAccess(req, res, body) {
|
||||
text: `Dein Code lautet: ${otpCode}`,
|
||||
code: otpCode
|
||||
});
|
||||
await dispatchAuthChallenge(req, user, selectedMethod, {
|
||||
type: "otp",
|
||||
subject: message.subject,
|
||||
text: message.text,
|
||||
html: message.html,
|
||||
code: otpCode
|
||||
});
|
||||
try {
|
||||
await dispatchAuthChallenge(req, user, selectedMethod, {
|
||||
type: "otp",
|
||||
subject: message.subject,
|
||||
text: message.text,
|
||||
html: message.html,
|
||||
code: otpCode
|
||||
});
|
||||
} catch (error) {
|
||||
if (isChallengeDeliveryError(error)) {
|
||||
await appendAudit("auth.request_access_failed", user, {
|
||||
status: user.status,
|
||||
requestedMethod: requestedMethod || null,
|
||||
method: selectedMethod.id,
|
||||
challengeType,
|
||||
code: error.code,
|
||||
reason: error && error.details ? error.details.reason : null
|
||||
});
|
||||
return sendError(res, 502, error.code, error.publicMessage || "E-Mail konnte nicht zugestellt werden. Bitte spaeter erneut versuchen.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
} else if (selectedMethod.type === "oauth") {
|
||||
const purpose = user.status === "active" ? "login" : "verify";
|
||||
const stateToken = await issueOauthChallenge(user.id, purpose, selectedMethod.id);
|
||||
@@ -2285,7 +2330,7 @@ async function dispatchAuthChallenge(req, user, method, payload) {
|
||||
source: "server-prelog"
|
||||
});
|
||||
|
||||
await plugin.instance.execute("send_challenge", {
|
||||
const result = await plugin.instance.execute("send_challenge", {
|
||||
methodId: method.id,
|
||||
methodType: method.type,
|
||||
user: sanitizeUser(user),
|
||||
@@ -2293,6 +2338,10 @@ async function dispatchAuthChallenge(req, user, method, payload) {
|
||||
origin: publicBaseUrlFor(req),
|
||||
payload
|
||||
}, { user });
|
||||
|
||||
if (result && result.delivered === false && result.smtpError) {
|
||||
throw buildAuthChallengeDeliveryError(result.smtpError, method, user);
|
||||
}
|
||||
}
|
||||
|
||||
async function issueOtpChallenge(userId, purpose) {
|
||||
@@ -2472,12 +2521,29 @@ async function ensureMailOutboxInitialized() {
|
||||
}
|
||||
}
|
||||
|
||||
async function sendEmailMessage(to, subject, text, html = "") {
|
||||
function buildAuthChallengeDeliveryError(reason, method, user) {
|
||||
const error = new Error("E-Mail konnte nicht zugestellt werden");
|
||||
error.code = "auth.challenge_delivery_failed";
|
||||
error.publicMessage = "E-Mail konnte nicht zugestellt werden. Bitte spaeter erneut versuchen.";
|
||||
error.details = {
|
||||
reason: String(reason || "delivery-failed"),
|
||||
method: method && method.id ? String(method.id) : null,
|
||||
userId: user && user.id ? String(user.id) : null
|
||||
};
|
||||
return error;
|
||||
}
|
||||
|
||||
function isChallengeDeliveryError(error) {
|
||||
return Boolean(error && error.code === "auth.challenge_delivery_failed");
|
||||
}
|
||||
|
||||
async function sendEmailMessage(to, subject, text, html = "", options = {}) {
|
||||
const strictDelivery = Boolean(options && options.strictDelivery);
|
||||
const smtpMethod = listPublicAuthMethods().find((entry) => entry.id === "smtp-link");
|
||||
if (smtpMethod) {
|
||||
const plugin = runtime.plugins.get(smtpMethod.pluginId);
|
||||
if (plugin && typeof plugin.instance.execute === "function") {
|
||||
await plugin.instance.execute("send_challenge", {
|
||||
const result = await plugin.instance.execute("send_challenge", {
|
||||
methodId: smtpMethod.id,
|
||||
methodType: smtpMethod.type,
|
||||
user: null,
|
||||
@@ -2490,9 +2556,15 @@ async function sendEmailMessage(to, subject, text, html = "") {
|
||||
html: String(html || "")
|
||||
}
|
||||
}, { user: null });
|
||||
if (strictDelivery && result && result.delivered === false && result.smtpError) {
|
||||
throw buildAuthChallengeDeliveryError(result.smtpError, smtpMethod, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strictDelivery) {
|
||||
throw buildAuthChallengeDeliveryError("smtp-method-unavailable", { id: "smtp-link" }, null);
|
||||
}
|
||||
const entry = {
|
||||
at: new Date().toISOString(),
|
||||
to,
|
||||
|
||||
Reference in New Issue
Block a user