You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by la...@apache.org on 2026/06/23 18:39:09 UTC

(airavata-custos) 01/01: Move audit-trace store into Service dropping AdminDeps

This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch audit-service
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit af5914980d85fa4e90ae0ec75990f94e75bf1e3f
Author: lahiruj <la...@gmail.com>
AuthorDate: Tue Jun 23 14:38:58 2026 -0400

    Move audit-trace store into Service dropping AdminDeps
---
 cmd/server/main.go                         |  6 +----
 internal/server/audit_handlers.go          |  9 ++++++--
 internal/server/audit_handlers_test.go     | 35 ++++++++++++++++--------------
 internal/server/integration_common_test.go |  2 +-
 internal/server/server.go                  | 11 ++--------
 internal/server/server_trace_test.go       |  2 +-
 pkg/service/service.go                     | 11 ++++++++++
 7 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/cmd/server/main.go b/cmd/server/main.go
index e7ba08a87..f7cc37762 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -38,7 +38,6 @@ import (
 	"github.com/apache/airavata-custos/internal/connectors"
 	"github.com/apache/airavata-custos/internal/db"
 	"github.com/apache/airavata-custos/internal/server"
-	"github.com/apache/airavata-custos/internal/store"
 	"github.com/apache/airavata-custos/internal/tracing"
 	"github.com/apache/airavata-custos/pkg/events"
 	"github.com/apache/airavata-custos/pkg/identity"
@@ -132,11 +131,8 @@ func run() error {
 
 	tryBootstrap(ctx, svc)
 
-	adminDeps := &server.AdminDeps{
-		AuditTraces: store.NewAuditTraceStore(database),
-	}
 	router := identity.NewRouter(http.NewServeMux())
-	srv := server.New(svc, router, adminDeps)
+	srv := server.New(svc, router)
 
 	// Tracks every background goroutine spawned by connectors so we can wait
 	// for them to drain on shutdown instead of killing them mid-flight.
diff --git a/internal/server/audit_handlers.go b/internal/server/audit_handlers.go
index 9b9199c8c..7307df47a 100644
--- a/internal/server/audit_handlers.go
+++ b/internal/server/audit_handlers.go
@@ -39,11 +39,16 @@ const (
 )
 
 func (s *Server) requireAuditStore(w http.ResponseWriter) (store.AuditTraceStore, bool) {
-	if s.admin == nil || s.admin.AuditTraces == nil {
+	if s.svc == nil {
 		common.WriteError(w, http.StatusServiceUnavailable, errors.New("audit trace store not configured"))
 		return nil, false
 	}
-	return s.admin.AuditTraces, true
+	ts := s.svc.AuditTraces()
+	if ts == nil {
+		common.WriteError(w, http.StatusServiceUnavailable, errors.New("audit trace store not configured"))
+		return nil, false
+	}
+	return ts, true
 }
 
 // @Summary	List audit traces with filters
diff --git a/internal/server/audit_handlers_test.go b/internal/server/audit_handlers_test.go
index d8596320c..7ad3327fc 100644
--- a/internal/server/audit_handlers_test.go
+++ b/internal/server/audit_handlers_test.go
@@ -29,6 +29,7 @@ import (
 	"github.com/apache/airavata-custos/internal/store"
 	"github.com/apache/airavata-custos/pkg/identity"
 	"github.com/apache/airavata-custos/pkg/models"
+	"github.com/apache/airavata-custos/pkg/service"
 )
 
 // fakeAuditStore implements AuditTraceStore for handler tests.
@@ -86,12 +87,14 @@ func mustHexTraceID(t *testing.T) string {
 	return strings.Repeat("ab", 16)
 }
 
-// newAuditServer boots an httptest.Server around the audit handlers with a
-// fake AuditTraceStore. svc is nil, audit handlers don't reach into *Service.
-func newAuditServer(t *testing.T, deps *AdminDeps) *httptest.Server {
+// newAuditServer boots an httptest.Server around the audit handlers with the
+// given fake AuditTraceStore (nil exercises the 503 path).
+func newAuditServer(t *testing.T, audit store.AuditTraceStore) *httptest.Server {
 	t.Helper()
 	router := identity.NewRouter(http.NewServeMux())
-	inner := New(nil, router, deps)
+	svc := service.New(nil, nil)
+	svc.SetAuditTraces(audit)
+	inner := New(svc, router)
 	wrap := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		inner.ServeHTTP(w, withTestCaller(r, "test-user"))
 	})
@@ -114,7 +117,7 @@ func TestListTracesReturnsRowsAndEcho(t *testing.T) {
 		}},
 		total: 1,
 	}
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: fs})
+	srv := newAuditServer(t, fs)
 
 	resp, err := http.Get(srv.URL + "/audit/traces?source=amie&status=ok&limit=25")
 	if err != nil {
@@ -148,7 +151,7 @@ func TestListTracesReturnsRowsAndEcho(t *testing.T) {
 }
 
 func TestListTracesRejectsBadStatus(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/traces?status=garbage")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -161,7 +164,7 @@ func TestListTracesRejectsBadStatus(t *testing.T) {
 
 func TestListTracesAppliesDefaultLimit(t *testing.T) {
 	fs := &fakeAuditStore{}
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: fs})
+	srv := newAuditServer(t, fs)
 	resp, err := http.Get(srv.URL + "/audit/traces")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -177,7 +180,7 @@ func TestListTracesAppliesDefaultLimit(t *testing.T) {
 
 func TestListTracesCapsLimitAt200(t *testing.T) {
 	fs := &fakeAuditStore{}
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: fs})
+	srv := newAuditServer(t, fs)
 	resp, err := http.Get(srv.URL + "/audit/traces?limit=5000")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -189,7 +192,7 @@ func TestListTracesCapsLimitAt200(t *testing.T) {
 }
 
 func TestListTracesRejectsOversizeOffset(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/traces?offset=99999999")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -201,7 +204,7 @@ func TestListTracesRejectsOversizeOffset(t *testing.T) {
 }
 
 func TestListTracesRejectsOversizeWindow(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/traces?from=2024-01-01T00:00:00Z&to=2026-01-02T00:00:00Z")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -213,7 +216,7 @@ func TestListTracesRejectsOversizeWindow(t *testing.T) {
 }
 
 func TestGetTraceBadHex(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/traces/not-hex")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -226,7 +229,7 @@ func TestGetTraceBadHex(t *testing.T) {
 
 func TestGetTraceNotFound(t *testing.T) {
 	raw := mustHexTraceID(t)
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/traces/" + raw)
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -268,7 +271,7 @@ func TestGetTraceReturnsTree(t *testing.T) {
 		},
 	}
 	fs := &fakeAuditStore{tree: tree}
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: fs})
+	srv := newAuditServer(t, fs)
 
 	resp, err := http.Get(srv.URL + "/audit/traces/" + raw)
 	if err != nil {
@@ -320,7 +323,7 @@ func TestListEventsFlat(t *testing.T) {
 		Status:    "ok",
 		CreatedAt: time.Unix(1700000000, 0).UTC(),
 	}}}
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: fs})
+	srv := newAuditServer(t, fs)
 
 	resp, err := http.Get(srv.URL + "/audit/events?trace_id=" + raw + "&span_id=" + span)
 	if err != nil {
@@ -351,7 +354,7 @@ func TestListEventsFlat(t *testing.T) {
 }
 
 func TestListEventsRejectsMissingTraceID(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/events")
 	if err != nil {
 		t.Fatalf("get: %v", err)
@@ -363,7 +366,7 @@ func TestListEventsRejectsMissingTraceID(t *testing.T) {
 }
 
 func TestListSources(t *testing.T) {
-	srv := newAuditServer(t, &AdminDeps{AuditTraces: &fakeAuditStore{}})
+	srv := newAuditServer(t, &fakeAuditStore{})
 	resp, err := http.Get(srv.URL + "/audit/sources")
 	if err != nil {
 		t.Fatalf("get: %v", err)
diff --git a/internal/server/integration_common_test.go b/internal/server/integration_common_test.go
index d36225331..2bf972f4b 100644
--- a/internal/server/integration_common_test.go
+++ b/internal/server/integration_common_test.go
@@ -72,7 +72,7 @@ func setupTestStack(t *testing.T) (*sqlx.DB, *service.Service, *Server) {
 	truncateAll(t, sharedDB)
 	svc := service.New(sharedDB, events.New())
 	router := identity.NewRouter(http.NewServeMux())
-	return sharedDB, svc, New(svc, router, nil)
+	return sharedDB, svc, New(svc, router)
 }
 
 func truncateAll(t *testing.T, database *sqlx.DB) {
diff --git a/internal/server/server.go b/internal/server/server.go
index 5b14e56c8..461ae75c5 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -34,23 +34,16 @@ import (
 	"github.com/apache/airavata-custos/pkg/service"
 )
 
-// AdminDeps wires the /audit/* endpoints. A nil field makes its routes return 503.
-// TODO(server): fold AuditTraces onto *Service and drop AdminDeps.
-type AdminDeps struct {
-	AuditTraces store.AuditTraceStore
-}
-
 // Server is an HTTP handler that exposes the service API.
 type Server struct {
 	svc    *service.Service
 	router *identity.Router
-	admin  *AdminDeps
 }
 
 // New builds an HTTP handler wired to the supplied service. The router owns the mux
 // and gates every authenticated route.
-func New(svc *service.Service, router *identity.Router, admin *AdminDeps) *Server {
-	s := &Server{svc: svc, router: router, admin: admin}
+func New(svc *service.Service, router *identity.Router) *Server {
+	s := &Server{svc: svc, router: router}
 	s.routes()
 	return s
 }
diff --git a/internal/server/server_trace_test.go b/internal/server/server_trace_test.go
index fe50ce8e4..40f86525c 100644
--- a/internal/server/server_trace_test.go
+++ b/internal/server/server_trace_test.go
@@ -41,7 +41,7 @@ func TestLoggingWrapsTracingProducesTraceIdHeader(t *testing.T) {
 	t.Cleanup(func() { otel.SetTracerProvider(prev) })
 
 	router := identity.NewRouter(http.NewServeMux())
-	handler := LoggingMiddleware(tracing.Middleware(New(nil, router, nil)))
+	handler := LoggingMiddleware(tracing.Middleware(New(nil, router)))
 
 	req := httptest.NewRequest(http.MethodGet, "/healthz", nil)
 	rec := httptest.NewRecorder()
diff --git a/pkg/service/service.go b/pkg/service/service.go
index c1737d7ab..2c8b42996 100644
--- a/pkg/service/service.go
+++ b/pkg/service/service.go
@@ -57,6 +57,7 @@ type Service struct {
 	privileges          store.UserPrivilegeStore
 	roles               store.RoleStore
 	userRoles           store.UserRoleStore
+	auditTraces         store.AuditTraceStore
 	identityCache       *identityCache
 }
 
@@ -87,6 +88,7 @@ func New(database *sqlx.DB, eventBus *events.Bus) *Service {
 		privileges:          store.NewUserPrivilegeStore(database),
 		roles:               store.NewRoleStore(database),
 		userRoles:           store.NewUserRoleStore(database),
+		auditTraces:         store.NewAuditTraceStore(database),
 		identityCache:       newIdentityCache(),
 	}
 }
@@ -143,10 +145,19 @@ func NewWithStores(
 		privileges:          privileges,
 		roles:               roles,
 		userRoles:           userRoles,
+		auditTraces:         store.NewAuditTraceStore(database),
 		identityCache:       newIdentityCache(),
 	}
 }
 
+func (s *Service) AuditTraces() store.AuditTraceStore {
+	return s.auditTraces
+}
+
+func (s *Service) SetAuditTraces(ts store.AuditTraceStore) {
+	s.auditTraces = ts
+}
+
 // inTx runs fn inside a database transaction managed by the Service.
 func (s *Service) inTx(ctx context.Context, fn func(tx *sql.Tx) error) error {
 	return db.TxFn(ctx, s.db, fn)