package infra import ( "net/http" "net/http/httptest" "testing" "time" ) func buildRBACRoles() []Role { return []Role{ {Name: "admin", Permissions: []Permission{{Resource: "users", Action: "delete"}}}, {Name: "viewer", Permissions: []Permission{{Resource: "users", Action: "read"}}}, } } func buildAuthedRequest(t *testing.T, role, secret string) *http.Request { t.Helper() claims := JWTClaims{ Subject: "user-1", ExpiresAt: time.Now().Add(time.Hour).Unix(), Custom: map[string]any{"role": role}, } tok, err := JWTGenerate(claims, secret) if err != nil { t.Fatalf("JWTGenerate: %v", err) } req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Set("Authorization", "Bearer "+tok) return req } func TestRBACMiddleware_PermissionGranted(t *testing.T) { secret := "s" chain := HTTPMiddlewareChain( JWTMiddleware(secret), RBACMiddleware(buildRBACRoles(), Permission{Resource: "users", Action: "delete"}), ) var called bool handler := chain(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true w.WriteHeader(200) })) rec := httptest.NewRecorder() handler.ServeHTTP(rec, buildAuthedRequest(t, "admin", secret)) if rec.Code != 200 || !called { t.Errorf("admin deberia pasar: status=%d called=%v", rec.Code, called) } } func TestRBACMiddleware_PermissionDenied(t *testing.T) { secret := "s" chain := HTTPMiddlewareChain( JWTMiddleware(secret), RBACMiddleware(buildRBACRoles(), Permission{Resource: "users", Action: "delete"}), ) handler := chain(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Error("viewer no deberia pasar") })) rec := httptest.NewRecorder() handler.ServeHTTP(rec, buildAuthedRequest(t, "viewer", secret)) if rec.Code != 403 { t.Errorf("status = %d, esperaba 403", rec.Code) } } func TestRBACMiddleware_UnknownRole(t *testing.T) { secret := "s" chain := HTTPMiddlewareChain( JWTMiddleware(secret), RBACMiddleware(buildRBACRoles(), Permission{Resource: "users", Action: "read"}), ) handler := chain(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Error("rol ghost no deberia pasar") })) rec := httptest.NewRecorder() handler.ServeHTTP(rec, buildAuthedRequest(t, "ghost", secret)) if rec.Code != 403 { t.Errorf("status = %d, esperaba 403", rec.Code) } } func TestRBACMiddleware_NoClaims(t *testing.T) { // Sin JWTMiddleware delante → no hay claims en context mw := RBACMiddleware(buildRBACRoles(), Permission{Resource: "users", Action: "read"}) handler := mw(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Error("no deberia ejecutarse") })) req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() handler.ServeHTTP(rec, req) if rec.Code != 401 { t.Errorf("status = %d, esperaba 401", rec.Code) } }