Änderungen: - Hinzufügung von Debug-Protokollausgaben zur Anzeige aller relevanten Umgebungsvariablen für die Redis-Konfiguration. - Detaillierte Protokollierung der finalen Redis-Konfiguration, einschließlich Host, Port, Passwort und URL. Diese Anpassungen verbessern die Transparenz und erleichtern die Fehlersuche bei der Redis-Konfiguration.
143 lines
5.5 KiB
JavaScript
143 lines
5.5 KiB
JavaScript
import { createClient } from 'redis';
|
|
import User from '../models/community/user.js';
|
|
// dotenv wird global in server.js/app.js geladen
|
|
|
|
const EXPIRATION_TIME = 30 * 60 * 1000;
|
|
|
|
// Debug: Zeige alle Umgebungsvariablen
|
|
console.log('[redis] DEBUG - Alle Umgebungsvariablen:');
|
|
console.log('[redis] process.env.REDIS_HOST:', process.env.REDIS_HOST);
|
|
console.log('[redis] process.env.REDIS_PORT:', process.env.REDIS_PORT);
|
|
console.log('[redis] process.env.REDIS_PASSWORD:', process.env.REDIS_PASSWORD ? '***gesetzt***' : 'NICHT GESETZT');
|
|
console.log('[redis] process.env.REDIS_PASS:', process.env.REDIS_PASS ? '***gesetzt***' : 'NICHT GESETZT');
|
|
console.log('[redis] process.env.REDIS_URL:', process.env.REDIS_URL);
|
|
|
|
const redisHost = process.env.REDIS_HOST || '127.0.0.1';
|
|
const redisPort = process.env.REDIS_PORT || '6379';
|
|
const redisPassword = process.env.REDIS_PASSWORD || process.env.REDIS_PASS || undefined;
|
|
const redisUrl = process.env.REDIS_URL || `redis://${redisHost}:${redisPort}`;
|
|
|
|
console.log('[redis] Finale Redis-Konfiguration:');
|
|
console.log('[redis] redisHost:', redisHost);
|
|
console.log('[redis] redisPort:', redisPort);
|
|
console.log('[redis] redisPassword:', redisPassword ? '***gesetzt***' : 'NICHT GESETZT');
|
|
console.log('[redis] redisUrl:', redisUrl);
|
|
|
|
if (!process.env.REDIS_HOST || !process.env.REDIS_PORT) {
|
|
console.warn(`[redis] Verwende Fallback ${redisHost}:${redisPort}`);
|
|
}
|
|
if (!process.env.REDIS_PASSWORD && !process.env.REDIS_PASS && !process.env.REDIS_URL) {
|
|
console.warn('[redis] Kein Passwort gesetzt (REDIS_PASSWORD/REDIS_PASS) und keine REDIS_URL vorhanden. Wenn der Server Auth erfordert, schlägt dies fehl.');
|
|
}
|
|
|
|
const redisClient = createClient({
|
|
url: redisUrl,
|
|
password: redisPassword,
|
|
legacyMode: false,
|
|
});
|
|
|
|
redisClient.on('error', (err) => {
|
|
if (typeof err?.message === 'string' && err.message.includes('NOAUTH')) {
|
|
console.error('[redis] Authentifizierungsfehler: Server verlangt Passwort. Bitte REDIS_PASSWORD/REDIS_PASS oder REDIS_URL setzen.');
|
|
} else {
|
|
console.error('[redis] Fehler:', err);
|
|
}
|
|
});
|
|
|
|
redisClient.connect().catch(console.error);
|
|
|
|
const setUserSession = async (userId, sessionData) => {
|
|
try {
|
|
await redisClient.sendCommand(['JSON.SET', `user:${userId}`, '.', JSON.stringify(sessionData)]);
|
|
console.log(userId, sessionData);
|
|
const sessionDataStr = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
|
|
console.log(sessionDataStr);
|
|
} catch (error) {
|
|
console.error('Fehler beim Setzen der Benutzersitzung:', error);
|
|
}
|
|
};
|
|
|
|
const deleteUserSession = async (userId) => {
|
|
try {
|
|
const result = await redisClient.del(`user:${userId}`);
|
|
if (result === 1) {
|
|
console.log(`Benutzersitzung für Benutzer ${userId} erfolgreich gelöscht.`);
|
|
} else {
|
|
console.warn(`Benutzersitzung für Benutzer ${userId} war nicht vorhanden.`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Löschen der Benutzersitzung:', error);
|
|
}
|
|
};
|
|
|
|
const convertToOriginalType = (value) => {
|
|
if (value === 'true') return true;
|
|
if (value === 'false') return false;
|
|
if (!isNaN(value) && value.trim() !== '') return Number(value);
|
|
return value;
|
|
};
|
|
|
|
const getUserSession = async (userId) => {
|
|
try {
|
|
const sessionData = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
|
|
return JSON.parse(sessionData);
|
|
} catch (error) {
|
|
console.error('Fehler beim Abrufen der Benutzersitzung:', error);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const updateUserTimestamp = async (userId) => {
|
|
try {
|
|
const userKey = `user:${userId}`;
|
|
const userExists = await redisClient.exists(userKey);
|
|
if (userExists) {
|
|
const sessionDataString = await redisClient.sendCommand(['JSON.GET', `user:${userId}`]);
|
|
const sessionData = JSON.parse(sessionDataString);
|
|
sessionData.timestamp = Date.now();
|
|
await redisClient.sendCommand(['JSON.SET', `user:${userId}`, '.', JSON.stringify(sessionData)]);
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Aktualisieren des Zeitstempels:', error);
|
|
}
|
|
};
|
|
|
|
const cleanupExpiredSessions = async () => {
|
|
try {
|
|
const keys = await redisClient.keys('user:*');
|
|
const now = Date.now();
|
|
|
|
for (const key of keys) {
|
|
try {
|
|
const sessionStr = await redisClient.sendCommand(['JSON.GET', key]);
|
|
if (sessionStr) {
|
|
const session = JSON.parse(sessionStr);
|
|
if (session.timestamp && now - parseInt(session.timestamp) > EXPIRATION_TIME) {
|
|
const userId = key.split(':')[1];
|
|
await redisClient.del(key);
|
|
await User.update({ authCode: '' }, { where: { hashedId: userId } });
|
|
console.log(`Abgelaufene Sitzung für Benutzer ${userId} mit RedisJSON gelöscht.`);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error.message.includes('WRONGTYPE')) {
|
|
console.warn(`Schlüssel ${key} ist kein JSON-Objekt, wird übersprungen.`);
|
|
} else {
|
|
console.error(`Fehler beim Bereinigen für Schlüssel ${key}:`, error);
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Bereinigen abgelaufener Sitzungen mit RedisJSON:', error);
|
|
}
|
|
};
|
|
|
|
export {
|
|
setUserSession,
|
|
deleteUserSession,
|
|
getUserSession,
|
|
updateUserTimestamp,
|
|
cleanupExpiredSessions,
|
|
redisClient
|
|
};
|