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") } }) }