package auth import ( "context" "net/http" "net/http/httptest" "strings" "testing" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" ) // injectUser returns a copy of r with the given user stored under userCtxKey. // This mirrors what RequireUser does at runtime. func injectUser(r *http.Request, u dbq.User) *http.Request { ctx := context.WithValue(r.Context(), userCtxKey, u) return r.WithContext(ctx) } func TestRequireAdmin_AdminPasses(t *testing.T) { called := false stub := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { called = true w.WriteHeader(http.StatusOK) }) h := RequireAdmin()(stub) req := injectUser( httptest.NewRequest(http.MethodGet, "/api/admin/test", nil), dbq.User{IsAdmin: true}, ) w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Errorf("status = %d, want 200", w.Code) } if !called { t.Error("stub handler was not called for admin user") } } func TestRequireAdmin_NonAdminReturns403(t *testing.T) { stub := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { t.Fatal("stub handler must not be called for non-admin user") }) h := RequireAdmin()(stub) req := injectUser( httptest.NewRequest(http.MethodGet, "/api/admin/test", nil), dbq.User{IsAdmin: false}, ) w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusForbidden { t.Errorf("status = %d, want 403", w.Code) } body := w.Body.String() if !strings.Contains(body, "not_authorized") { t.Errorf("body %q does not contain %q", body, "not_authorized") } ct := w.Header().Get("Content-Type") if !strings.HasPrefix(ct, "application/json") { t.Errorf("Content-Type = %q, want application/json", ct) } } func TestRequireAdmin_NoUserContextReturns500(t *testing.T) { stub := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { t.Fatal("stub handler must not be called when no user is in context") }) h := RequireAdmin()(stub) // Do NOT inject a user — simulate RequireUser being bypassed. req := httptest.NewRequest(http.MethodGet, "/api/admin/test", nil) w := httptest.NewRecorder() h.ServeHTTP(w, req) if w.Code != http.StatusInternalServerError { t.Errorf("status = %d, want 500", w.Code) } body := w.Body.String() if !strings.Contains(body, "internal_error") { t.Errorf("body %q does not contain %q", body, "internal_error") } ct := w.Header().Get("Content-Type") if !strings.HasPrefix(ct, "application/json") { t.Errorf("Content-Type = %q, want application/json", ct) } }