test: Verschlüsselung und Kalendermodelle absichern
Sieben Tests für die Tokenverschlüsselung: Rückweg, Umlaute, verschiedene Chiffren bei gleichem Klartext, und dass eine Veränderung am Chiffrat null ergibt statt Unsinn. Der Integrationstest deckt jetzt auch ab, dass dasselbe Konto mit verschiedenen Kalendern erlaubt ist, ein Upsert den Termin aktualisiert statt zu doppeln, und ein Bereich das Löschen seines Standard-Kalenderkontos überlebt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d8d3227c82
commit
df50627a20
@@ -0,0 +1,62 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
/**
|
||||
* Die Verschlüsselung liegt in src/server, weil sie AUTH_SECRET braucht.
|
||||
* Für den Test wird die Umgebung ersetzt und "server-only" auf ein leeres
|
||||
* Modul umgebogen — sonst bricht der Import außerhalb einer Serverumgebung ab.
|
||||
*/
|
||||
vi.mock('server-only', () => ({}))
|
||||
|
||||
vi.mock('@/server/umgebung', () => ({
|
||||
umgebung: () => ({ AUTH_SECRET: 'test-geheimnis-fuer-die-ableitung-1234567890' }),
|
||||
}))
|
||||
|
||||
const { entschluesseln, schluesselVergessen, verschluesseln } =
|
||||
await import('@/server/krypto')
|
||||
|
||||
describe('verschluesseln und entschluesseln', () => {
|
||||
beforeEach(() => {
|
||||
schluesselVergessen()
|
||||
})
|
||||
|
||||
it('gibt zurück, was hineinging', () => {
|
||||
const klartext = 'ya29.beispiel-aktualisierungstoken'
|
||||
expect(entschluesseln(verschluesseln(klartext))).toBe(klartext)
|
||||
})
|
||||
|
||||
it('kommt mit Umlauten und langen Texten zurecht', () => {
|
||||
const klartext = 'Rückgabewert mit Umlauten: äöüß — ' + 'x'.repeat(4000)
|
||||
expect(entschluesseln(verschluesseln(klartext))).toBe(klartext)
|
||||
})
|
||||
|
||||
it('erzeugt bei gleichem Text verschiedene Chiffren', () => {
|
||||
// Sonst ließe sich an der Datenbank ablesen, welche Konten dasselbe
|
||||
// Token tragen.
|
||||
expect(verschluesseln('gleich')).not.toBe(verschluesseln('gleich'))
|
||||
})
|
||||
|
||||
it('lässt den Klartext nicht durchscheinen', () => {
|
||||
expect(verschluesseln('geheim')).not.toContain('geheim')
|
||||
})
|
||||
|
||||
it('gibt für nichts auch nichts zurück', () => {
|
||||
expect(entschluesseln(null)).toBeNull()
|
||||
})
|
||||
|
||||
it('weist Veränderungen ab, statt Unsinn zu liefern', () => {
|
||||
const chiffre = verschluesseln('unverändert')
|
||||
const teile = chiffre.split(':')
|
||||
// Ein Bit im Inhalt kippen.
|
||||
const inhalt = Buffer.from(teile[3] ?? '', 'base64url')
|
||||
inhalt[0] = (inhalt[0] ?? 0) ^ 0x01
|
||||
teile[3] = inhalt.toString('base64url')
|
||||
|
||||
expect(entschluesseln(teile.join(':'))).toBeNull()
|
||||
})
|
||||
|
||||
it('weist eine fremde Form ab', () => {
|
||||
expect(entschluesseln('einfach nur Text')).toBeNull()
|
||||
expect(entschluesseln('v2:a:b:c')).toBeNull()
|
||||
expect(entschluesseln('v1:zu:wenige')).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user