instances added god may help
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Architektur
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22 (geprüft)
|
||||
|
||||
## 1) Zielbild
|
||||
|
||||
@@ -32,16 +32,18 @@ Ablauf pro Request:
|
||||
|
||||
## 3) Routing-Modell
|
||||
|
||||
- Route-Definitionen liegen in `/config/routes.php`.
|
||||
- Registrierung erfolgt in `/config/router.php`.
|
||||
- `public=true` in `routes.php` steuert, welche Pfade ohne Login erlaubt sind.
|
||||
- Route-Definitionen (Pfad-Aliase) liegen in `/config/routes.php`.
|
||||
- Registrierung erfolgt in `/config/router.php` (liest nur `path` und `target`; das `public`-Feld wird vom Router nicht ausgewertet).
|
||||
- Welche Pfade ohne Login erreichbar sind, steuert `lib/Http/AccessControl.php`:
|
||||
- Hartkodierte `ALWAYS_PUBLIC_PREFIXES` (z. B. `auth/microsoft/`, `api/`, `branding/`, `flash/`)
|
||||
- `APP_PUBLIC_PATHS`-Konstante (gesetzt in `config/config.php`)
|
||||
|
||||
MintyPHP-Konvention (Dateinamensrouting):
|
||||
|
||||
- `pages/admin/users/edit($id).php` erwartet URL-Parameter `id`
|
||||
- `pages/admin/users/data().php` für Datenendpunkte
|
||||
- `...(none).phtml` für responses ohne Template-Layout
|
||||
- Binarausgaben (z. B. Onboarding-PDF/ZIP) setzen `MINTY_ALLOW_OUTPUT` im Action-Endpoint.
|
||||
- Binärausgaben (z. B. Onboarding-PDF/ZIP) setzen `MINTY_ALLOW_OUTPUT` im Action-Endpoint.
|
||||
|
||||
## 4) Schichten und Verantwortungen
|
||||
|
||||
@@ -57,6 +59,15 @@ MintyPHP-Konvention (Dateinamensrouting):
|
||||
- Geschäftsregeln
|
||||
- Cross-Cutting-Logik (z. B. Auth, Settings, Branding)
|
||||
- Orchestrierung mehrerer Repositories
|
||||
- Scheduler/Lifecycle sind instanzbasiert über `lib/Service/Scheduler/SchedulerServicesFactory.php` verdrahtet.
|
||||
- Import/Import-Audit sind instanzbasiert über `lib/Service/Import/ImportServicesFactory.php` verdrahtet.
|
||||
- User-Domain ist instanzbasiert über `lib/Service/User/UserServicesFactory.php` verdrahtet
|
||||
(Services: `UserAccountService`, `UserAssignmentService`, `UserTenantContextService`, `UserPasswordService`;
|
||||
Repositories: `UserReadRepository`, `UserWriteRepository`, `UserListQueryRepository` + Assignment-Repositories).
|
||||
- Auth-/SSO-Domain ist instanzbasiert über `lib/Service/Auth/AuthServicesFactory.php` verdrahtet
|
||||
(u. a. `AuthService`, `RememberMeService`, `SsoUserLinkService`, `TenantSsoService`, `MicrosoftOidcService`).
|
||||
- Auth-Infra-Repositories (`ApiTokenRepository`, `RememberTokenRepository`, `PasswordResetRepository`,
|
||||
`EmailVerificationRepository`) werden ebenfalls instanzbasiert über die Factory injiziert.
|
||||
|
||||
### Repository-Layer (`/lib/Repository`)
|
||||
|
||||
@@ -180,8 +191,8 @@ So bleibt die Trennung stabil und Refactoring kontrollierbar.
|
||||
- `settings` (DB) ist die alleinige fachliche Quelle für globale Settings.
|
||||
- `config/settings.php` ist ein technischer Teil-Cache für sehr häufig gelesene UI-Basiswerte.
|
||||
- Zugriffsmuster:
|
||||
- `SettingService::get*` / `SettingService::set*` -> DB
|
||||
- `appSetting(...)` -> Datei-Cache (`SettingCacheService`)
|
||||
- `SettingGateway` (verdrahtet über `SettingServicesFactory`) -> `SettingService` -> DB
|
||||
- `appSetting(...)` -> `SettingServicesFactory` -> `SettingCacheService` (Datei-Cache)
|
||||
- Konsequenz:
|
||||
- Es ist korrekt, dass nicht alle DB-Settings im Datei-Cache stehen (z. B. SMTP/SSO/API-Details).
|
||||
- Der Cache muss nur die Keys enthalten, die im Runtime-Helper `appSetting(...)` verwendet werden.
|
||||
|
||||
78
docs/auth-sso-smoke-test.md
Normal file
78
docs/auth-sso-smoke-test.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Auth/SSO Smoke-Test
|
||||
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
Dieser Runbook prüft die 5 kritischen Flows nach Auth/SSO-Änderungen:
|
||||
- Login (Passwort)
|
||||
- Microsoft Start
|
||||
- Microsoft Callback
|
||||
- Tenant-SSO speichern
|
||||
- Logout
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Test-User ist aktiv und hat mindestens einen aktiven Tenant.
|
||||
- Es gibt einen Tenant mit Microsoft-SSO-Konfiguration.
|
||||
- Für Microsoft-Flow: gültige Tenant-SSO-Credentials vorhanden (Shared oder Override).
|
||||
- Testumgebung läuft und du bist als Admin eingeloggt.
|
||||
|
||||
## 1) Login (Passwort)
|
||||
|
||||
1. `login` aufrufen (optional `login?tenant=<slug>`).
|
||||
2. Gültige E-Mail + Passwort eingeben.
|
||||
3. Erwartung:
|
||||
- Login erfolgreich, Redirect auf `admin`.
|
||||
- Session enthält `user`, `available_tenants`, `current_tenant`.
|
||||
- Kein Fehler-Flash.
|
||||
|
||||
Negativtest:
|
||||
- Falsches Passwort -> generischer Fehler (kein Account-Leak), kein Login.
|
||||
|
||||
## 2) Microsoft Start (`auth/microsoft/start`)
|
||||
|
||||
1. `auth/microsoft/start?tenant=<slug>` aufrufen.
|
||||
2. Erwartung:
|
||||
- Bei gültigem Tenant + SSO-Config: Redirect zur Microsoft-Authorize-URL.
|
||||
- URL enthält `state`, `nonce`, PKCE (`code_challenge`).
|
||||
3. Negativtest:
|
||||
- Ungültiger Tenant-Slug -> Redirect auf `login` mit passendem Flash.
|
||||
- SSO deaktiviert/inkomplett -> Redirect zurück auf Tenant-Login mit passendem Flash.
|
||||
|
||||
## 3) Microsoft Callback (`auth/microsoft/callback`)
|
||||
|
||||
1. Erfolgreichen Callback durchlaufen lassen.
|
||||
2. Erwartung:
|
||||
- `state` wird einmalig konsumiert (kein Replay).
|
||||
- ID-Token-Prüfungen greifen (`aud`, `iss`, `tid`, `exp/nbf`, `nonce`, Signatur).
|
||||
- User wird verknüpft/provisioniert und auf `admin` weitergeleitet.
|
||||
|
||||
Negativtests:
|
||||
- Callback mit altem/wiederverwendetem `state` -> Login schlägt sauber fehl.
|
||||
- Callback ohne `code`/mit Fehler -> Redirect `login` mit Fehler-Flash.
|
||||
|
||||
## 4) Tenant-SSO speichern (Admin)
|
||||
|
||||
1. `admin/tenants/edit/<uuid>` öffnen, Tab `SSO`.
|
||||
2. Pflichtwerte setzen:
|
||||
- `Microsoft login` aktiv
|
||||
- `Entra tenant ID`
|
||||
- Shared App oder Override-Credentials vollständig
|
||||
3. Speichern.
|
||||
4. Erwartung:
|
||||
- Save erfolgreich.
|
||||
- UI-Status „Konfiguration vollständig“.
|
||||
- Bei `enforce_microsoft_login=1` und unvollständiger Config: Save wird blockiert.
|
||||
|
||||
## 5) Logout
|
||||
|
||||
1. Als eingeloggter User `logout` aufrufen.
|
||||
2. Erwartung:
|
||||
- Session beendet.
|
||||
- Remember-Me Token wird vergessen.
|
||||
- Redirect auf `login`.
|
||||
|
||||
## Schnellcheck (optional)
|
||||
|
||||
- In Browser A einloggen, dann in Browser B denselben User ändern (z. B. deaktivieren).
|
||||
- In Browser A nächste Anfrage auslösen.
|
||||
- Erwartung: bestehende Session-Refresh-Logik greift (ggf. Logout bei inaktiv/ohne Tenant).
|
||||
@@ -1,6 +1,6 @@
|
||||
# Benutzer-Lifecycle-Policy
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
## Ziel
|
||||
|
||||
@@ -45,6 +45,7 @@ Automatische Lifecycle-Aktionen ignorieren Benutzer mit mindestens einer aktiven
|
||||
|
||||
- Endpoint: `POST /admin/settings/run-user-lifecycle`
|
||||
- Schutz: Login + `settings.update` + CSRF
|
||||
- Verdrahtung: `SchedulerServicesFactory` erstellt `UserLifecycleService` instanzbasiert.
|
||||
|
||||
### Cron/CLI
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Einstellungen: Speicherung (DB + Cache)
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
## Kurzfassung
|
||||
|
||||
@@ -41,8 +41,8 @@ Daher ist es korrekt, wenn diese Werte in `settings` (DB) vorhanden sind, aber n
|
||||
## Laufzeitfluss
|
||||
|
||||
1. Admin speichert Settings in `admin/settings`.
|
||||
2. `SettingService::set*` schreibt in DB.
|
||||
3. `SettingCacheService::update(...)` aktualisiert den Datei-Cache nur für den definierten Teilbereich.
|
||||
2. `SettingGateway` (aus `SettingServicesFactory`) delegiert auf `SettingService`, der in DB schreibt.
|
||||
3. `SettingCacheService` aktualisiert den Datei-Cache nur für den definierten Teilbereich.
|
||||
4. UI-Helfer `appSetting(...)` liest danach aus Datei-Cache.
|
||||
|
||||
## Wenn DB und Datei scheinbar nicht zusammenpassen
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Leitfaden für die erste Änderung
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
## Ziel
|
||||
|
||||
@@ -11,7 +11,10 @@ Ein neuer Entwickler soll den ersten Change strukturiert und reproduzierbar umse
|
||||
### Schrittfolge
|
||||
|
||||
1. Data-Endpoint erweitern (z. B. `pages/admin/users/data().php`)
|
||||
2. Falls nötig: neue Repository-Query/Count-Methode (z. B. `lib/Repository/User/UserRepository.php`)
|
||||
2. Falls nötig: neue Repository-Methode ergänzen – je nach Typ:
|
||||
- Listenabfrage / Filterung / Paginierung → `lib/Repository/User/UserListQueryRepository.php`
|
||||
- Einzelnes Objekt lesen → `lib/Repository/User/UserReadRepository.php`
|
||||
- Schreiboperation → `lib/Repository/User/UserWriteRepository.php`
|
||||
3. Grid-Spalte in `pages/admin/<modul>/index(default).phtml` ergänzen (z. B. `pages/admin/users/index(default).phtml`)
|
||||
4. i18n-Key für Spaltennamen setzen
|
||||
5. `php -l` + manueller UI-Test
|
||||
|
||||
@@ -84,7 +84,7 @@ Unterstützte Typen:
|
||||
### Architektur-überblick
|
||||
|
||||
Jeder Job ist eine eigene Handler-Klasse, die `ScheduledJobHandlerInterface` implementiert.
|
||||
Die Registry ist eine reine Map von `job_key` zu Handler-Klasse – sie enthält keine
|
||||
Die Registry ist eine Map von `job_key` zu Handler-Instanz – sie enthält keine
|
||||
job-spezifische Logik.
|
||||
|
||||
```
|
||||
@@ -93,6 +93,7 @@ lib/Service/Scheduler/
|
||||
ScheduledJobHandlerInterface.php ← Vertrag für alle Handler
|
||||
UserLifecycleJobHandler.php ← Referenz-Implementierung
|
||||
ScheduledJobRegistry.php ← Handler-Map (einzige Datei die bei neuen Jobs angefasst wird)
|
||||
SchedulerServicesFactory.php ← verdrahtet Abhängigkeiten zentral
|
||||
```
|
||||
|
||||
### Schritt-für-Schritt
|
||||
@@ -110,7 +111,11 @@ use MintyPHP\Service\MeinBereich\MeinService;
|
||||
|
||||
class MeinJobHandler implements ScheduledJobHandlerInterface
|
||||
{
|
||||
public static function definition(): array
|
||||
public function __construct(private readonly MeinService $meinService)
|
||||
{
|
||||
}
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'label' => 'Mein Job',
|
||||
@@ -126,9 +131,9 @@ class MeinJobHandler implements ScheduledJobHandlerInterface
|
||||
];
|
||||
}
|
||||
|
||||
public static function execute(?int $actorUserId): array
|
||||
public function execute(?int $actorUserId): array
|
||||
{
|
||||
$result = MeinService::run($actorUserId);
|
||||
$result = $this->meinService->run($actorUserId);
|
||||
|
||||
if (!($result['ok'] ?? false)) {
|
||||
$errorCode = (string) ($result['error'] ?? 'job_failed');
|
||||
@@ -162,20 +167,22 @@ Datei: `lib/Service/Scheduler/ScheduledJobRegistry.php`
|
||||
// Konstante hinzufügen:
|
||||
public const MEIN_JOB = 'mein_job';
|
||||
|
||||
// In handlers() eine Zeile hinzufügen:
|
||||
private static function handlers(): array
|
||||
{
|
||||
return [
|
||||
self::USER_LIFECYCLE_RUN => UserLifecycleJobHandler::class,
|
||||
self::MEIN_JOB => MeinJobHandler::class, // ← neu
|
||||
];
|
||||
}
|
||||
// In __construct() eine Zeile hinzufügen:
|
||||
$this->handlers = [
|
||||
self::USER_LIFECYCLE_RUN => new UserLifecycleJobHandler($userLifecycleService),
|
||||
self::MEIN_JOB => new MeinJobHandler($meinService), // ← neu
|
||||
];
|
||||
```
|
||||
|
||||
**3. Fertig.**
|
||||
**3. Factory-Verdrahtung ergänzen**
|
||||
|
||||
Keine anderen Dateien müssen angefasst werden. `ensureSystemJobs()` legt den Job beim
|
||||
nächsten Scheduler-Aufruf automatisch in der Datenbank an.
|
||||
Datei: `lib/Service/Scheduler/SchedulerServicesFactory.php`
|
||||
|
||||
- `MeinService` instanziieren bzw. bereitstellen
|
||||
- beim Erzeugen von `ScheduledJobRegistry` den Service mit übergeben
|
||||
|
||||
Danach legt `ensureSystemJobs()` den Job beim nächsten Scheduler-Aufruf automatisch
|
||||
in der Datenbank an.
|
||||
|
||||
### Regeln für Handler
|
||||
|
||||
@@ -202,7 +209,8 @@ nächsten Scheduler-Aufruf automatisch in der Datenbank an.
|
||||
|
||||
`lib/Service/Scheduler/Handler/UserLifecycleJobHandler.php` ist die vollständige
|
||||
Referenz-Implementierung mit internem Service-Lock, Fehlerbehandlung und
|
||||
job-spezifischem `result`-Payload.
|
||||
job-spezifischem `result`-Payload. Der Objektgraph wird über
|
||||
`lib/Service/Scheduler/SchedulerServicesFactory.php` gebaut.
|
||||
|
||||
---
|
||||
|
||||
@@ -219,6 +227,6 @@ job-spezifischem `result`-Payload.
|
||||
- `lock_not_acquired`:
|
||||
- Ein anderer Runner läuft bereits.
|
||||
- Job bleibt auf `running`:
|
||||
- stale-running Schutz erlaubt nach 2 Stunden wieder neue Runs (Schwellwert in `ScheduledJobRepository::markRunning`).
|
||||
- stale-running Schutz erlaubt nach 2 Stunden wieder neue Runs (Schwellwert in `ScheduledJobRepository->markRunning`).
|
||||
- Kein fälliger Job:
|
||||
- `next_run_at`, `enabled`, `timezone` und schedule Konfiguration prüfen.
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
# Importe
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
Diese Seite beschreibt den V1 CSV-Import unter `/admin/imports`.
|
||||
|
||||
## Technischer Aufbau
|
||||
|
||||
- Das Import-Modul ist instanzbasiert über `lib/Service/Import/ImportServicesFactory.php` verdrahtet.
|
||||
- `ImportService` orchestriert Analyze/Preview/Commit.
|
||||
- `ImportStateStoreService` kapselt den tokenbasierten Session-State (`admin_imports_v1`, TTL 2h).
|
||||
- `CsvReaderService` und `ImportTempFileService` sind eigene Instanzservices.
|
||||
- Import-Audit läuft über `ImportAuditService` + `ImportAuditRunRepository`.
|
||||
|
||||
## Scope (V1)
|
||||
|
||||
- Profile: `users`, `departments`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Dokumentation
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
Diese Dokumente sind für Entwickler gedacht, die die Anwendung warten oder erweitern.
|
||||
|
||||
@@ -63,6 +63,8 @@ Diese Dokumente sind für Entwickler gedacht, die die Anwendung warten oder erwe
|
||||
- Alle ENV-Variablen mit Beschreibung, Standardwerten und Produktions-Checkliste.
|
||||
- `/docs/fehlerbehebung.md`
|
||||
- Häufige Fehlerbilder und schnelle Lösungen.
|
||||
- `/docs/auth-sso-smoke-test.md`
|
||||
- Manueller Smoke-Runbook für Login, Microsoft-Start/Callback, Tenant-SSO-Save und Logout.
|
||||
- `/docs/docker-lokal.md`
|
||||
- Schneller lokaler Docker-Start inkl. typischer Befehle und Troubleshooting.
|
||||
- `/docs/docker-produktiv.md`
|
||||
|
||||
@@ -25,6 +25,8 @@ Diese Regeln sind projektweit verbindlich, um Lesbarkeit und Wartbarkeit stabil
|
||||
- Keine HTML-Ausgabe.
|
||||
- Keine direkten View-Annahmen.
|
||||
- Bei globalen Settings bleibt DB die Quelle (`SettingService`); Datei-Cache nur gezielt für `appSetting(...)`.
|
||||
- Für neue oder refaktorierte Domain-Module Instanz-Services + Factory verwenden (z. B. `...ServicesFactory`) statt statischer Domain-Methoden.
|
||||
- Keine domain-spezifischen Service-Locator-Helper in `lib/Support/helpers/app.php`; Composition per Factory im Aufrufer.
|
||||
|
||||
### Action (`pages/**.php`)
|
||||
|
||||
@@ -121,6 +123,7 @@ Ausführen bei: Feature-Entfernung, größerem Refactoring oder vor Releases. Pa
|
||||
## 8) Settings-Konvention
|
||||
|
||||
- Neue Settings immer zuerst sauber im `SettingService` modellieren (Validierung + Read/Write).
|
||||
- Nur dann in `SettingCacheService::update(...)` aufnehmen, wenn der Key wirklich über `appSetting(...)` im Hot Path genutzt wird.
|
||||
- Aufrufer nutzen `SettingGateway` aus `SettingServicesFactory`; kein globaler `settingGateway()`-Helper.
|
||||
- Nur dann in den `SettingCacheService` aufnehmen, wenn der Key wirklich über `appSetting(...)` im Hot Path genutzt wird.
|
||||
- Keine Sicherheits-/Integrationssettings (SMTP, SSO-Secrets, API-Policies) als Pflicht in den Datei-Cache drücken.
|
||||
- Bei manuellen DB-Änderungen an gecachten Keys den Cache gezielt aktualisieren (z. B. über Settings-Save-Flow).
|
||||
|
||||
@@ -10,6 +10,8 @@ servers:
|
||||
security:
|
||||
- BearerAuth: []
|
||||
tags:
|
||||
- name: auth
|
||||
description: Public authentication endpoints (no Bearer token required)
|
||||
- name: me
|
||||
- name: tokens
|
||||
- name: users
|
||||
@@ -17,6 +19,60 @@ tags:
|
||||
- name: departments
|
||||
- name: roles
|
||||
paths:
|
||||
/auth/login:
|
||||
post:
|
||||
tags: [auth]
|
||||
summary: Login with email and password
|
||||
description: |
|
||||
Authenticates a user with email and password and returns a Bearer token.
|
||||
This endpoint is **public** — no Authorization header required.
|
||||
|
||||
The returned token can be used immediately as `Authorization: Bearer <token>`
|
||||
for all subsequent API requests.
|
||||
|
||||
Rate limits (stricter than general API limits):
|
||||
- 10 failed attempts per IP per 10 minutes
|
||||
- 5 failed attempts per email+IP per 15 minutes
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginRequest'
|
||||
example:
|
||||
email: user@example.com
|
||||
password: "..."
|
||||
token_name: "My App"
|
||||
responses:
|
||||
'201':
|
||||
description: Login successful — token issued
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginResponse'
|
||||
'401':
|
||||
description: Authentication failed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
examples:
|
||||
invalid_credentials:
|
||||
value:
|
||||
error: invalid_credentials
|
||||
account_inactive:
|
||||
value:
|
||||
error: account_inactive
|
||||
'403':
|
||||
$ref: '#/components/responses/Forbidden'
|
||||
'409':
|
||||
$ref: '#/components/responses/Conflict'
|
||||
'422':
|
||||
$ref: '#/components/responses/ValidationError'
|
||||
'429':
|
||||
$ref: '#/components/responses/RateLimited'
|
||||
|
||||
/me:
|
||||
get:
|
||||
tags: [me]
|
||||
@@ -833,6 +889,47 @@ components:
|
||||
data:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
LoginRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [email, password]
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: User email address (case-insensitive)
|
||||
password:
|
||||
type: string
|
||||
description: User password
|
||||
token_name:
|
||||
type: string
|
||||
description: Optional label for the issued token (e.g. "iPhone App"). Defaults to "Login".
|
||||
default: Login
|
||||
tenant_uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Optional — scope the issued token to a specific tenant UUID. Must be assigned to the user.
|
||||
LoginResponse:
|
||||
type: object
|
||||
required: [data]
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
required: [token, token_uuid, expires_at]
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
description: Full Bearer token in format `selector:plaintext`. Shown only once — store securely.
|
||||
example: "abc123def:456789..."
|
||||
token_uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the created token record (use for revocation via /me/tokens)
|
||||
expires_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: UTC expiry timestamp of the token
|
||||
RoleWriteRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sicherheitsmodell
|
||||
|
||||
Letzte Aktualisierung: 2026-02-21
|
||||
Letzte Aktualisierung: 2026-02-22
|
||||
|
||||
## 1) Grundprinzip
|
||||
|
||||
@@ -21,6 +21,8 @@ Kein einzelner Layer ist ausreichend; die Kombination ist der Schutz.
|
||||
- Auto-Login aus Cookie erfolgt früh in `/web/index.php`.
|
||||
- Zentraler Login-Entry ist `login` (optional `login?tenant=<slug>` für Tenant-Vorauswahl).
|
||||
- Unknown-Email-Verhalten im Login bleibt generisch (keine Tenant-/Account-Details vor erfolgreicher Auflösung).
|
||||
- Auth-/SSO-Kern ist instanzbasiert verdrahtet über `lib/Service/Auth/AuthServicesFactory.php`
|
||||
(`AuthService`, `RememberMeService`, `SsoUserLinkService`, `TenantSsoService`, `MicrosoftOidcService`).
|
||||
|
||||
Kritisch:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user