diff --git a/.env.example b/.env.example index f203d13..331a42b 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,8 @@ # Aether – das Nötigste für eine neue Umgebung. cp .env.example .env +# +# Zwei Fallen beim Bearbeiten: +# $ im Wert → als $$ schreiben, sonst schneidet Compose ab +# Kommentar hinter einem LEEREN Wert → der Kommentar wird zum Wert # Erklärungen: README.md, Abschnitt „Einstellungen" # Alle Schalter: deploy/.env.example @@ -44,9 +48,13 @@ ADMIN_USERNAME=admin ADMIN_PASSWORD= # ── Anmeldung über einen Identitätsanbieter (optional) ─────────────────────── -# Leerer OIDC_ISSUER = aus. Sonst die vollständige Adresse des Anbieters – -# nicht seinen Namen. Falsch gesetzt bricht der Start ab. -OIDC_ISSUER= # z. B. https://id.example.com +# Leerer OIDC_ISSUER = aus. Sonst die vollständige Adresse des Anbieters, +# z. B. https://id.example.com – nicht seinen Namen. Falsch gesetzt bricht +# der Start ab. +# +# Kommentar NIE hinter einen leeren Wert setzen: `OIDC_ISSUER= # text` macht +# den Text zum Wert. Hinter einem gefüllten Wert ist er dagegen harmlos. +OIDC_ISSUER= OIDC_CLIENT_ID=aether OIDC_CLIENT_SECRET= # Muss exakt /api/v1/auth/oidc/callback sein. @@ -54,6 +62,8 @@ OIDC_REDIRECT_URL=https://cloud.example.com/api/v1/auth/oidc/callback # Bestehendes Konto verbinden statt ein zweites anzulegen. # VOR der ersten Anmeldung setzen – danach ist es zu spät. OIDC_LINK_BY_USERNAME=false +# Beschriftung des Knopfes auf der Anmeldeseite. +OIDC_BUTTON_LABEL=Sign in with SSO / OIDC # ── Office (optional) ───────────────────────────────────────────────────────── # Leer = aus, auch wenn ein Office-Container läuft. diff --git a/README.md b/README.md index de97b26..4584857 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,10 @@ und Audit-Log werden damit wertlos, ohne dass irgendetwas nach Fehler aussieht. **`ADMIN_PASSWORD`** legt beim allerersten Start den Admin an. Danach leeren: Das Konto bleibt, das Passwort stünde sonst dauerhaft in einer Datei. +**`OIDC_BUTTON_LABEL`** beschriftet den Knopf auf der Anmeldeseite +(Vorgabe „Sign in with SSO / OIDC"). „Anmelden mit PocketID" sagt dem, der +davorsteht, mehr als eine Abkürzung, die man kennen muss. + **`OIDC_LINK_BY_USERNAME`** verbindet ein bestehendes Konto mit derselben Kennung, statt ein zweites anzulegen. **Vor der ersten Anmeldung setzen** – danach existiert das zweite Konto (`marc2`, leer, ohne Adminrecht) schon, und @@ -223,6 +227,26 @@ Kleiner als 1 wird verworfen: Die Zahl geht als `OFFSET` in die Aufräumabfrage, und `OFFSET 0` löschte jede Fassung – aus „keine Grenze" würde „kein Verlauf". Wer keinen Verlauf will, lässt den Schalter an der Datei aus. +**Ausschalten löscht nichts.** Der Schalter setzt nur ein Flag: Ab dann +entstehen keine neuen Fassungen mehr, die vorhandenen bleiben liegen – mitsamt +ihrem Platz im Kontingent. Das ist Absicht, ein Umschalter soll keine Daten +vernichten. Es heißt aber auch, dass belegter Platz übrig bleibt, den man nur +im Verlaufs-Dialog sieht. + +Endgültig weg sind sie erst, wenn die **Datei selbst** verschwindet, und zwar +richtig: Der Papierkorb genügt nicht – dort liegen Datei und Fassungen weiter. +Beim **Leeren des Papierkorbs** wird die Zeile gelöscht, `ON DELETE CASCADE` +nimmt die Fassungen mit, und die Blobs verschwinden sofort von der Platte. + +Gemessen an einer Datei mit drei Fassungen: + +| Schritt | Fassungen | Blobs | +|---|---|---| +| Versionierung an, dreimal überschrieben | 3 | 4 | +| Versionierung **aus**geschaltet | 3 | 4 | +| in den Papierkorb gelegt | 3 | 4 | +| Papierkorb geleert | – | 0 | + Zu beachten: **Jedes Strg+S in Office legt eine Fassung an.** Beim Testen sprang eine Datei dadurch von v1 auf v3, nicht auf v2. diff --git a/TESTING.md b/TESTING.md index d148528..e1de044 100644 --- a/TESTING.md +++ b/TESTING.md @@ -706,6 +706,63 @@ ist die falsche – die Schnipsel haben deshalb **kein** Profil mehr. --- +## Kommentar hinter leerem Wert in der .env (24.08.2026) + +Beim Testen selbst gebaut und sofort wieder eingefangen. In einer `.env` gilt: + +``` +A=production # kommentar → production ✓ +C=production#kommentar → production#kommentar +F= # kommentar → "# kommentar" ✗ +``` + +Hinter einem **gefüllten** Wert ist ein Kommentar harmlos. Hinter einem +**leeren** wird er zum Wert. `OIDC_ISSUER= # z. B. https://…` startete damit +den OIDC-Aufbau mit dem Kommentartext als Adresse – und weil ein Fehlschlag +dort den Start abbricht, kam die Cloud nicht hoch. + +In `deploy/.env.example` steckten vier weitere solche Zeilen, darunter +`OFFICE_PROVIDER= # collabora | onlyoffice`: Office wäre mit Unsinn als +Anbieter eingeschaltet worden. Alle vier umgestellt, der Kommentar steht jetzt +darüber. + +- [ ] `grep -nE '^[A-Z_]+=[[:space:]]*#' .env.example deploy/.env.example` + liefert nichts 🔎 +- [ ] Frische Instanz allein aus den Beispieldateien startet 🔎 + +--- + +## Beschriftung des SSO-Knopfes (24.08.2026) + +`OIDC_BUTTON_LABEL`, Vorgabe „Sign in with SSO / OIDC". + +- [ ] Gesetzt → der Knopf auf der Anmeldeseite trägt den Text +- [ ] Nicht gesetzt → die Vorgabe +- [ ] OIDC aus → `/public/config` liefert einen **leeren** Wert 🔎 (die + Einstellung geht niemanden etwas an, solange es keinen Knopf gibt) + +--- + +## Versionen: was beim Ausschalten passiert (24.08.2026) + +Der Schalter „Keep versions" setzt nur ein Flag. Vorhandene Fassungen bleiben +liegen – mitsamt ihrem Platz im Kontingent. Gemessen an einer Datei mit drei +Fassungen: + +| Schritt | Fassungen | Blobs | +|---|---|---| +| dreimal überschrieben | 3 | 4 | +| Versionierung ausgeschaltet | 3 | 4 | +| in den Papierkorb | 3 | 4 | +| Papierkorb geleert | – | 0 | + +- [ ] Ausschalten löscht nichts 🔎 +- [ ] Der Papierkorb genügt nicht – dort bleibt alles 🔎 +- [ ] Leeren des Papierkorbs entfernt Fassungen **und** Blobs sofort 🔎 + (nicht erst beim nächsten GC) + +--- + ## Anzahl aufgehobener Fassungen (24.08.2026) `MAX_VERSIONS_KEPT`, Vorgabe 5. Vorher eine Konstante – und zwar **zwei**: diff --git a/backend/cmd/aether/main.go b/backend/cmd/aether/main.go index 95b6883..c02a65c 100644 --- a/backend/cmd/aether/main.go +++ b/backend/cmd/aether/main.go @@ -346,6 +346,10 @@ func main() { // Public config (no auth) – used by login page to discover OIDC availability r.Get("/api/v1/public/config", func(w http.ResponseWriter, r *http.Request) { cloudName := "Aether" + oidcLabel := "" + if oidcHandler.IsEnabled() { + oidcLabel = cfg.OIDCButtonLabel + } // Farben gehören hierher (statt hinter die Auth), damit schon die // Login-Seite im eingestellten Farbschema erscheint. var primaryColor, accentColor, logoURL, faviconURL, appleTouchURL string @@ -381,6 +385,10 @@ func main() { // anwendet. Vorher stand sie zweimal im Quelltext, mit einem // Kommentar „muss zusammenpassen" – das ist keine Zusicherung. "max_versions_kept": cfg.MaxVersionsKept, + // Beschriftung des SSO-Knopfes. Nur mitgeschickt, wenn OIDC an + // ist – sonst gibt der Endpunkt eine Einstellung preis, die + // niemanden etwas angeht. + "oidc_button_label": oidcLabel, }) }) diff --git a/backend/pkg/config/config.go b/backend/pkg/config/config.go index 098ed36..4135dd5 100644 --- a/backend/pkg/config/config.go +++ b/backend/pkg/config/config.go @@ -22,6 +22,10 @@ type Config struct { // MaxVersionsKept: Wie viele frühere Fassungen einer Datei aufgehoben // werden, wenn die Versionierung für sie eingeschaltet ist. MaxVersionsKept int + // OIDCButtonLabel steht auf dem Knopf der Anmeldeseite. Der Anbieter hat + // bei jedem einen anderen Namen – „Sign in with SSO / OIDC" sagt dem + // Nutzer weniger als „Anmelden mit PocketID". + OIDCButtonLabel string DBPort string DBName string DBUser string @@ -156,6 +160,7 @@ func Load() (*Config, error) { DBHost: getEnv("DB_HOST", "localhost"), MaxVersionsKept: getEnvInt("MAX_VERSIONS_KEPT", 5), + OIDCButtonLabel: getEnv("OIDC_BUTTON_LABEL", "Sign in with SSO / OIDC"), DBPort: getEnv("DB_PORT", "5432"), DBName: getEnv("DB_NAME", "aether"), DBUser: getEnv("DB_USER", "aether"), diff --git a/deploy/.env.example b/deploy/.env.example index 1c81c32..9f6004a 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -1,4 +1,8 @@ # Aether – alle Schalter. cp deploy/.env.example deploy/.env +# +# Zwei Fallen beim Bearbeiten: +# $ im Wert → als $$ schreiben, sonst schneidet Compose ab +# Kommentar hinter einem LEEREN Wert → der Kommentar wird zum Wert # Erklärungen und Fallstricke: README.md, Abschnitt „Einstellungen" # # Für den reinen Betrieb genügt die kürzere .env.example im @@ -57,6 +61,8 @@ ADMIN_PASSWORD=changeme_strong_admin_password # Bestehendes Konto verbinden statt ein zweites anzulegen. # VOR der ersten Anmeldung setzen – danach ist es zu spät. # OIDC_LINK_BY_USERNAME=true +# Beschriftung des Knopfes auf der Anmeldeseite. +# OIDC_BUTTON_LABEL=Anmelden mit PocketID # ── Volltextsuche (OCR) ─────────────────────────────────────────────────────── # Standardmäßig an; fehlen ocrmypdf/tesseract, schaltet es sich selbst ab. @@ -72,15 +78,19 @@ EXTERNAL_APPS= # ── Office (optional) ───────────────────────────────────────────────────────── # Leer = aus, auch wenn ein Office-Container läuft. Schnipsel: README.md -OFFICE_PROVIDER= # collabora | onlyoffice (auch Euro-Office) +# collabora | onlyoffice (auch Euro-Office) +OFFICE_PROVIDER= # Backend → Office. Collabora lauscht auf 9980, OnlyOffice/Euro-Office auf 80. OFFICE_URL= -OFFICE_PUBLIC_URL= # Browser → Office; leer = wie OFFICE_URL +# Browser → Office; leer = wie OFFICE_URL +OFFICE_PUBLIC_URL= # Office → Aether; leer = PUBLIC_URL. # Weder localhost noch der veröffentlichte Port – beides scheitert. OFFICE_WOPI_URL= -OFFICE_ALLOWED_HOSTS= # gegen SSRF; Host aus OFFICE_URL zählt immer -OFFICE_JWT_SECRET= # nur OnlyOffice/Euro-Office, mind. 32 Zeichen +# Gegen SSRF; der Host aus OFFICE_URL zählt immer dazu. +OFFICE_ALLOWED_HOSTS= +# Nur OnlyOffice/Euro-Office, mind. 32 Zeichen. +OFFICE_JWT_SECRET= OFFICE_INSECURE_TLS=false # nur für Tests mit selbstsigniertem Zertifikat # Nur für den Collabora-Container aus deploy/docker-compose.yml: diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index c7e3b13..54ab5dd 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -214,6 +214,8 @@ export interface PublicConfig { office_enabled?: boolean /** Wie viele frühere Fassungen der Server aufhebt (MAX_VERSIONS_KEPT). */ max_versions_kept?: number + /** Beschriftung des SSO-Knopfes (OIDC_BUTTON_LABEL). Leer, wenn OIDC aus ist. */ + oidc_button_label?: string primary_color?: string accent_color?: string external_apps: ExternalApp[] diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx index 3300a83..d8d5862 100644 --- a/frontend/src/pages/LoginPage.tsx +++ b/frontend/src/pages/LoginPage.tsx @@ -80,7 +80,9 @@ export default function LoginPage({ onLogin }: Props) { - Sign in with SSO / OIDC + {/* Der Anbieter heißt bei jedem anders. „Anmelden mit PocketID" + sagt mehr als eine Abkürzung, die man kennen muss. */} + {config.oidc_button_label || 'Sign in with SSO / OIDC'} )}