Files
sshkeyvault/tests/e2e/lokale-konten.spec.ts
florian.wildeandClaude Opus 5.5 5d03681f3c feat(deploymentkey): Rotation vor dem Umstellen abbrechen (#036)
Eine begonnene Rotation ließ sich nicht zurücknehmen; nahm ein Host den
neuen Key dauerhaft nicht an, blieb nur das Übergehen. Abbrechen
verwirft jetzt den neuen Key samt Private Key, ein Dry-Run nimmt ihn
wieder von den Hosts, und eine neue Rotation kann sofort starten.

Nebenbei: Aktionen der Benutzerverwaltung (#035) bekommen im Audit-Log
eine eigene Gruppe, statt den Filter „Anmeldung“ zu verwässern; der
E2E-Test für lokale Konten hängt nicht mehr von der Reihenfolge ab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:52:32 +02:00

73 lines
3.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from "@playwright/test";
import { base32Dekodieren, totpCode, totpSchritt } from "../../src/lib/totp";
import { anmelden, oidcBestaetigen } from "./hilfen";
/**
* Lokale Konten (#035) im gebauten Stand: Admin legt ein Konto an, die Person meldet sich zum
* ersten Mal an (eigenes Passwort, TOTP), der Admin sperrt sie – die Sitzung endet sofort.
*/
test.setTimeout(120_000);
test("lokales Konto anlegen, erste Anmeldung, sperren", async ({ page, browser }) => {
const anmeldename = `zz-e2e-${Date.now().toString(36)}`;
const passwort = "ein-eigenes-e2e-passwort";
await anmelden(page);
await page.goto("/einstellungen");
await page.getByRole("link", { name: "Konten verwalten" }).click();
await expect(page.getByRole("heading", { name: "Benutzer", exact: true })).toBeVisible();
// Frische Bestaetigung immer selbst holen – ob ein frueherer Test sie schon gesetzt hat,
// haengt von der Reihenfolge ab. Dass das Recht sie verlangt, pruefen die Unit-Tests.
await page.goto("/bestaetigen?ziel=%2Feinstellungen%2Fbenutzer");
await oidcBestaetigen(page);
await expect(page).toHaveURL(/\/einstellungen\/benutzer$/);
await page.getByLabel("Anmeldename").fill(anmeldename);
await page.getByLabel("Name", { exact: true }).fill("E2E Lokal");
await page.getByLabel("Rolle", { exact: true }).selectOption("OPERATOR");
await page.getByRole("button", { name: "Konto anlegen" }).click();
const anzeige = page.getByRole("region", { name: `Einmal-Passwort für ${anmeldename}` });
const einmal = ((await anzeige.locator("code").textContent()) ?? "").trim();
expect(einmal).toMatch(/^[a-zA-Z2-9]{5}(-[a-zA-Z2-9]{5}){3}$/);
await page.screenshot({ path: "docs/anleitung/bilder/benutzer-desktop.png", fullPage: true });
// Zweiter Browser: die Person meldet sich zum ersten Mal an.
const kontext = await browser.newContext();
const person = await kontext.newPage();
await person.goto("/anmelden");
await person.getByText("Lokales Konto oder Notfallzugang", { exact: true }).click();
await person.getByLabel("Anmeldename").fill(anmeldename);
await person.getByLabel("Passwort").fill(einmal);
await person.getByRole("button", { name: "Mit Benutzername anmelden" }).click();
await expect(person).toHaveURL(/\/anmelden\/passwort/);
await person.getByLabel("Neues Passwort", { exact: true }).fill("zu-kurz");
await person.getByLabel("Neues Passwort wiederholen").fill("zu-kurz");
await person.getByRole("button", { name: "Passwort setzen" }).click();
await expect(person.getByText(/mindestens 12 Zeichen/).last()).toBeVisible();
await person.getByLabel("Neues Passwort", { exact: true }).fill(passwort);
await person.getByLabel("Neues Passwort wiederholen").fill(passwort);
await person.getByRole("button", { name: "Passwort setzen" }).click();
await expect(person).toHaveURL(/\/anmelden\/totp/);
const geheimnis = ((await person.locator("code").first().textContent()) ?? "").trim();
await person
.getByLabel("Code zur Bestätigung")
.fill(totpCode(base32Dekodieren(geheimnis), totpSchritt(Date.now())));
await person.getByRole("button", { name: /TOTP einrichten/ }).click();
await expect(person.getByRole("heading", { name: "Übersicht" })).toBeVisible();
await expect(person.getByText("Operator · über lokales Konto")).toBeVisible();
// Ein Operator verwaltet keine Benutzer.
await person.goto("/einstellungen/benutzer");
await expect(person).toHaveURL(/\/kein-zugriff/);
// Admin sperrt das Konto – die Sitzung der Person endet sofort.
await page.reload();
const zeile = page.getByRole("row").filter({ hasText: anmeldename });
await expect(zeile.getByText("Einrichtung offen")).toHaveCount(0);
await zeile.getByRole("button", { name: /Sperren/ }).click();
await expect(zeile.getByText("gesperrt", { exact: true })).toBeVisible();
await person.goto("/");
await expect(person).toHaveURL(/\/anmelden/);
await kontext.close();
});