Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions internal/apirouter/destination_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,23 @@ import (
"github.com/hookdeck/outpost/internal/logging"
"github.com/hookdeck/outpost/internal/models"
"github.com/hookdeck/outpost/internal/telemetry"
"github.com/hookdeck/outpost/internal/tenantstore"
"github.com/hookdeck/outpost/internal/util/maputil"
)

type DestinationHandlers struct {
logger *logging.Logger
telemetry telemetry.Telemetry
entityStore models.EntityStore
tenantStore tenantstore.TenantStore
topics []string
registry destregistry.Registry
}

func NewDestinationHandlers(logger *logging.Logger, telemetry telemetry.Telemetry, entityStore models.EntityStore, topics []string, registry destregistry.Registry) *DestinationHandlers {
func NewDestinationHandlers(logger *logging.Logger, telemetry telemetry.Telemetry, tenantStore tenantstore.TenantStore, topics []string, registry destregistry.Registry) *DestinationHandlers {
return &DestinationHandlers{
logger: logger,
telemetry: telemetry,
entityStore: entityStore,
tenantStore: tenantStore,
topics: topics,
registry: registry,
}
Expand All @@ -36,9 +37,9 @@ func NewDestinationHandlers(logger *logging.Logger, telemetry telemetry.Telemetr
func (h *DestinationHandlers) List(c *gin.Context) {
typeParams := c.QueryArray("type")
topicsParams := c.QueryArray("topics")
var opts models.ListDestinationByTenantOpts
var opts tenantstore.ListDestinationByTenantOpts
if len(typeParams) > 0 || len(topicsParams) > 0 {
opts = models.WithDestinationFilter(models.DestinationFilter{
opts = tenantstore.WithDestinationFilter(tenantstore.DestinationFilter{
Type: typeParams,
Topics: topicsParams,
})
Expand All @@ -49,7 +50,7 @@ func (h *DestinationHandlers) List(c *gin.Context) {
return
}

destinations, err := h.entityStore.ListDestinationByTenant(c.Request.Context(), tenantID, opts)
destinations, err := h.tenantStore.ListDestinationByTenant(c.Request.Context(), tenantID, opts)
if err != nil {
AbortWithError(c, http.StatusInternalServerError, NewErrInternalServer(err))
return
Expand Down Expand Up @@ -96,7 +97,7 @@ func (h *DestinationHandlers) Create(c *gin.Context) {
AbortWithValidationError(c, err)
return
}
if err := h.entityStore.CreateDestination(c.Request.Context(), destination); err != nil {
if err := h.tenantStore.CreateDestination(c.Request.Context(), destination); err != nil {
h.handleUpsertDestinationError(c, err)
return
}
Expand Down Expand Up @@ -196,7 +197,7 @@ func (h *DestinationHandlers) Update(c *gin.Context) {

// Update destination.
updatedDestination.UpdatedAt = time.Now()
if err := h.entityStore.UpsertDestination(c.Request.Context(), updatedDestination); err != nil {
if err := h.tenantStore.UpsertDestination(c.Request.Context(), updatedDestination); err != nil {
h.handleUpsertDestinationError(c, err)
return
}
Expand All @@ -218,7 +219,7 @@ func (h *DestinationHandlers) Delete(c *gin.Context) {
if destination == nil {
return
}
if err := h.entityStore.DeleteDestination(c.Request.Context(), destination.TenantID, destination.ID); err != nil {
if err := h.tenantStore.DeleteDestination(c.Request.Context(), destination.TenantID, destination.ID); err != nil {
AbortWithError(c, http.StatusInternalServerError, NewErrInternalServer(err))
return
}
Expand Down Expand Up @@ -274,7 +275,7 @@ func (h *DestinationHandlers) setDisabilityHandler(c *gin.Context, disabled bool
destination.DisabledAt = nil
}
if shouldUpdate {
if err := h.entityStore.UpsertDestination(c.Request.Context(), *destination); err != nil {
if err := h.tenantStore.UpsertDestination(c.Request.Context(), *destination); err != nil {
h.handleUpsertDestinationError(c, err)
return
}
Expand All @@ -289,9 +290,9 @@ func (h *DestinationHandlers) setDisabilityHandler(c *gin.Context, disabled bool
}

func (h *DestinationHandlers) mustRetrieveDestination(c *gin.Context, tenantID, destinationID string) *models.Destination {
destination, err := h.entityStore.RetrieveDestination(c.Request.Context(), tenantID, destinationID)
destination, err := h.tenantStore.RetrieveDestination(c.Request.Context(), tenantID, destinationID)
if err != nil {
if errors.Is(err, models.ErrDestinationDeleted) {
if errors.Is(err, tenantstore.ErrDestinationDeleted) {
c.Status(http.StatusNotFound)
return nil
}
Expand All @@ -310,7 +311,7 @@ func (h *DestinationHandlers) handleUpsertDestinationError(c *gin.Context, err e
AbortWithValidationError(c, err)
return
}
if errors.Is(err, models.ErrDuplicateDestination) {
if errors.Is(err, tenantstore.ErrDuplicateDestination) {
AbortWithError(c, http.StatusBadRequest, NewErrBadRequest(err))
return
}
Expand Down
8 changes: 4 additions & 4 deletions internal/apirouter/destination_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestDestinationCreateHandler(t *testing.T) {
t.Parallel()

router, _, redisClient := setupTestRouter(t, "", "")
entityStore := setupTestEntityStore(t, redisClient, nil)
tenantStore := setupTestTenantStore(t, redisClient)

t.Run("should set updated_at equal to created_at on creation", func(t *testing.T) {
t.Parallel()
Expand All @@ -30,7 +30,7 @@ func TestDestinationCreateHandler(t *testing.T) {
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
err := entityStore.UpsertTenant(context.Background(), tenant)
err := tenantStore.UpsertTenant(context.Background(), tenant)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -60,8 +60,8 @@ func TestDestinationCreateHandler(t *testing.T) {

// Cleanup
if destID, ok := response["id"].(string); ok {
entityStore.DeleteDestination(context.Background(), tenantID, destID)
tenantStore.DeleteDestination(context.Background(), tenantID, destID)
}
entityStore.DeleteTenant(context.Background(), tenantID)
tenantStore.DeleteTenant(context.Background(), tenantID)
})
}
20 changes: 10 additions & 10 deletions internal/apirouter/log_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ func parseIncludeOptions(c *gin.Context) IncludeOptions {

// APIAttempt is the API response for an attempt
type APIAttempt struct {
ID string `json:"id"`
Status string `json:"status"`
DeliveredAt time.Time `json:"delivered_at"`
Code string `json:"code,omitempty"`
ResponseData map[string]interface{} `json:"response_data,omitempty"`
AttemptNumber int `json:"attempt_number"`
Manual bool `json:"manual"`
ID string `json:"id"`
Status string `json:"status"`
DeliveredAt time.Time `json:"delivered_at"`
Code string `json:"code,omitempty"`
ResponseData map[string]interface{} `json:"response_data,omitempty"`
AttemptNumber int `json:"attempt_number"`
Manual bool `json:"manual"`

// Expandable fields - string (ID) or object depending on expand
Event interface{} `json:"event"`
Expand Down Expand Up @@ -146,8 +146,8 @@ type EventPaginatedResult struct {
func toAPIAttempt(ar *logstore.AttemptRecord, opts IncludeOptions) APIAttempt {
api := APIAttempt{
AttemptNumber: ar.Attempt.AttemptNumber,
Manual: ar.Attempt.Manual,
Destination: ar.Attempt.DestinationID,
Manual: ar.Attempt.Manual,
Destination: ar.Attempt.DestinationID,
}

if ar.Attempt != nil {
Expand Down Expand Up @@ -186,7 +186,7 @@ func toAPIAttempt(ar *logstore.AttemptRecord, opts IncludeOptions) APIAttempt {
}

// TODO: Handle destination expansion
// This would require injecting EntityStore into LogHandlers and batch-fetching
// This would require injecting TenantStore into LogHandlers and batch-fetching
// destinations by ID. Consider if this is needed - clients can fetch destination
// details separately via GET /destinations/:id if needed.

Expand Down
16 changes: 8 additions & 8 deletions internal/apirouter/log_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func TestListAttempts(t *testing.T) {
// Create a tenant
tenantID := idgen.String()
destinationID := idgen.Destination()
require.NoError(t, result.entityStore.UpsertTenant(context.Background(), models.Tenant{
require.NoError(t, result.tenantStore.UpsertTenant(context.Background(), models.Tenant{
ID: tenantID,
CreatedAt: time.Now(),
}))
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: destinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down Expand Up @@ -295,11 +295,11 @@ func TestRetrieveAttempt(t *testing.T) {
// Create a tenant
tenantID := idgen.String()
destinationID := idgen.Destination()
require.NoError(t, result.entityStore.UpsertTenant(context.Background(), models.Tenant{
require.NoError(t, result.tenantStore.UpsertTenant(context.Background(), models.Tenant{
ID: tenantID,
CreatedAt: time.Now(),
}))
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: destinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down Expand Up @@ -404,11 +404,11 @@ func TestRetrieveEvent(t *testing.T) {
// Create a tenant
tenantID := idgen.String()
destinationID := idgen.Destination()
require.NoError(t, result.entityStore.UpsertTenant(context.Background(), models.Tenant{
require.NoError(t, result.tenantStore.UpsertTenant(context.Background(), models.Tenant{
ID: tenantID,
CreatedAt: time.Now(),
}))
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: destinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down Expand Up @@ -489,11 +489,11 @@ func TestListEvents(t *testing.T) {
// Create a tenant
tenantID := idgen.String()
destinationID := idgen.Destination()
require.NoError(t, result.entityStore.UpsertTenant(context.Background(), models.Tenant{
require.NoError(t, result.tenantStore.UpsertTenant(context.Background(), models.Tenant{
ID: tenantID,
CreatedAt: time.Now(),
}))
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: destinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down
7 changes: 4 additions & 3 deletions internal/apirouter/requiretenant_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import (

"github.com/gin-gonic/gin"
"github.com/hookdeck/outpost/internal/models"
"github.com/hookdeck/outpost/internal/tenantstore"
)

func RequireTenantMiddleware(entityStore models.EntityStore) gin.HandlerFunc {
func RequireTenantMiddleware(tenantStore tenantstore.TenantStore) gin.HandlerFunc {
return func(c *gin.Context) {
tenantID, exists := c.Get("tenantID")
if !exists {
c.AbortWithStatus(http.StatusNotFound)
return
}

tenant, err := entityStore.RetrieveTenant(c.Request.Context(), tenantID.(string))
tenant, err := tenantStore.RetrieveTenant(c.Request.Context(), tenantID.(string))
if err != nil {
if err == models.ErrTenantDeleted {
if err == tenantstore.ErrTenantDeleted {
c.AbortWithStatus(http.StatusNotFound)
return
}
Expand Down
4 changes: 2 additions & 2 deletions internal/apirouter/requiretenant_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ func TestRequireTenantMiddleware(t *testing.T) {
tenant := models.Tenant{
ID: idgen.String(),
}
entityStore := setupTestEntityStore(t, redisClient, nil)
err := entityStore.UpsertTenant(context.Background(), tenant)
tenantStore := setupTestTenantStore(t, redisClient)
err := tenantStore.UpsertTenant(context.Background(), tenant)
require.Nil(t, err)

w := httptest.NewRecorder()
Expand Down
9 changes: 5 additions & 4 deletions internal/apirouter/retry_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,26 @@ import (
"github.com/hookdeck/outpost/internal/logging"
"github.com/hookdeck/outpost/internal/logstore"
"github.com/hookdeck/outpost/internal/models"
"github.com/hookdeck/outpost/internal/tenantstore"
"go.uber.org/zap"
)

type RetryHandlers struct {
logger *logging.Logger
entityStore models.EntityStore
tenantStore tenantstore.TenantStore
logStore logstore.LogStore
deliveryMQ *deliverymq.DeliveryMQ
}

func NewRetryHandlers(
logger *logging.Logger,
entityStore models.EntityStore,
tenantStore tenantstore.TenantStore,
logStore logstore.LogStore,
deliveryMQ *deliverymq.DeliveryMQ,
) *RetryHandlers {
return &RetryHandlers{
logger: logger,
entityStore: entityStore,
tenantStore: tenantStore,
logStore: logStore,
deliveryMQ: deliveryMQ,
}
Expand Down Expand Up @@ -58,7 +59,7 @@ func (h *RetryHandlers) RetryAttempt(c *gin.Context) {
}

// 2. Check destination exists and is enabled
destination, err := h.entityStore.RetrieveDestination(c.Request.Context(), tenant.ID, attemptRecord.Attempt.DestinationID)
destination, err := h.tenantStore.RetrieveDestination(c.Request.Context(), tenant.ID, attemptRecord.Attempt.DestinationID)
if err != nil {
AbortWithError(c, http.StatusInternalServerError, NewErrInternalServer(err))
return
Expand Down
6 changes: 3 additions & 3 deletions internal/apirouter/retry_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ func TestRetryAttempt(t *testing.T) {
// Create a tenant and destination
tenantID := idgen.String()
destinationID := idgen.Destination()
require.NoError(t, result.entityStore.UpsertTenant(context.Background(), models.Tenant{
require.NoError(t, result.tenantStore.UpsertTenant(context.Background(), models.Tenant{
ID: tenantID,
CreatedAt: time.Now(),
}))
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: destinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down Expand Up @@ -117,7 +117,7 @@ func TestRetryAttempt(t *testing.T) {
// Create a new destination that's disabled
disabledDestinationID := idgen.Destination()
disabledAt := time.Now()
require.NoError(t, result.entityStore.UpsertDestination(context.Background(), models.Destination{
require.NoError(t, result.tenantStore.UpsertDestination(context.Background(), models.Destination{
ID: disabledDestinationID,
TenantID: tenantID,
Type: "webhook",
Expand Down
Loading
Loading