Documentation
¶
Overview ¶
Package webhook manages webhooks that dispatch push notifications on incoming HTTP payloads.
Index ¶
- Variables
- type CreateInspectSessionRequest
- type CreateWebhookRequest
- type CreatedWebhookResponse
- type DispatchReport
- type Dispatcher
- type FinalizeInspectRequest
- type Handler
- func (h *Handler) CreateInspectSession(w http.ResponseWriter, r *http.Request)
- func (h *Handler) CreateWebhook(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DeleteWebhook(w http.ResponseWriter, r *http.Request)
- func (h *Handler) FinalizeInspect(w http.ResponseWriter, r *http.Request)
- func (h *Handler) GetInspectSession(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ListWebhooks(w http.ResponseWriter, r *http.Request)
- func (h *Handler) Receive(w http.ResponseWriter, r *http.Request)
- func (h *Handler) RegenerateToken(w http.ResponseWriter, r *http.Request)
- func (h *Handler) UpdateWebhook(w http.ResponseWriter, r *http.Request)
- type InspectSession
- type InspectSessionResponse
- type InspectSessionStatusResponse
- type InspectStatus
- type InspectStore
- func (s *InspectStore) Capture(tokenHash string, payload json.RawMessage) error
- func (s *InspectStore) Create(userID, name, description, priority string, topics []string) (*InspectSession, error)
- func (s *InspectStore) Delete(userID string)
- func (s *InspectStore) GetByTokenHash(tokenHash string) *InspectSession
- func (s *InspectStore) GetByUserID(userID string) *InspectSession
- type PayloadType
- type ReceiveResponse
- type ReceiveStatus
- type RegenerateTokenResponse
- type Repository
- func (r *Repository) AddTopic(ctx context.Context, webhookID, topicID string) error
- func (r *Repository) Create(ctx context.Context, userID, name, description string, payloadType PayloadType, ...) (string, error)
- func (r *Repository) CreateWithTopics(ctx context.Context, userID, name, description string, payloadType PayloadType, ...) (string, error)
- func (r *Repository) DeleteTopic(ctx context.Context, webhookID, topicID string) error
- func (r *Repository) GetByID(ctx context.Context, userID, webhookID string) (*Webhook, error)
- func (r *Repository) GetByTokenHash(ctx context.Context, tokenHash string) (*Webhook, error)
- func (r *Repository) GetByUser(ctx context.Context, userID string) ([]Webhook, error)
- func (r *Repository) GetTopicIDs(ctx context.Context, webhookID string) ([]string, error)
- func (r *Repository) GetTopics(ctx context.Context, webhookID string) ([]string, error)
- func (r *Repository) GetTopicsWithIDs(ctx context.Context, webhookID string) ([]WebhookTopic, error)
- func (r *Repository) Revoke(ctx context.Context, userID, webhookID string) error
- func (r *Repository) TouchLastUsedAt(ctx context.Context, webhookID string) error
- func (r *Repository) Update(ctx context.Context, userID, webhookID, name, description string, ...) error
- func (r *Repository) UpdateTokenHash(ctx context.Context, userID, webhookID, newTokenHash string) error
- func (r *Repository) UpdateWithTopics(ctx context.Context, userID, webhookID, name, description string, ...) error
- type Service
- func (s *Service) CaptureInspectPayload(tokenStr string, body []byte) (bool, error)
- func (s *Service) CreateInspectSession(ctx context.Context, userID, name, description, priority string, ...) (*InspectSessionResponse, error)
- func (s *Service) CreateWebhook(ctx context.Context, userID, name, description string, payloadType PayloadType, ...) (string, string, error)
- func (s *Service) FinalizeInspect(ctx context.Context, userID, titlePath, bodyPath string) (string, string, error)
- func (s *Service) GetInspectSession(ctx context.Context, userID string) *InspectSessionStatusResponse
- func (s *Service) ListWebhooks(ctx context.Context, userID string) ([]WebhookResponse, error)
- func (s *Service) Receive(ctx context.Context, tokenStr string, body []byte, log *slog.Logger) (*ReceiveResponse, error)
- func (s *Service) RegenerateToken(ctx context.Context, userID, webhookID string) (string, error)
- func (s *Service) RevokeWebhook(ctx context.Context, userID, webhookID string) error
- func (s *Service) UpdateWebhook(ctx context.Context, userID, webhookID, name, description string, ...) error
- type TopicValidator
- type UpdateWebhookRequest
- type Webhook
- type WebhookResponse
- type WebhookTopic
- type WebhooksListResponse
Constants ¶
This section is empty.
Variables ¶
var ( // ErrWebhookNotFound is returned when a webhook does not exist or does not belong to the user. ErrWebhookNotFound = errors.New("webhook not found") // ErrWebhookInactive is returned when a webhook token resolves to a revoked webhook. ErrWebhookInactive = errors.New("webhook is inactive") // ErrPayloadExtraction is returned when gjson cannot find the configured path in the payload. ErrPayloadExtraction = errors.New("failed to extract fields from payload") // ErrAtLeastOneTopic is returned when a webhook request contains no topics. ErrAtLeastOneTopic = errors.New("at least one topic is required") // ErrInvalidTopicSelection is returned when one or more topics are invalid for the user. ErrInvalidTopicSelection = errors.New("invalid topic selection") // ErrWebhookDeliveryFailed is returned when every dispatch attempt for a webhook fails. ErrWebhookDeliveryFailed = errors.New("webhook delivery failed") // ErrInspectSessionNotFound is returned when an inspect session does not exist or has expired. ErrInspectSessionNotFound = errors.New("inspect session not found") // ErrInspectNotWaiting is returned when trying to capture a payload on a non-waiting session. ErrInspectNotWaiting = errors.New("inspect session is not in waiting state") // ErrInspectNotCaptured is returned when trying to finalize without a captured payload. ErrInspectNotCaptured = errors.New("no payload has been captured") // ErrInspectSessionExpired is returned when an inspect session has expired. ErrInspectSessionExpired = errors.New("inspect session expired") )
Functions ¶
This section is empty.
Types ¶
type CreateInspectSessionRequest ¶
type CreateInspectSessionRequest struct {
Name string `json:"name"`
Description string `json:"description"`
Topics []string `json:"topics"`
Priority string `json:"priority"`
}
CreateInspectSessionRequest is the request body for POST /webhooks/inspect.
func (*CreateInspectSessionRequest) Validate ¶
func (r *CreateInspectSessionRequest) Validate() []error
Validate validates the create inspect session request fields.
type CreateWebhookRequest ¶
type CreateWebhookRequest struct {
Name string `json:"name"`
Description string `json:"description"`
PayloadType PayloadType `json:"payload_type"`
TitlePath string `json:"title_path"`
BodyPath string `json:"body_path"`
Priority string `json:"priority"`
Topics []string `json:"topics"`
}
CreateWebhookRequest is the request body for POST /webhooks.
func (*CreateWebhookRequest) Validate ¶
func (r *CreateWebhookRequest) Validate() []error
Validate validates the create webhook request fields.
type CreatedWebhookResponse ¶
type CreatedWebhookResponse struct {
ID string `json:"id"`
Token string `json:"token"`
Name string `json:"name"`
}
CreatedWebhookResponse is returned on POST /webhooks (one-time token reveal).
type DispatchReport ¶
type DispatchReport struct {
TotalSent int
}
DispatchReport contains webhook-local delivery reporting needed for logging.
type Dispatcher ¶
type Dispatcher interface {
Dispatch(ctx context.Context, userID, topicID, topicName, title, body, priority string, log *slog.Logger) (*DispatchReport, error)
}
Dispatcher dispatches push notifications for a given user/topic.
type FinalizeInspectRequest ¶
type FinalizeInspectRequest struct {
TitlePath string `json:"title_path"`
BodyPath string `json:"body_path"`
}
FinalizeInspectRequest is the request body for POST /webhooks/inspect/finalize.
func (*FinalizeInspectRequest) Validate ¶
func (r *FinalizeInspectRequest) Validate() []error
Validate validates the finalize inspect request fields.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler handles webhook HTTP requests.
func NewHandler ¶
NewHandler creates a new webhook handler.
func (*Handler) CreateInspectSession ¶
func (h *Handler) CreateInspectSession(w http.ResponseWriter, r *http.Request)
CreateInspectSession handles POST /webhooks/inspect.
func (*Handler) CreateWebhook ¶
func (h *Handler) CreateWebhook(w http.ResponseWriter, r *http.Request)
CreateWebhook handles POST /webhooks.
func (*Handler) DeleteWebhook ¶
func (h *Handler) DeleteWebhook(w http.ResponseWriter, r *http.Request)
DeleteWebhook handles DELETE /webhooks/{webhookID}.
func (*Handler) FinalizeInspect ¶
func (h *Handler) FinalizeInspect(w http.ResponseWriter, r *http.Request)
FinalizeInspect handles POST /webhooks/inspect/finalize.
func (*Handler) GetInspectSession ¶
func (h *Handler) GetInspectSession(w http.ResponseWriter, r *http.Request)
GetInspectSession handles GET /webhooks/inspect.
func (*Handler) ListWebhooks ¶
func (h *Handler) ListWebhooks(w http.ResponseWriter, r *http.Request)
ListWebhooks handles GET /webhooks.
func (*Handler) Receive ¶
func (h *Handler) Receive(w http.ResponseWriter, r *http.Request)
Receive handles incoming webhook payloads.
func (*Handler) RegenerateToken ¶
func (h *Handler) RegenerateToken(w http.ResponseWriter, r *http.Request)
RegenerateToken handles POST /webhooks/{webhookID}/token.
func (*Handler) UpdateWebhook ¶
func (h *Handler) UpdateWebhook(w http.ResponseWriter, r *http.Request)
UpdateWebhook handles PATCH /webhooks/{webhookID}.
type InspectSession ¶
type InspectSessionResponse ¶
type InspectSessionResponse struct {
Token string `json:"token"`
URL string `json:"url"`
Status InspectStatus `json:"status"`
ExpiresAt time.Time `json:"expires_at"`
}
InspectSessionResponse is the HTTP response for inspect session operations.
type InspectSessionStatusResponse ¶
type InspectSessionStatusResponse struct {
Status InspectStatus `json:"status"`
Payload json.RawMessage `json:"payload,omitempty"`
CapturedAt *time.Time `json:"captured_at,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
}
InspectSessionStatusResponse is the HTTP response for GET /webhooks/inspect.
type InspectStatus ¶
type InspectStatus string
const ( InspectStatusWaiting InspectStatus = "waiting" InspectStatusCaptured InspectStatus = "captured" InspectStatusCompleted InspectStatus = "completed" InspectStatusExpired InspectStatus = "expired" )
type InspectStore ¶
type InspectStore struct {
// contains filtered or unexported fields
}
func NewInspectStore ¶
func NewInspectStore() *InspectStore
NewInspectStore returns a new in-memory inspect session store.
func (*InspectStore) Capture ¶
func (s *InspectStore) Capture(tokenHash string, payload json.RawMessage) error
Capture records the payload for the inspect session identified by token hash.
func (*InspectStore) Create ¶
func (s *InspectStore) Create(userID, name, description, priority string, topics []string) (*InspectSession, error)
Create generates a new inspect session for the given user, replacing any previous one.
func (*InspectStore) Delete ¶
func (s *InspectStore) Delete(userID string)
Delete removes the inspect session for the given user.
func (*InspectStore) GetByTokenHash ¶
func (s *InspectStore) GetByTokenHash(tokenHash string) *InspectSession
GetByTokenHash returns the inspect session matching the given token hash, or nil if not found or expired.
func (*InspectStore) GetByUserID ¶
func (s *InspectStore) GetByUserID(userID string) *InspectSession
GetByUserID returns the inspect session for the given user, or nil if not found or expired.
type PayloadType ¶
type PayloadType string
PayloadType identifies how a webhook payload should be parsed.
const ( PayloadTypeBeebuzz PayloadType = "beebuzz" PayloadTypeCustom PayloadType = "custom" )
type ReceiveResponse ¶
type ReceiveResponse struct {
Status ReceiveStatus `json:"status"`
SentCount int `json:"sent_count"`
TotalCount int `json:"total_count"`
FailedCount int `json:"failed_count"`
}
ReceiveResponse is returned on successful webhook delivery.
type ReceiveStatus ¶
type ReceiveStatus string
ReceiveStatus represents the outcome of a webhook delivery attempt.
const ( ReceiveStatusDelivered ReceiveStatus = "delivered" ReceiveStatusPartial ReceiveStatus = "partial" ReceiveStatusFailed ReceiveStatus = "failed" )
type RegenerateTokenResponse ¶
type RegenerateTokenResponse struct {
Token string `json:"token"`
}
RegenerateTokenResponse is returned when a webhook token is regenerated.
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
Repository provides data access for the webhook domain.
func NewRepository ¶
func NewRepository(db *sqlx.DB) *Repository
NewRepository creates a new webhook repository.
func (*Repository) AddTopic ¶
func (r *Repository) AddTopic(ctx context.Context, webhookID, topicID string) error
AddTopic associates a webhook with a topic.
func (*Repository) Create ¶
func (r *Repository) Create(ctx context.Context, userID, name, description string, payloadType PayloadType, tokenHash, titlePath, bodyPath, priority string) (string, error)
Create inserts a new webhook. tokenHash must be the SHA-256 hash of the raw token.
func (*Repository) CreateWithTopics ¶
func (r *Repository) CreateWithTopics(ctx context.Context, userID, name, description string, payloadType PayloadType, tokenHash, titlePath, bodyPath, priority string, topicIDs []string) (string, error)
CreateWithTopics atomically creates a webhook and its topic associations.
func (*Repository) DeleteTopic ¶
func (r *Repository) DeleteTopic(ctx context.Context, webhookID, topicID string) error
DeleteTopic removes a topic association from a webhook.
func (*Repository) GetByID ¶
GetByID retrieves a webhook by ID and user. Returns nil, nil if not found.
func (*Repository) GetByTokenHash ¶
GetByTokenHash looks up an active webhook by its token hash. Returns nil, nil if not found.
func (*Repository) GetTopicIDs ¶
GetTopicIDs retrieves topic IDs for a webhook.
func (*Repository) GetTopicsWithIDs ¶
func (r *Repository) GetTopicsWithIDs(ctx context.Context, webhookID string) ([]WebhookTopic, error)
GetTopicsWithIDs retrieves topic IDs and names for a webhook.
func (*Repository) Revoke ¶
func (r *Repository) Revoke(ctx context.Context, userID, webhookID string) error
Revoke marks a webhook as inactive.
func (*Repository) TouchLastUsedAt ¶
func (r *Repository) TouchLastUsedAt(ctx context.Context, webhookID string) error
TouchLastUsedAt sets last_used_at to the current time for the given webhook.
func (*Repository) Update ¶
func (r *Repository) Update(ctx context.Context, userID, webhookID, name, description string, payloadType PayloadType, titlePath, bodyPath, priority string) error
Update updates mutable fields of a webhook.
func (*Repository) UpdateTokenHash ¶
func (r *Repository) UpdateTokenHash(ctx context.Context, userID, webhookID, newTokenHash string) error
UpdateTokenHash replaces the token hash for a webhook owned by userID.
func (*Repository) UpdateWithTopics ¶
func (r *Repository) UpdateWithTopics(ctx context.Context, userID, webhookID, name, description string, payloadType PayloadType, titlePath, bodyPath, priority string, topicIDs []string) error
UpdateWithTopics atomically updates a webhook and replaces topic associations.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides webhook business logic.
func NewService ¶
func NewService(repo *Repository, inspectStore *InspectStore, dispatcher Dispatcher, topicValidator TopicValidator, log *slog.Logger) *Service
NewService creates a new webhook service.
func (*Service) CaptureInspectPayload ¶
CaptureInspectPayload attempts to capture a payload for an active inspect session.
func (*Service) CreateInspectSession ¶
func (s *Service) CreateInspectSession(ctx context.Context, userID, name, description, priority string, topics []string, hookURL string) (*InspectSessionResponse, error)
CreateInspectSession creates a new inspect session and returns the raw token and webhook URL.
func (*Service) CreateWebhook ¶
func (s *Service) CreateWebhook(ctx context.Context, userID, name, description string, payloadType PayloadType, titlePath, bodyPath, priority string, topics []string) (string, string, error)
CreateWebhook creates a new webhook and returns the raw token (one-time reveal) and webhook ID.
func (*Service) FinalizeInspect ¶
func (s *Service) FinalizeInspect(ctx context.Context, userID, titlePath, bodyPath string) (string, string, error)
FinalizeInspect creates the actual webhook from a completed inspect session.
func (*Service) GetInspectSession ¶
func (s *Service) GetInspectSession(ctx context.Context, userID string) *InspectSessionStatusResponse
GetInspectSession returns the current inspect session status for the user.
func (*Service) ListWebhooks ¶
ListWebhooks lists all active webhooks for the user.
func (*Service) Receive ¶
func (s *Service) Receive(ctx context.Context, tokenStr string, body []byte, log *slog.Logger) (*ReceiveResponse, error)
Receive validates the token, extracts title/body from the payload, and dispatches notifications.
func (*Service) RegenerateToken ¶
RegenerateToken generates a new token for the given webhook and returns the raw token.
func (*Service) RevokeWebhook ¶
RevokeWebhook revokes a webhook, returning ErrWebhookNotFound if it does not exist.
func (*Service) UpdateWebhook ¶
func (s *Service) UpdateWebhook(ctx context.Context, userID, webhookID, name, description string, payloadType PayloadType, titlePath, bodyPath, priority string, topicIDs []string) error
UpdateWebhook updates a webhook's settings and topic associations.
type TopicValidator ¶
type TopicValidator interface {
ValidateTopicIDs(ctx context.Context, userID string, topicIDs []string) error
}
TopicValidator verifies that topic IDs belong to the given user.
type UpdateWebhookRequest ¶
type UpdateWebhookRequest struct {
Name string `json:"name"`
Description string `json:"description"`
PayloadType PayloadType `json:"payload_type"`
TitlePath string `json:"title_path"`
BodyPath string `json:"body_path"`
Priority string `json:"priority"`
Topics []string `json:"topics"`
}
UpdateWebhookRequest is the request body for PATCH /webhooks/{webhookID}.
func (*UpdateWebhookRequest) Validate ¶
func (r *UpdateWebhookRequest) Validate() []error
Validate validates the update webhook request fields.
type Webhook ¶
type Webhook struct {
ID string `db:"id"`
UserID string `db:"user_id"`
TokenHash string `db:"token_hash"`
Name string `db:"name"`
Description *string `db:"description"`
PayloadType PayloadType `db:"payload_type"`
TitlePath string `db:"title_path"`
BodyPath string `db:"body_path"`
Priority string `db:"priority"`
IsActive bool `db:"is_active"`
RevokedAt *int64 `db:"revoked_at"`
LastUsedAt *int64 `db:"last_used_at"`
CreatedAt int64 `db:"created_at"`
}
Webhook is the DB struct — db tags only.
type WebhookResponse ¶
type WebhookResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
PayloadType PayloadType `json:"payload_type"`
TitlePath string `json:"title_path,omitempty"`
BodyPath string `json:"body_path,omitempty"`
Priority string `json:"priority"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
TopicIDs []string `json:"topic_ids,omitempty"`
}
WebhookResponse is the HTTP response struct — json tags only.
type WebhookTopic ¶
WebhookTopic holds topic ID and name for dispatch — db tags only.
type WebhooksListResponse ¶
type WebhooksListResponse struct {
Data []WebhookResponse `json:"data"`
}
WebhooksListResponse wraps a collection.