0645cac618
Der am Vormittag gefundene Zugriffs-Guard-Defekt ist behoben (260907-e8k) und im echten Browser gegen ein frisch gebautes Web-Image nachgeprueft. nutzer2 ohne Freigabe bekommt jetzt auf /modules/tender-radar, dessen Unterseiten my-sources und settings sowie auf /modules/dkv-fleet die 403-Seite als Serverantwort. Auf /modules/cert-manager, wo er eine Freigabe hat, kommt er weiterhin durch — das ist die Gegenprobe dagegen, dass die Sperre zu weit greift. admin sieht alle vier Adressen unveraendert, nutzer1 sieht Meine Quellen mit allen drei Abschnitten; die Phase-17-Funktion ist unbeschaedigt. Im Bericht zusaetzlich festgehalten, dass ein erster Messversuch per fetch() aus der laufenden Seite heraus faelschlich alle Seiten als gesperrt meldete, auch fuer den Administrator. Der Aufruf fuehrt die Sitzung nicht wie eine echte Navigation mit. Alle berichteten Zahlen stammen aus echten Seitenaufrufen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5jtbGzC5Sf9npJ3JCjKhq
156 lines
9.9 KiB
Markdown
156 lines
9.9 KiB
Markdown
---
|
|
phase: 15-modul-berechtigungen-gruppen-user-grants
|
|
kind: uat-nachtrag
|
|
date: 2026-09-07
|
|
windows_addressed: [1, 2, 3]
|
|
windows_opened: [10]
|
|
windows_closed_later: [10]
|
|
result: 2 von 3 bestanden, 1 mit Befund — Befund am selben Tag behoben und gegengeprueft
|
|
---
|
|
|
|
# Phase 15 — Browser-Gegenproben, nachgeholt am 2026-09-07
|
|
|
|
Die drei Browser-Durchläufe aus den Plänen 15-06, 15-07 und 15-08 waren seit dem
|
|
2026-08-04 offen, weil in den damaligen Ausführungssitzungen kein Browser-Tool
|
|
verfügbar war (WINDOWS.md #1, #2, #3). Sie wurden jetzt nachgeholt.
|
|
|
|
**Aufbau:** frisch gebaute Images aus `main` (`79015dd`), lokaler Docker-Stack,
|
|
leere Datenbank, echter Chrome über Playwright. Testdaten über die Oberfläche
|
|
angelegt: Modul im Marktplatz aktiviert, zwei USER-Konten (`nutzer1`, `nutzer2`)
|
|
im selben Mandanten, Gruppen und Freigaben über die Administrationsseiten.
|
|
|
|
## WINDOWS #1 — Gruppenverwaltung (15-06) — BESTANDEN
|
|
|
|
| Schritt aus dem Plan | Beobachtung |
|
|
|---|---|
|
|
| Gruppe anlegen | „Vertrieb" erscheint in der Liste, Spalte AD-Bindung „Manuell", 0 Mitglieder |
|
|
| Umbenennen | Auf „Vertrieb Innendienst" geändert, Liste zieht nach |
|
|
| Standardmarkierung setzen | Markierung wandert exklusiv: „Alle Benutzer" wechselt auf „Als Standardgruppe festlegen", die neue Gruppe trägt „Standardgruppe" |
|
|
| Standardmarkierung wieder abschalten | Durch Setzen bei „Alle Benutzer" zurückgewandert |
|
|
| Mitglied hinzufügen | „Nutzer Eins" erscheint mit Herkunfts-Badge „Manuell"; seine Auswahl-Checkbox ist danach gesperrt, ein Doppel-Hinzufügen also nicht möglich |
|
|
| Mitglied entfernen | Liste wieder leer, Checkbox wieder frei |
|
|
| Löschdialog mit gefüllter Gruppe | „Diese Gruppe hat 1 Mitglieder und 1 Modul-Freigaben." — beide Zahlen konkret genannt (D-17) |
|
|
| Löschvorgang bei gestoppter API | Sichtbare deutsche Klartextmeldung „Gruppe konnte nicht gelöscht werden. Bitte erneut versuchen.", Löschen-Knopf danach gesperrt, Gruppe bleibt in der Liste |
|
|
|
|
**Nicht mehr prüfbar, weil bewusst geändert:** Der Plan verlangte „an eine
|
|
AD-Gruppe binden und Bindung lösen" sowie die AD-Suche bei gestoppter API. Beides
|
|
gibt es an dieser Stelle nicht mehr. Phase 16 hat den Anlegen-Dialog umgebaut: er
|
|
trägt jetzt den Hinweis „AD-Gruppen werden im LDAP-Bereich importiert, nicht hier
|
|
angelegt." samt Link dorthin. Die Prüfpunkte sind damit gegenstandslos, nicht
|
|
übersprungen.
|
|
|
|
**Kleiner Sprachbefund:** Der Löschdialog schreibt „1 Mitglieder" statt
|
|
„1 Mitglied" — Plural auch bei Eins.
|
|
|
|
## WINDOWS #2 — Freigaben-Matrix und Direkt-Grants (15-07) — BESTANDEN
|
|
|
|
| Schritt aus dem Plan | Beobachtung |
|
|
|---|---|
|
|
| Freigabe in der Matrix setzen | Checkbox für „Vertrieb Innendienst" gesetzt, Beschriftung wechselt von „freigeben" auf „entziehen" |
|
|
| Freigabe wieder entziehen und Wirkung gegenprüfen | Entzug für „Alle Benutzer" führte dazu, dass `nutzer2` den Zugriff sofort verlor — belegt über alle vier Ebenen unter #3 |
|
|
| Aktivierungsdialog, Weg „Sofort freigeben" | Cert Manager aktiviert; Grant an die Standardgruppe „Alle Benutzer" entstand (D-10) |
|
|
| Aktivierungsdialog, Weg „Später konfigurieren" | DKV-Rechnung aktiviert; **kein** Grant entstanden (0 Freigaben in der Datenbank) |
|
|
| Direkt-Grant neben Gruppen-Grant | Im Benutzer-Detail von `nutzer1` zeigt die Spalte „Über Gruppe(n)" beide freigebenden Gruppen an, während die Spalte „Direkt" unabhängig davon gesetzt werden kann |
|
|
| Matrix-Zelle bei gestoppter API | Fehlermeldung erscheint **und** die Checkbox springt in ihren alten Zustand zurück; die Datenbank zeigt danach unveränderte Freigaben — kein optimistischer Zustand überlebt den fehlgeschlagenen Request. Beleg: `uat-2026-09-07/w2-matrix-rollback-api-aus.png` |
|
|
| Direkt-Kästchen bei gestoppter API | Fehlermeldung im Dialog, Grant unverändert in der Datenbank |
|
|
| Sehr langer Gruppenname | Kopfzeile schneidet mit Ellipse ab („Abteilung Zentraler Einkauf und Vergabemanagement…"), Spaltenbreiten bleiben, die Seite scrollt nicht horizontal. Beleg: `uat-2026-09-07/w2-matrix-lange-namen.png` |
|
|
|
|
**Befunde ohne Blockerwirkung:**
|
|
|
|
- Die Fehlermeldung bei gestoppter API lautet in Matrix und Benutzer-Detail roh
|
|
„500: Internal Server Error". Der Löschdialog der Gruppenseite kann es besser
|
|
(deutscher Klartext) — die Behandlung ist also uneinheitlich.
|
|
- Wird eine Matrix-Seite bei bereits gestoppter API frisch geladen, meldet sie dem
|
|
Administrator „Zugriff verweigert" statt „Server nicht erreichbar". Das ist eine
|
|
irreführende Diagnose: der Administrator vermutet ein Rechteproblem statt eines
|
|
Serverausfalls.
|
|
- Der Aktivierungsdialog duzt („möchtest du die Freigaben separat konfigurieren?"),
|
|
während die übrige Oberfläche siezt.
|
|
- Das Deaktivieren eines Moduls entfernt seine Freigaben nicht. Beim
|
|
Wiederaktivieren sind die alten Freigaben sofort wieder wirksam. Das wirkt
|
|
gewollt, ist aber nirgends festgehalten.
|
|
|
|
## WINDOWS #3 — Sperrung ohne Freigabe über alle vier Ebenen (15-08) — DURCHGEFÜHRT, MIT BEFUND
|
|
|
|
Geprüft mit `nutzer2` (Rolle USER, Freigabe für Ausschreibungs-Radar entzogen)
|
|
gegen `nutzer1` (Freigabe über Gruppe) und `admin`.
|
|
|
|
| Ebene | Ergebnis |
|
|
|---|---|
|
|
| 1. Sidebar | Kategorie „procurement" fehlt für `nutzer2` vollständig; nur „security tools" (Cert Manager, dort freigegeben) erscheint ✓ |
|
|
| 2. Direkte URL `/modules/procurement/tender-radar` | 403-Seite „Kein Zugriff auf dieses Modul" mit Handlungsanweisung und Weg zurück ✓ (D-07) |
|
|
| 3. Marketplace | Karte trägt „Aktiviert" **und** das Sperr-Badge „Kein Zugriff", ist nicht anklickbar; der Klick löst den Toast „Kein Zugriff auf dieses Modul — wende dich an deinen Administrator." aus und navigiert **nicht** ✓ (D-08). Modul wird gekennzeichnet, nicht ausgeblendet |
|
|
| 4. API | `nutzer2` erhält auf `/modules/tender-radar` und allen geprüften Unterendpunkten (`saved-searches`, `rss-feeds`, `email-config`) durchgehend HTTP 403; `nutzer1` durchgehend 200 ✓ |
|
|
|
|
**Der Nachweis von PERM-04 gelingt damit auf drei von vier Ebenen nicht
|
|
vollständig — siehe WINDOWS #10.**
|
|
|
|
### WINDOWS #10 (neu) — der Zugriffs-Guard greift nicht auf modul-eigenen Routen
|
|
|
|
Ebene 2 ist nur für die generische Route abgesichert. Der Guard sitzt in
|
|
`modules/[category]/[moduleSlug]/page.tsx`. Vier Module haben daneben fest
|
|
verdrahtete eigene Routen:
|
|
|
|
```
|
|
apps/web/src/app/(portal)/modules/cert-manager/
|
|
apps/web/src/app/(portal)/modules/dkv-fleet/
|
|
apps/web/src/app/(portal)/modules/domaincheck/
|
|
apps/web/src/app/(portal)/modules/tender-radar/
|
|
```
|
|
|
|
Diese laufen am Guard vorbei. Im Browser als `nutzer2` **ohne** Freigabe gemessen:
|
|
|
|
| Adresse | Ergebnis |
|
|
|---|---|
|
|
| `/modules/procurement/tender-radar` | 403-Seite ✓ (generische Route, abgesichert) |
|
|
| `/modules/tender-radar` | **volle Seite** — Überschrift, Filter, Suchprofil-Formular, Trefferliste, Zahnrad-Link |
|
|
| `/modules/tender-radar/my-sources` | **volle Seite** — Postfach-Formular, Feed-Formular, Digest-Auswahl, alle Knöpfe bedienbar |
|
|
| `/modules/dkv-fleet` | **volle Seite** — inklusive Knopf „Jetzt pruefen" und Link zu den Moduleinstellungen |
|
|
|
|
**Es werden keine Daten preisgegeben.** Die API antwortet auf jedem Endpunkt mit
|
|
403, die Listen bleiben leer. Der Defekt liegt auf der Anzeigeebene:
|
|
|
|
1. Der Nutzer sieht eine Seite, die er nicht benutzen darf, statt der 403-Seite.
|
|
2. Die Bedienelemente sind anklickbar und laufen ins Leere — genau das, was
|
|
Plan 17-03 auf der Einstellungsseite des Ausschreibungs-Radars abgeschafft hat.
|
|
3. Statt einer verständlichen Meldung erscheinen rohe englische Techniktexte
|
|
mitten in der deutschen Oberfläche: „Module 'tender-radar' is not accessible
|
|
for this user", „Failed to fetch tenders", „Failed to fetch saved searches",
|
|
„Failed to fetch notification preference".
|
|
|
|
Beleg: `uat-2026-09-07/befund-modul-eigene-route-ohne-freigabe.png`
|
|
|
|
**Behoben am 2026-09-07** (Quick-Task `260907-e8k`, Commits `4a23e13`, `69b6418`).
|
|
Umgesetzt wurde nicht ein einzelnes Layout mit Pfadauflösung, sondern je ein `layout.tsx`
|
|
pro Modulverzeichnis mit fest eingetragenem Slug — ein Layout deckt in Next.js alle
|
|
verschachtelten Unterrouten automatisch mit ab, und der Slug steht damit explizit im Code
|
|
statt aus dem Pfad geraten zu werden. Das 403-Markup liegt jetzt einmal als gemeinsame
|
|
Komponente vor, die generische Route nutzt dieselbe. Ein Test liest das Modulverzeichnis
|
|
aus und verlangt für jedes nicht-dynamische Unterverzeichnis eine `layout.tsx`, damit ein
|
|
künftiges Modul die Lücke nicht erneut aufreißt.
|
|
|
|
### Gegenprobe im Browser nach dem Fix (2026-09-07)
|
|
|
|
Frisch gebautes Web-Image, echter Chrome, dieselben Konten:
|
|
|
|
| Konto | Adresse | Ergebnis |
|
|
|---|---|---|
|
|
| `admin` (SUPER_ADMIN) | `/modules/tender-radar`, `/modules/tender-radar/my-sources`, `/modules/dkv-fleet`, `/modules/procurement/tender-radar` | alle **unverändert offen** — die Sperre trifft niemanden zu viel |
|
|
| `nutzer1` (Freigabe über Gruppe) | `/modules/tender-radar/my-sources` | offen, alle drei Abschnitte da — Phase-17-Funktion unbeschädigt |
|
|
| `nutzer2` (keine Freigabe) | `/modules/tender-radar`, `/modules/tender-radar/my-sources`, `/modules/tender-radar/settings`, `/modules/dkv-fleet` | alle **gesperrt**, 403-Seite als Serverantwort |
|
|
| `nutzer2` auf `/modules/cert-manager` (dort **hat** er eine Freigabe) | | **offen** — die Gegenprobe gegen Überschießen |
|
|
|
|
Beleg: `uat-2026-09-07/w10-fix-my-sources-gesperrt.png`
|
|
|
|
**Messhinweis für spätere Prüfungen:** Ein erster Versuch, die Adressen per `fetch()` aus der
|
|
laufenden Seite heraus zu prüfen, meldete fälschlich *alle* Seiten als gesperrt — auch für den
|
|
Administrator. Der Aufruf führt die Sitzung nicht so mit, wie eine echte Navigation es tut. Die
|
|
Zahlen oben stammen ausschließlich aus echten Seitenaufrufen. Wer das nachprüft, sollte nicht
|
|
per `fetch` messen.
|
|
|
|
## Ergebnis
|
|
|
|
WINDOWS #1 und #2 sind geschlossen. #3 ist als Durchlauf erledigt. Der dabei gefundene
|
|
Defekt wurde als #10 erfasst, am selben Tag behoben und im Browser gegengeprüft — er ist
|
|
damit ebenfalls geschlossen.
|