/* * Prueft das hinterlegte Client-Secret, soweit es ohne Datenbank geht: * Verschluesselung, Ablaufrechnung und die Pruefung des Datums. * * Der Schluessel muss vor dem Import stehen - msSecret.js liest ihn beim * Verschluesseln aus der Umgebung, genau wie im Betrieb. */ process.env.JWT_SECRET = 'test-schluessel-lang-genug-fuer-die-pruefung'; delete process.env.CRM_ENCRYPTION_KEY; const { WARN_DAYS, daysUntil, decrypt, encrypt, expiryLevel, normalizeExpiry } = await import( '../src/msSecret.js' ); let failures = 0; function check(name, condition, detail = '') { if (condition) { console.log(` ok ${name}${detail ? ` - ${detail}` : ''}`); } else { console.log(` FAIL ${name}${detail ? ` - ${detail}` : ''}`); failures += 1; } } console.log('\nClient-Secret'); console.log('\n Verschluesselung'); const klartext = 'Abc8Q~geheimes-client-secret-aus-entra'; const cipher = encrypt(klartext); check('Ergebnis ist nicht der Klartext', !cipher.includes('geheimes-client-secret')); check('Format ist gekennzeichnet', cipher.startsWith('v1:')); check('Entschluesseln ergibt das Original', decrypt(cipher) === klartext); check( 'zweimal verschluesselt ergibt zwei verschiedene Werte', encrypt(klartext) !== encrypt(klartext), 'eigener Zufallsvektor je Aufruf' ); check('veraenderter Text wird nicht entschluesselt', decrypt(`${cipher}xx`) === '', 'GCM erkennt es'); check('fremdes Format wird abgelehnt', decrypt('irgendwas') === ''); check('leerer Wert bleibt leer', decrypt('') === ''); // Ein anderer Schluessel darf nicht passen - genau das passiert, wenn jemand // JWT_SECRET wechselt. Die Oberflaeche zeigt dann "nicht entschluesselbar". process.env.CRM_ENCRYPTION_KEY = 'ein-ganz-anderer-schluessel-fuer-den-test'; check('anderer Schluessel entschluesselt nicht', decrypt(cipher) === ''); delete process.env.CRM_ENCRYPTION_KEY; check('mit dem alten Schluessel geht es wieder', decrypt(cipher) === klartext); console.log('\n Restlaufzeit'); const heute = new Date('2026-09-21T08:00:00Z'); check('heute sind es 0 Tage', daysUntil('2026-09-21', heute) === 0); check('morgen ist 1 Tag', daysUntil('2026-09-22', heute) === 1); check('gestern sind -1 Tage', daysUntil('2026-09-20', heute) === -1); check('ohne Datum null', daysUntil('', heute) === null); check('unlesbares Datum ergibt null', daysUntil('irgendwann', heute) === null); check('Jahreswechsel zaehlt richtig', daysUntil('2027-09-21', heute) === 365); console.log('\n Warnstufe'); check('kein Datum: unbekannt', expiryLevel(null) === 'unbekannt'); check('abgelaufen bei -1', expiryLevel(-1) === 'abgelaufen'); check('Warnung am Tag des Ablaufs', expiryLevel(0) === 'warnung'); check(`Warnung genau ${WARN_DAYS} Tage vorher`, expiryLevel(WARN_DAYS) === 'warnung'); check('einen Tag frueher noch ok', expiryLevel(WARN_DAYS + 1) === 'ok'); console.log('\n Ablaufdatum pruefen'); check('gueltiges Datum wird uebernommen', normalizeExpiry('2027-03-01').value === '2027-03-01'); check('leer loescht den Eintrag', normalizeExpiry('').value === ''); check('deutsches Format wird abgelehnt', Boolean(normalizeExpiry('01.03.2027').error)); check('31. Februar wird abgelehnt', Boolean(normalizeExpiry('2027-02-31').error)); check('Monat 13 wird abgelehnt', Boolean(normalizeExpiry('2027-13-01').error)); console.log( failures === 0 ? '\nAlle Pruefungen bestanden.\n' : `\n${failures} Pruefung(en) fehlgeschlagen.\n` ); process.exit(failures === 0 ? 0 : 1);