Files
Pickup-Config/services/sessionRefresh.js
2026-02-01 17:47:54 +01:00

129 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const foodsharingClient = require('./foodsharingClient');
const sessionStore = require('./sessionStore');
const notificationService = require('./notificationService');
const ADMIN_SESSION_ERROR_COOLDOWN_MS = 6 * 60 * 60 * 1000;
const adminSessionErrorCooldowns = new Map();
function shouldNotifyAdminSessionError(key) {
if (!key) {
return false;
}
const now = Date.now();
const lastNotified = adminSessionErrorCooldowns.get(key) || 0;
if (now - lastNotified < ADMIN_SESSION_ERROR_COOLDOWN_MS) {
return false;
}
adminSessionErrorCooldowns.set(key, now);
return true;
}
function isUnauthorizedError(error) {
const status = error?.response?.status;
return status === 401 || status === 403;
}
function isCsrfError(error) {
const status = error?.response?.status;
if (status !== 400) {
return false;
}
const data = error?.response?.data;
const message =
typeof data === 'string'
? data
: typeof data?.message === 'string'
? data.message
: '';
return message.toLowerCase().includes('csrf');
}
async function refreshSession(session, { label } = {}) {
if (!session?.credentials?.email || !session?.credentials?.password) {
console.warn(
`[SESSION] Session ${session?.id || 'unbekannt'} kann nicht erneuert werden keine Zugangsdaten gespeichert.`
);
return false;
}
try {
const refreshed = await foodsharingClient.login(
session.credentials.email,
session.credentials.password
);
sessionStore.update(session.id, {
cookieHeader: refreshed.cookieHeader,
csrfToken: refreshed.csrfToken,
profile: {
...session.profile,
...refreshed.profile
}
});
console.log(
`[SESSION] Session ${session.id} wurde erfolgreich erneuert${label ? ` (${label})` : ''}.`
);
return true;
} catch (error) {
console.error(
`[SESSION] Session ${session?.id || 'unbekannt'} konnte nicht erneuert werden${label ? ` (${label})` : ''}:`,
error.message
);
const profileId = session?.profile?.id ? String(session.profile.id) : null;
const notifyKey = profileId || session?.id || null;
if (shouldNotifyAdminSessionError(notifyKey)) {
try {
await notificationService.sendAdminSessionErrorNotification({
profileId,
profileEmail: session?.credentials?.email || session?.profile?.email,
profileName: session?.profile?.name,
sessionId: session?.id,
error: error?.message,
label
});
} catch (notifyError) {
console.error('[NOTIFY] Admin-Session-Fehler konnte nicht gemeldet werden:', notifyError.message);
}
}
return false;
}
}
async function ensureSession(session) {
if (!session?.profile?.id) {
return false;
}
if (!session.cookieHeader) {
return refreshSession(session, { label: 'missing-cookie' });
}
return true;
}
async function withSessionRetry(session, action, { label } = {}) {
if (!session) {
throw new Error('Session fehlt');
}
if (!session.cookieHeader && session.credentials) {
const refreshed = await refreshSession(session, { label });
if (!refreshed) {
throw new Error('Session konnte nicht erneuert werden');
}
}
try {
return await action();
} catch (error) {
if (!isUnauthorizedError(error) && !isCsrfError(error)) {
throw error;
}
const refreshed = await refreshSession(session, { label });
if (!refreshed) {
throw error;
}
return action();
}
}
module.exports = {
ensureSession,
refreshSession,
withSessionRetry
};