package httpapi import ( "context" "errors" "net/http" "net/http/httptest" "testing" fbauth "firebase.google.com/go/v4/auth" "github.com/gin-gonic/gin" ) type fakeVerifier struct { token *fbauth.Token err error } func (f fakeVerifier) Verify(_ context.Context, _ string) (*fbauth.Token, error) { return f.token, f.err } func TestAuthMiddleware_MissingHeader(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(AuthMiddleware(fakeVerifier{})) r.GET("/", func(c *gin.Context) {}) req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected status %d, got %d", http.StatusUnauthorized, w.Code) } } func TestAuthMiddleware_InvalidToken(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(AuthMiddleware(fakeVerifier{err: errors.New("boom")})) r.GET("/", func(c *gin.Context) {}) req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Set("Authorization", "Bearer invalid") w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected status %d, got %d", http.StatusUnauthorized, w.Code) } } func TestAuthMiddleware_Success(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(AuthMiddleware(fakeVerifier{token: &fbauth.Token{UID: "user-123"}})) r.GET("/", func(c *gin.Context) { c.Status(http.StatusOK) }) req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Set("Authorization", "Bearer validtoken") w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status %d, got %d", http.StatusOK, w.Code) } } func TestAdminOnly_MissingToken(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(AdminOnly()) r.GET("/", func(c *gin.Context) {}) req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected status %d, got %d", http.StatusUnauthorized, w.Code) } } func TestAdminOnly_Forbidden(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(func(c *gin.Context) { c.Set("firebaseToken", &fbauth.Token{Claims: map[string]interface{}{"admin": false}}) }) r.Use(AdminOnly()) r.GET("/", func(c *gin.Context) {}) req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusForbidden { t.Fatalf("expected status %d, got %d", http.StatusForbidden, w.Code) } } func TestAdminOnly_Success(t *testing.T) { gin.SetMode(gin.TestMode) r := gin.New() r.Use(func(c *gin.Context) { c.Set("firebaseToken", &fbauth.Token{Claims: map[string]interface{}{"admin": true}}) }) r.Use(AdminOnly()) r.GET("/", func(c *gin.Context) { c.Status(http.StatusOK) }) req := httptest.NewRequest(http.MethodGet, "/", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("expected status %d, got %d", http.StatusOK, w.Code) } }