import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { anschlussAus, warnungZuruecksetzen } from '@/lib/auth/anschluss' /** * Aus welchem Kopf die Adresse des Aufrufers gelesen wird. * * Vorher stand dort der ERSTE Eintrag von "x-forwarded-for". Das ist die * klassische Verwechslung: Der Kopf ist eine Liste, an die jeder * Zwischenknoten hinten anhaengt - der erste Eintrag ist also der, den der * Aufrufer selbst mitgeschickt hat. Wer bei jeder Anfrage eine andere Zahl * hineinschrieb, sah fuer die Anmeldesperre wie tausend Anschluesse aus. */ function koepfe(werte: Record): Headers { return new Headers(werte) } describe('Anschluss des Aufrufers', () => { beforeEach(() => { warnungZuruecksetzen() delete process.env.VERTRAUE_PROXY delete process.env.VERTRAUE_PROXY_STUFEN }) afterEach(() => { delete process.env.VERTRAUE_PROXY delete process.env.VERTRAUE_PROXY_STUFEN vi.restoreAllMocks() }) describe('ohne vertrauten Proxy', () => { it('glaubt dem weitergereichten Kopf nicht', () => { const warnung = vi.spyOn(console, 'warn').mockImplementation(() => {}) expect(anschlussAus(koepfe({ 'x-forwarded-for': '203.0.113.9' }))).toBeNull() expect(warnung).toHaveBeenCalledOnce() }) it('warnt nur einmal, nicht bei jeder Anfrage', () => { const warnung = vi.spyOn(console, 'warn').mockImplementation(() => {}) for (let i = 0; i < 20; i += 1) { anschlussAus(koepfe({ 'x-forwarded-for': `203.0.113.${i}` })) } expect(warnung).toHaveBeenCalledOnce() }) it('schweigt, wenn gar kein solcher Kopf ankommt', () => { const warnung = vi.spyOn(console, 'warn').mockImplementation(() => {}) expect(anschlussAus(koepfe({}))).toBeNull() expect(warnung).not.toHaveBeenCalled() }) }) describe('mit einem vertrauten Proxy', () => { beforeEach(() => { process.env.VERTRAUE_PROXY = 'true' }) it('nimmt den letzten Eintrag, nicht den ersten', () => { // Links das, was der Aufrufer selbst behauptet hat; rechts das, was // der Proxy gesehen hat. Nur letzteres ist etwas wert. const kopf = koepfe({ 'x-forwarded-for': '10.0.0.1, 198.51.100.7' }) expect(anschlussAus(kopf)).toBe('198.51.100.7') }) it('laesst sich durch eine erfundene Kette nicht taeuschen', () => { const kopf = koepfe({ 'x-forwarded-for': '1.1.1.1, 2.2.2.2, 3.3.3.3, 198.51.100.7', }) expect(anschlussAus(kopf)).toBe('198.51.100.7') }) it('nimmt den einzigen Eintrag, wenn der Aufrufer keinen mitschickte', () => { expect(anschlussAus(koepfe({ 'x-forwarded-for': '198.51.100.7' }))).toBe('198.51.100.7') }) it('faellt auf x-real-ip zurueck', () => { expect(anschlussAus(koepfe({ 'x-real-ip': '198.51.100.7' }))).toBe('198.51.100.7') }) it('gibt null, wenn nichts da ist', () => { expect(anschlussAus(koepfe({}))).toBeNull() }) it('kommt mit Leerraum und leeren Gliedern zurecht', () => { const kopf = koepfe({ 'x-forwarded-for': ' 10.0.0.1 , , 198.51.100.7 ' }) expect(anschlussAus(kopf)).toBe('198.51.100.7') }) }) describe('mit mehreren Stufen', () => { it('zaehlt die angegebene Anzahl von hinten ab', () => { process.env.VERTRAUE_PROXY = 'true' process.env.VERTRAUE_PROXY_STUFEN = '2' // Zwei eigene Zwischenknoten: der aeussere haengt 198.51.100.7 an, // der innere 10.0.0.5. Der Aufrufer steht eine Stelle weiter links. const kopf = koepfe({ 'x-forwarded-for': 'erfunden, 198.51.100.7, 10.0.0.5' }) expect(anschlussAus(kopf)).toBe('198.51.100.7') }) it('greift nicht ueber den Anfang der Kette hinaus', () => { process.env.VERTRAUE_PROXY = 'true' process.env.VERTRAUE_PROXY_STUFEN = '9' expect(anschlussAus(koepfe({ 'x-forwarded-for': '198.51.100.7' }))).toBe('198.51.100.7') }) }) describe('der Schalter selbst', () => { it('gilt nur bei ausdruecklichem Ja', () => { for (const wert of ['false', 'nein', '0', 'vielleicht', '']) { warnungZuruecksetzen() vi.spyOn(console, 'warn').mockImplementation(() => {}) process.env.VERTRAUE_PROXY = wert expect(anschlussAus(koepfe({ 'x-forwarded-for': '198.51.100.7' }))).toBeNull() } }) it('nimmt true, 1 und ja', () => { for (const wert of ['true', '1', 'ja', 'TRUE', ' Ja ']) { process.env.VERTRAUE_PROXY = wert expect(anschlussAus(koepfe({ 'x-forwarded-for': '198.51.100.7' }))).toBe('198.51.100.7') } }) }) })