84 lines
3.7 KiB
TypeScript
84 lines
3.7 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
import { readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import { authConfig } from '../../support/auth-config';
|
|
|
|
const root = resolve(__dirname, '../../..');
|
|
const toml = readFileSync(resolve(root, 'supabase/config.toml'), 'utf8');
|
|
const doc = readFileSync(resolve(root, 'docs/auth-konfiguration.md'), 'utf8');
|
|
|
|
/** Aktive (nicht auskommentierte) Zeilen von `config.toml`. */
|
|
const active = toml
|
|
.split('\n')
|
|
.map((l) => l.trim())
|
|
.filter((l) => l && !l.startsWith('#'));
|
|
|
|
function value(key: string, section?: string): string | undefined {
|
|
let current = '';
|
|
for (const line of active) {
|
|
const sec = line.match(/^\[(.+)\]$/);
|
|
if (sec) {
|
|
current = sec[1];
|
|
continue;
|
|
}
|
|
if (section !== undefined && current !== section) continue;
|
|
const kv = line.match(new RegExp(`^${key}\\s*=\\s*(.+)$`));
|
|
if (kv) return kv[1].replace(/^"|"$/g, '');
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
test.describe('Auth-Konfiguration: auth-config.ts stimmt mit config.toml und Doku ueberein', () => {
|
|
test('AUTH-CFG-01: Site-URL', () => {
|
|
expect(value('site_url', 'auth')).toBe(authConfig.siteUrl);
|
|
});
|
|
test('AUTH-CFG-04: E-Mail-Bestaetigung Pflicht', () => {
|
|
expect(value('enable_confirmations', 'auth.email')).toBe('true');
|
|
});
|
|
test('AUTH-CFG-05/-06: Passwort-Mindestlaenge und keine Zeichenklassen', () => {
|
|
expect(Number(value('minimum_password_length', 'auth'))).toBe(authConfig.passwordMinLength);
|
|
expect(value('password_requirements', 'auth')).toBe('');
|
|
});
|
|
test('AUTH-CFG-07: Gueltigkeit der Links', () => {
|
|
expect(Number(value('otp_expiry', 'auth.email'))).toBe(authConfig.otpExpirySeconds);
|
|
});
|
|
test('AUTH-CFG-08: Mindestabstand lokal 1 s', () => {
|
|
expect(value('max_frequency', 'auth.email')).toBe(`${authConfig.maxFrequencySeconds}s`);
|
|
});
|
|
test('AUTH-CFG-10: Login-/Token-Refresh-Drosselung (150 je 5 min, Burst 30)', () => {
|
|
expect(Number(value('token_refresh', 'auth.rate_limit'))).toBe(150);
|
|
expect(authConfig.loginBurst).toBe(30);
|
|
});
|
|
test('AUTH-CFG-11: Signup/Reset/Resend-Drosselung (30 je 5 min)', () => {
|
|
expect(Number(value('sign_in_sign_ups', 'auth.rate_limit'))).toBe(authConfig.otpBurst);
|
|
});
|
|
test('AUTH-CFG-12: Link-Pruefung (30 je 5 min)', () => {
|
|
expect(Number(value('token_verifications', 'auth.rate_limit'))).toBe(30);
|
|
});
|
|
test('AUTH-CFG-14/-15: JWT-Laufzeit und Refresh-Token-Rotation', () => {
|
|
expect(Number(value('jwt_expiry', 'auth'))).toBe(authConfig.jwtExpirySeconds);
|
|
expect(value('enable_refresh_token_rotation', 'auth')).toBe('true');
|
|
expect(Number(value('refresh_token_reuse_interval', 'auth'))).toBe(authConfig.refreshTokenReuseIntervalSeconds);
|
|
});
|
|
test('KTO-01 Kriterium 5: AUTH-CFG-16 Sitzungsbegrenzung ist nicht gesetzt (timebox, inactivity_timeout)', () => {
|
|
expect(active.some((l) => /^timebox\s*=/.test(l))).toBe(false);
|
|
expect(active.some((l) => /^inactivity_timeout\s*=/.test(l))).toBe(false);
|
|
expect(active).not.toContain('[auth.sessions]');
|
|
});
|
|
test('AUTH-CFG-19: alle Benachrichtigungs-Mails aus', () => {
|
|
const sections = active.filter((l) => l.startsWith('[auth.email.notification.'));
|
|
expect(sections.length).toBeGreaterThan(0);
|
|
for (const s of sections) {
|
|
expect(value('enabled', s.slice(1, -1)), s).toBe('false');
|
|
}
|
|
});
|
|
test('AUTH-CFG-24: SMS-Autoconfirm aus (enable_confirmations = true), Voraussetzung fuer den Enumerationsschutz', () => {
|
|
expect(value('enable_confirmations', 'auth.sms')).toBe('true');
|
|
});
|
|
test('docs/auth-konfiguration.md fuehrt AUTH-CFG-01 bis -25', () => {
|
|
for (let i = 1; i <= 25; i++) {
|
|
const id = `AUTH-CFG-${String(i).padStart(2, '0')}`;
|
|
expect(doc, id).toContain(`| ${id} |`);
|
|
}
|
|
});
|
|
});
|