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 <[email protected]> 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)
