package notifyprefs import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "gitea.perlbach24.de/scripte/nexarch/internal/auth" ) func sessionCookie(t *testing.T, issuer *auth.TokenIssuer, userID, tenantSlug string) *http.Cookie { t.Helper() token, err := issuer.Issue(userID, tenantSlug) if err != nil { t.Fatalf("session-token ausstellen: %v", err) } return &http.Cookie{Name: auth.CookieName, Value: token} } // Akzeptanzkriterium 1: Benutzer setzt eigene Praeferenz per HTTP. func TestHandlerSetAndListMine(t *testing.T) { prefs, _, _, cleanup := setupTest(t) defer cleanup() h := NewHandler(prefs) issuer := auth.NewTokenIssuer("test-secret") cookie := sessionCookie(t, issuer, "user-1", "acme") setBody, _ := json.Marshal(setPreferenceRequest{EventType: "welcome", Channel: "email", Enabled: false}) setReq := httptest.NewRequest(http.MethodPost, "/notifications/preferences", bytes.NewReader(setBody)) setReq.AddCookie(cookie) setRec := httptest.NewRecorder() auth.RequireAuth(issuer, h.SetPreference)(setRec, setReq) if setRec.Code != http.StatusOK { t.Fatalf("set: status = %d, body: %s", setRec.Code, setRec.Body.String()) } listReq := httptest.NewRequest(http.MethodGet, "/notifications/preferences", nil) listReq.AddCookie(cookie) listRec := httptest.NewRecorder() auth.RequireAuth(issuer, h.ListMine)(listRec, listReq) if listRec.Code != http.StatusOK { t.Fatalf("list: status = %d, body: %s", listRec.Code, listRec.Body.String()) } var out []Preference if err := json.Unmarshal(listRec.Body.Bytes(), &out); err != nil { t.Fatalf("response dekodieren: %v", err) } if len(out) != 1 || out[0].Enabled { t.Fatalf("erwartet genau 1 deaktivierte praeferenz, habe %+v", out) } } // Akzeptanzkriterium 1 / Pruefung 2: ListMine zeigt AUSSCHLIESSLICH die // eigenen Praeferenzen — die UserID kommt aus dem Session-Token, nicht aus // einem vom Client kontrollierbaren Parameter. func TestHandlerListMine_NeverShowsOtherUsersPreferences(t *testing.T) { prefs, _, _, cleanup := setupTest(t) defer cleanup() h := NewHandler(prefs) issuer := auth.NewTokenIssuer("test-secret") setBody, _ := json.Marshal(setPreferenceRequest{EventType: "welcome", Channel: "email", Enabled: false}) setReq := httptest.NewRequest(http.MethodPost, "/notifications/preferences", bytes.NewReader(setBody)) setReq.AddCookie(sessionCookie(t, issuer, "user-1", "acme")) setRec := httptest.NewRecorder() auth.RequireAuth(issuer, h.SetPreference)(setRec, setReq) if setRec.Code != http.StatusOK { t.Fatalf("set fuer user-1: status = %d", setRec.Code) } // user-2 fragt seine eigenen Praeferenzen ab — muss leer sein. listReq := httptest.NewRequest(http.MethodGet, "/notifications/preferences", nil) listReq.AddCookie(sessionCookie(t, issuer, "user-2", "acme")) listRec := httptest.NewRecorder() auth.RequireAuth(issuer, h.ListMine)(listRec, listReq) if listRec.Code != http.StatusOK { t.Fatalf("list fuer user-2: status = %d", listRec.Code) } var out []Preference if err := json.Unmarshal(listRec.Body.Bytes(), &out); err != nil { t.Fatalf("response dekodieren: %v", err) } if len(out) != 0 { t.Fatalf("user-2 haette user-1s praeferenzen NICHT sehen duerfen, habe %+v", out) } } // Akzeptanzkriterium 3: Tenant-Übersicht liefert alle Benutzer des Mandanten. func TestHandlerListTenantOverview(t *testing.T) { prefs, _, _, cleanup := setupTest(t) defer cleanup() h := NewHandler(prefs) issuer := auth.NewTokenIssuer("test-secret") for _, u := range []string{"user-1", "user-2"} { body, _ := json.Marshal(setPreferenceRequest{EventType: "welcome", Channel: "email", Enabled: false}) req := httptest.NewRequest(http.MethodPost, "/notifications/preferences", bytes.NewReader(body)) req.AddCookie(sessionCookie(t, issuer, u, "acme")) rec := httptest.NewRecorder() auth.RequireAuth(issuer, h.SetPreference)(rec, req) if rec.Code != http.StatusOK { t.Fatalf("set fuer %s: status = %d", u, rec.Code) } } req := httptest.NewRequest(http.MethodGet, "/notifications/preferences/tenant", nil) req.AddCookie(sessionCookie(t, issuer, "admin-1", "acme")) rec := httptest.NewRecorder() auth.RequireAuth(issuer, h.ListTenantOverview)(rec, req) if rec.Code != http.StatusOK { t.Fatalf("overview: status = %d, body: %s", rec.Code, rec.Body.String()) } var out []Preference if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil { t.Fatalf("response dekodieren: %v", err) } if len(out) != 2 { t.Fatalf("erwartet 2 eintraege (beide Benutzer), habe %d", len(out)) } }