Files
HoneyandClaude Opus 5 31a027c93a feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA.
Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb,
Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming,
Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office
(Collabora/OnlyOffice).

Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort)
sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:25:36 +02:00

91 lines
2.6 KiB
Go
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.
package auth
import (
"context"
"os"
"testing"
"github.com/jackc/pgx/v5/pgxpool"
)
// Prüft den Fall, der beim Einschalten von OIDC über eine bestehende
// Installation entscheidet: Wird das vorhandene Konto verbunden – oder entsteht
// daneben ein zweites, leeres?
//
// Läuft nur mit TEST_DSN gegen eine echte Datenbank; ohne wird übersprungen,
// damit `go test ./...` überall grün bleibt.
func TestGetOrCreateByOIDC_Linking(t *testing.T) {
dsn := os.Getenv("TEST_DSN")
if dsn == "" {
t.Skip("TEST_DSN nicht gesetzt")
}
ctx := context.Background()
pool, err := pgxpool.New(ctx, dsn)
if err != nil {
t.Fatalf("verbinden: %v", err)
}
defer pool.Close()
s := NewStore(pool)
// Aufräumen, auch wenn der Test scheitert.
cleanup := func() {
_, _ = pool.Exec(ctx, `DELETE FROM users WHERE username LIKE 'linkprobe%'`)
}
cleanup()
defer cleanup()
hash, _ := HashPassword("irrelevant-aber-gueltig")
if _, err := pool.Exec(ctx,
`INSERT INTO users (username, display_name, password, is_admin)
VALUES ('linkprobe', 'Link Probe', $1, true)`, hash); err != nil {
t.Fatalf("konto anlegen: %v", err)
}
t.Run("ohne Verknüpfung entsteht ein zweites Konto", func(t *testing.T) {
u, err := s.GetOrCreateByOIDC(ctx, "sub-A", "linkprobe", "Link Probe", false)
if err != nil {
t.Fatalf("aufruf: %v", err)
}
if u.Username == "linkprobe" {
t.Fatal("erwartet: ein neues Konto mit abgewandeltem Namen")
}
if u.IsAdmin {
t.Error("ein neu angelegtes Konto darf keine Adminrechte erben")
}
_, _ = pool.Exec(ctx, `DELETE FROM users WHERE oidc_sub = 'sub-A'`)
})
t.Run("mit Verknüpfung bleibt das bestehende Konto", func(t *testing.T) {
u, err := s.GetOrCreateByOIDC(ctx, "sub-B", "linkprobe", "Link Probe", true)
if err != nil {
t.Fatalf("aufruf: %v", err)
}
if u.Username != "linkprobe" {
t.Fatalf("erwartet linkprobe, bekam %q", u.Username)
}
if !u.IsAdmin {
t.Error("Adminrecht des bestehenden Kontos ging verloren")
}
if !u.IsOIDC {
t.Error("Konto sollte jetzt als OIDC-Konto gelten")
}
})
t.Run("erneutes Anmelden findet dasselbe Konto", func(t *testing.T) {
u, err := s.GetOrCreateByOIDC(ctx, "sub-B", "linkprobe", "Link Probe", true)
if err != nil || u.Username != "linkprobe" {
t.Fatalf("wiederholte Anmeldung: %v / %+v", err, u)
}
})
t.Run("fremde Identität übernimmt ein gebundenes Konto nicht", func(t *testing.T) {
u, err := s.GetOrCreateByOIDC(ctx, "sub-FREMD", "linkprobe", "Angreifer", true)
if err != nil {
t.Fatalf("aufruf: %v", err)
}
if u.Username == "linkprobe" {
t.Fatal("ein bereits gebundenes Konto wurde übernommen – das darf nie passieren")
}
})
}