Files
proxui/backend/internal/audit/handler_test.go
T

87 lines
2.4 KiB
Go

package audit
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"proxui/backend/internal/auth"
"proxui/backend/internal/membership"
"proxui/backend/internal/rbac"
)
func TestListTenantAuditReturnsEntries(t *testing.T) {
repository := &stubRepository{
entries: []Entry{{
ID: "audit-1",
TenantID: "tenant-1",
ProfileID: "profile-1",
Action: "vm.power.start",
TargetType: "vm",
TargetID: "vm-1",
Metadata: json.RawMessage(`{"cluster_id":"c-1"}`),
CreatedAt: time.Date(2026, 6, 11, 12, 0, 0, 0, time.UTC),
}},
}
handler := NewHandler(repository)
req := requestWithPrincipalAndMembership(http.MethodGet, "/tenants/tenant-1/audit", "tenant-1", "owner")
req.SetPathValue("tenantID", "tenant-1")
rec := httptest.NewRecorder()
handler.ListTenantAudit(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK)
}
var response struct {
Data []Entry `json:"data"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
t.Fatalf("unmarshal response: %v", err)
}
if len(response.Data) != 1 {
t.Fatalf("len(data) = %d, want 1", len(response.Data))
}
if response.Data[0].ID != "audit-1" {
t.Fatalf("entry ID = %q, want audit-1", response.Data[0].ID)
}
}
func TestListTenantAuditReturnsForbiddenForViewer(t *testing.T) {
handler := NewHandler(&stubRepository{})
req := requestWithPrincipalAndMembership(http.MethodGet, "/tenants/tenant-1/audit", "tenant-1", "viewer")
req.SetPathValue("tenantID", "tenant-1")
rec := httptest.NewRecorder()
handler.ListTenantAudit(rec, req)
if rec.Code != http.StatusForbidden {
t.Fatalf("status = %d, want %d", rec.Code, http.StatusForbidden)
}
}
func requestWithPrincipalAndMembership(method string, target string, tenantID string, role string) *http.Request {
req := httptest.NewRequest(method, target, nil)
ctx := auth.ContextWithPrincipal(req.Context(), auth.Principal{
Subject: "profile-1",
Email: "user@example.test",
Role: "authenticated",
})
ctx = membership.ContextWithMembership(ctx, membership.Membership{
TenantID: tenantID,
Role: rbac.Role(role),
})
return req.WithContext(ctx)
}
type stubRepository struct {
entries []Entry
err error
}
func (s *stubRepository) ListTenantAudit(_ context.Context, _ string, _ int, _ int) ([]Entry, error) {
return s.entries, s.err
}