Ctrl K
ComunidadGuías…

internal/middleware/tenant_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package middleware

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/google/uuid"

	"github.com/sarathsp06/sparrow/internal/tenant"
	"github.com/sarathsp06/sparrow/pkg/access"
)

// forTenant runs the request as tenant id, as server.WithTenant does.
func forTenant(id uuid.UUID) func(*http.Request) {
	return func(r *http.Request) { *r = *r.WithContext(tenant.WithTenant(r.Context(), id)) }
}

func both(sets ...func(*http.Request)) func(*http.Request) {
	return func(r *http.Request) {
		for _, set := range sets {
			set(r)
		}
	}
}

func TestAuthRefusesATokenOfTenantAOnTenantB(t *testing.T) {
	auth, svc := newAuth(t, "secret")
	tenantA, tenantB := uuid.New(), uuid.New()
	tok, secret, err := svc.CreateToken(context.Background(), access.CreateTokenRequest{Realm: tenantA.String(), Name: "a", CreatedBy: "x"})
	if err != nil {
		t.Fatal(err)
	}

	if code, p, _ := guarded(auth, both(forTenant(tenantA), apiKey(secret))); code != http.StatusNoContent || p.TokenID != tok.ID {
		t.Fatalf("token on its own tenant: %d %+v", code, p)
	}
	if code, _, body := guarded(auth, both(forTenant(tenantB), apiKey(secret))); code != http.StatusUnauthorized {
		t.Fatalf("token of tenant A on tenant B: %d %s, want 401", code, body)
	}
	if code, _, body := guarded(auth, apiKey(secret)); code != http.StatusUnauthorized {
		t.Fatalf("token of tenant A on the default tenant: %d %s, want 401", code, body)
	}
	// The master key is the server's, not a tenant's.
	if code, p, _ := guarded(auth, both(forTenant(tenantB), apiKey("secret"))); code != http.StatusNoContent || !p.Root {
		t.Fatalf("master key on tenant B: %d %+v", code, p)
	}
}

func TestAuthDisabledRunsAsTheRequestTenant(t *testing.T) {
	auth, _ := newAuth(t, "")
	tenantB := uuid.New()
	if code, p, _ := guarded(auth, forTenant(tenantB)); code != http.StatusNoContent || p.Realm != tenantB.String() {
		t.Fatalf("disabled auth on tenant B: %d %+v", code, p)
	}
}

func TestPortalGatewayRefusesATokenOfTenantAOnTenantB(t *testing.T) {
	svc, gw, seen := newPortalGateway(t)
	tenantA, tenantB := uuid.New(), uuid.New()
	acme := "acme"
	_, secret, err := svc.CreateToken(context.Background(), access.CreateTokenRequest{Realm: tenantA.String(), Scope: &acme, Name: "portal", CreatedBy: "x"})
	if err != nil {
		t.Fatal(err)
	}
	call := func(id uuid.UUID) int {
		req := httptest.NewRequest(http.MethodGet, "/portal/api/webhooks", nil)
		req = req.WithContext(tenant.WithTenant(req.Context(), id))
		req.Header.Set("Authorization", "Bearer "+secret)
		rr := httptest.NewRecorder()
		gw.ServeHTTP(rr, req)
		return rr.Code
	}

	if code := call(tenantA); code != http.StatusNoContent || *seen != "/v1/consumers/acme/webhooks" {
		t.Fatalf("token on its own tenant: %d %q", code, *seen)
	}
	*seen = ""
	if code := call(tenantB); code != http.StatusUnauthorized || *seen != "" {
		t.Fatalf("token of tenant A on tenant B: %d, reached %q; want 401 and nothing reached", code, *seen)
	}
	if code := call(tenant.DefaultTenantID); code != http.StatusUnauthorized || *seen != "" {
		t.Fatalf("token of tenant A on the default tenant: %d, reached %q; want 401", code, *seen)
	}
}