handler

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2026 License: AGPL-3.0 Imports: 29 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AdminHandler

type AdminHandler struct {
	Store   *store.Store
	Webhook *service.WebhookService
	Email   *service.EmailService
	Expiry  *service.ExpiryChecker
	Metered *service.MeteredBillingSyncer
}

func (*AdminHandler) AddLicenseAddon

func (h *AdminHandler) AddLicenseAddon(c *gin.Context)

func (*AdminHandler) AnalyticsActivationTrend

func (h *AdminHandler) AnalyticsActivationTrend(c *gin.Context)

func (*AdminHandler) AnalyticsBreakdown

func (h *AdminHandler) AnalyticsBreakdown(c *gin.Context)

func (*AdminHandler) AnalyticsInsights

func (h *AdminHandler) AnalyticsInsights(c *gin.Context)

func (*AdminHandler) AnalyticsSummary

func (h *AdminHandler) AnalyticsSummary(c *gin.Context)

func (*AdminHandler) AnalyticsUsageTop

func (h *AdminHandler) AnalyticsUsageTop(c *gin.Context)

func (*AdminHandler) ChangeLicensePlan

func (h *AdminHandler) ChangeLicensePlan(c *gin.Context)

func (*AdminHandler) CreateAPIKey

func (h *AdminHandler) CreateAPIKey(c *gin.Context)

func (*AdminHandler) CreateAddon

func (h *AdminHandler) CreateAddon(c *gin.Context)

func (*AdminHandler) CreateEntitlement

func (h *AdminHandler) CreateEntitlement(c *gin.Context)

func (*AdminHandler) CreateLicense

func (h *AdminHandler) CreateLicense(c *gin.Context)

func (*AdminHandler) CreatePlan

func (h *AdminHandler) CreatePlan(c *gin.Context)

func (*AdminHandler) CreateProduct

func (h *AdminHandler) CreateProduct(c *gin.Context)

func (*AdminHandler) DeleteAPIKey

func (h *AdminHandler) DeleteAPIKey(c *gin.Context)

func (*AdminHandler) DeleteActivation

func (h *AdminHandler) DeleteActivation(c *gin.Context)

func (*AdminHandler) DeleteAddon

func (h *AdminHandler) DeleteAddon(c *gin.Context)

func (*AdminHandler) DeleteEntitlement

func (h *AdminHandler) DeleteEntitlement(c *gin.Context)

func (*AdminHandler) DeletePlan

func (h *AdminHandler) DeletePlan(c *gin.Context)

func (*AdminHandler) DeleteProduct

func (h *AdminHandler) DeleteProduct(c *gin.Context)

func (*AdminHandler) ExportLicenses

func (h *AdminHandler) ExportLicenses(c *gin.Context)

ExportLicenses exports all licenses as CSV or JSON. GET /api/v1/admin/licenses/export?format=csv&product_id=xxx&status=xxx

func (*AdminHandler) GetEmailTemplates

func (h *AdminHandler) GetEmailTemplates(c *gin.Context)

GetEmailTemplates returns all email templates (custom from DB + hardcoded defaults).

func (*AdminHandler) GetLicense

func (h *AdminHandler) GetLicense(c *gin.Context)

func (*AdminHandler) GetPlan

func (h *AdminHandler) GetPlan(c *gin.Context)

func (*AdminHandler) GetProduct

func (h *AdminHandler) GetProduct(c *gin.Context)

func (*AdminHandler) GetSettings

func (h *AdminHandler) GetSettings(c *gin.Context)

func (*AdminHandler) GetUserDetail

func (h *AdminHandler) GetUserDetail(c *gin.Context)

func (*AdminHandler) InviteTeamMember

func (h *AdminHandler) InviteTeamMember(c *gin.Context)

InviteTeamMember promotes an existing user to admin, or creates a placeholder admin user. Only owners can invite new admins.

func (*AdminHandler) ListAPIKeys

func (h *AdminHandler) ListAPIKeys(c *gin.Context)

func (*AdminHandler) ListAddons

func (h *AdminHandler) ListAddons(c *gin.Context)

func (*AdminHandler) ListAnalytics

func (h *AdminHandler) ListAnalytics(c *gin.Context)

func (*AdminHandler) ListAuditLogs

func (h *AdminHandler) ListAuditLogs(c *gin.Context)

func (*AdminHandler) ListFloatingSessions

func (h *AdminHandler) ListFloatingSessions(c *gin.Context)

func (*AdminHandler) ListLicenseAddons

func (h *AdminHandler) ListLicenseAddons(c *gin.Context)

func (*AdminHandler) ListLicenseSeats

func (h *AdminHandler) ListLicenseSeats(c *gin.Context)

func (*AdminHandler) ListLicenseUsage

func (h *AdminHandler) ListLicenseUsage(c *gin.Context)

func (*AdminHandler) ListLicenses

func (h *AdminHandler) ListLicenses(c *gin.Context)

func (*AdminHandler) ListPlans

func (h *AdminHandler) ListPlans(c *gin.Context)

func (*AdminHandler) ListProducts

func (h *AdminHandler) ListProducts(c *gin.Context)

func (*AdminHandler) ListTeamMembers

func (h *AdminHandler) ListTeamMembers(c *gin.Context)

ListTeamMembers returns all platform admins (owner + admin roles).

func (*AdminHandler) ListUsers

func (h *AdminHandler) ListUsers(c *gin.Context)

func (*AdminHandler) RefundLicense

func (h *AdminHandler) RefundLicense(c *gin.Context)

func (*AdminHandler) ReinstateLicense

func (h *AdminHandler) ReinstateLicense(c *gin.Context)

func (*AdminHandler) RemoveLicenseAddon

func (h *AdminHandler) RemoveLicenseAddon(c *gin.Context)

func (*AdminHandler) RemoveTeamMember

func (h *AdminHandler) RemoveTeamMember(c *gin.Context)

RemoveTeamMember demotes an admin back to regular user. Only owners can remove admins. Cannot remove the last owner.

func (*AdminHandler) ResetLicenseUsage

func (h *AdminHandler) ResetLicenseUsage(c *gin.Context)

func (*AdminHandler) RevokeLicense

func (h *AdminHandler) RevokeLicense(c *gin.Context)

func (*AdminHandler) RotateAPIKey added in v0.1.1

func (h *AdminHandler) RotateAPIKey(c *gin.Context)

RotateAPIKey generates a new secret for an existing key. The old secret stops working immediately — pre-launch we don't ship a grace period because rolling two valid secrets at once doubles the blast radius if either leaks during the rotation window.

The key ID is stable so callers can update their config without touching the row's name / scopes / product_id.

func (*AdminHandler) RunExpiryChecks added in v0.1.1

func (h *AdminHandler) RunExpiryChecks(c *gin.Context)

RunExpiryChecks triggers one full pass of the lifecycle checker on demand. Useful for admins (apply new grace_days immediately, debug "did expiry mailer run last night?") and for end-to-end tests of the expiring / dunning / renewal email paths that are otherwise on an hourly cron.

func (*AdminHandler) RunMeteredSync added in v0.1.1

func (h *AdminHandler) RunMeteredSync(c *gin.Context)

RunMeteredSync triggers one drain pass of the Stripe meter-event queue on demand. Useful for operators who just attached an entitlement to a Stripe meter and want to ship the backlog immediately, and for end-to-end tests that don't want to wait for the 5-minute loop.

func (*AdminHandler) SendTestEmail

func (h *AdminHandler) SendTestEmail(c *gin.Context)

SendTestEmail sends a real test message through the configured SMTP server so the admin can verify host/port/credentials end-to-end. Body: { "to": "user@example.com" } — optional; defaults to the logged-in admin's own email address.

func (*AdminHandler) Stats

func (h *AdminHandler) Stats(c *gin.Context)

func (*AdminHandler) SuspendLicense

func (h *AdminHandler) SuspendLicense(c *gin.Context)

func (*AdminHandler) UpdateAddon

func (h *AdminHandler) UpdateAddon(c *gin.Context)

func (*AdminHandler) UpdateEntitlement

func (h *AdminHandler) UpdateEntitlement(c *gin.Context)

func (*AdminHandler) UpdatePlan

func (h *AdminHandler) UpdatePlan(c *gin.Context)

func (*AdminHandler) UpdateProduct

func (h *AdminHandler) UpdateProduct(c *gin.Context)

func (*AdminHandler) UpdateSettings

func (h *AdminHandler) UpdateSettings(c *gin.Context)

type AuthHandler added in v0.1.1

type AuthHandler struct {
	Store  *store.Store
	Config *config.Config
	Email  *service.EmailService
}

func (*AuthHandler) AcceptInvite added in v0.1.1

func (h *AuthHandler) AcceptInvite(svc *service.SeatService) gin.HandlerFunc

AcceptInvite consumes a seat-invite token and, on success, ALSO issues a session for the invitee. Reasoning: the plain token in the email is proof of email ownership (we mailed it there), so requiring the invitee to *separately* OTP themselves in after clicking the link is theater — and bad UX. They'd hit /login and have to round-trip through the same mailbox. By issuing a session here, "click link → land in portal" is one step.

Service is provided as a parameter rather than as a field so we don't have to widen AuthHandler's surface; main.go closes over it.

func (*AuthHandler) DevLogin added in v0.1.1

func (h *AuthHandler) DevLogin(c *gin.Context)

DevLogin is a development-only endpoint that creates a session without email OTP. Security: This endpoint is ONLY available when BOTH conditions are met:

  1. ENVIRONMENT is explicitly set to "development"
  2. The server is NOT listening on a public interface (checked via BASE_URL)

This prevents accidental exposure in production deployments.

func (*AuthHandler) Logout added in v0.1.1

func (h *AuthHandler) Logout(c *gin.Context)

func (*AuthHandler) Me added in v0.1.1

func (h *AuthHandler) Me(c *gin.Context)

func (*AuthHandler) OTPSend added in v0.1.1

func (h *AuthHandler) OTPSend(c *gin.Context)

OTPSend handles POST /api/v1/auth/otp/send

func (*AuthHandler) OTPVerify added in v0.1.1

func (h *AuthHandler) OTPVerify(c *gin.Context)

OTPVerify handles POST /api/v1/auth/otp/verify

func (*AuthHandler) Providers added in v0.1.1

func (h *AuthHandler) Providers(c *gin.Context)

func (*AuthHandler) Refresh added in v0.1.1

func (h *AuthHandler) Refresh(c *gin.Context)

type EntitlementHandler

type EntitlementHandler struct {
	// contains filtered or unexported fields
}

func NewEntitlementHandler

func NewEntitlementHandler(svc *service.EntitlementService) *EntitlementHandler

func (*EntitlementHandler) Check

func (h *EntitlementHandler) Check(c *gin.Context)

type FloatingHandler

type FloatingHandler struct {
	// contains filtered or unexported fields
}

func NewFloatingHandler

func NewFloatingHandler(svc *service.FloatingService) *FloatingHandler

func (*FloatingHandler) CheckIn

func (h *FloatingHandler) CheckIn(c *gin.Context)

func (*FloatingHandler) CheckOut

func (h *FloatingHandler) CheckOut(c *gin.Context)

func (*FloatingHandler) Heartbeat

func (h *FloatingHandler) Heartbeat(c *gin.Context)

type LicenseHandler

type LicenseHandler struct {
	// contains filtered or unexported fields
}

func NewLicenseHandler

func NewLicenseHandler(svc *service.LicenseService) *LicenseHandler

func (*LicenseHandler) Activate

func (h *LicenseHandler) Activate(c *gin.Context)

func (*LicenseHandler) Deactivate

func (h *LicenseHandler) Deactivate(c *gin.Context)

func (*LicenseHandler) Verify

func (h *LicenseHandler) Verify(c *gin.Context)

type PortalActivationsHandler added in v0.1.1

type PortalActivationsHandler struct {
	// contains filtered or unexported fields
}

PortalActivationsHandler exposes self-service activation management to the license owner (the user matching license.email) OR any accepted seat on the license (admin or member). The "member can also manage activation slots" rule matches the use case: a teammate who lost their laptop must be able to free their own slot without filing a support ticket.

GET    /api/v1/portal/licenses/:license_key/activations
DELETE /api/v1/portal/licenses/:license_key/activations/:activation_id

The classic UX problem this solves: "I lost my old laptop, all 3 activation slots are taken, I can't activate the new machine". Without self-service, that's a customer-support ticket every time.

func NewPortalActivationsHandler added in v0.1.1

func NewPortalActivationsHandler(s *store.Store) *PortalActivationsHandler

func (*PortalActivationsHandler) Delete added in v0.1.1

func (h *PortalActivationsHandler) Delete(c *gin.Context)

DELETE /api/v1/portal/licenses/:license_key/activations/:activation_id

func (*PortalActivationsHandler) List added in v0.1.1

func (h *PortalActivationsHandler) List(c *gin.Context)

GET /api/v1/portal/licenses/:license_key/activations

type ReleaseAdminHandler added in v0.1.1

type ReleaseAdminHandler struct {
	// contains filtered or unexported fields
}

ReleaseAdminHandler exposes admin-only release management endpoints.

Industry-aligned API:

POST   /admin/releases                              Create draft release
GET    /admin/releases                              List releases
GET    /admin/releases/:id                          Get release with artifacts
PATCH  /admin/releases/:id                          Update display name + notes
DELETE /admin/releases/:id                          Delete draft (cascades artifacts)

POST   /admin/releases/:id/artifacts                Add artifact (returns presigned PUT)
POST   /admin/releases/:id/artifacts/:aid/finalize  Finalize artifact upload
DELETE /admin/releases/:id/artifacts/:aid           Delete artifact (draft only)

POST   /admin/releases/:id/actions/publish          Publish (signs all artifacts)
POST   /admin/releases/:id/actions/yank             Yank
POST   /admin/releases/:id/actions/unyank           Unyank

Nested artifact endpoints validate that :aid belongs to :id — a request for a real artifact ID under the wrong release returns 404, not the artifact's data — to avoid IDOR-style cross-release access.

func NewReleaseAdminHandler added in v0.1.1

func NewReleaseAdminHandler(svc *service.ReleaseService, st *store.Store) *ReleaseAdminHandler

func (*ReleaseAdminHandler) AddArtifact added in v0.1.1

func (h *ReleaseAdminHandler) AddArtifact(c *gin.Context)

POST /api/v1/admin/releases/:id/artifacts

Body: { platform, content_type?, expected_size?, filename? }

func (*ReleaseAdminHandler) Create added in v0.1.1

func (h *ReleaseAdminHandler) Create(c *gin.Context)

POST /api/v1/admin/releases

Body: { product_id, version, channel?, name?, release_notes? }

func (*ReleaseAdminHandler) Delete added in v0.1.1

func (h *ReleaseAdminHandler) Delete(c *gin.Context)

DELETE /api/v1/admin/releases/:id (draft only; cascades artifacts).

func (*ReleaseAdminHandler) DeleteArtifact added in v0.1.1

func (h *ReleaseAdminHandler) DeleteArtifact(c *gin.Context)

DELETE /api/v1/admin/releases/:id/artifacts/:aid

func (*ReleaseAdminHandler) FinalizeArtifact added in v0.1.1

func (h *ReleaseAdminHandler) FinalizeArtifact(c *gin.Context)

POST /api/v1/admin/releases/:id/artifacts/:aid/finalize

Body: { expected_sha256? }

The server reads the uploaded bytes from storage and computes the authoritative sha256 itself. expected_sha256 (legacy alias: sha256) is optional — when provided, the server compares it to the computed digest and returns 409 SHA256_MISMATCH on disagreement. Clients should move to expected_sha256; sha256 is accepted for one release cycle.

func (*ReleaseAdminHandler) Get added in v0.1.1

func (h *ReleaseAdminHandler) Get(c *gin.Context)

GET /api/v1/admin/releases/:id

func (*ReleaseAdminHandler) List added in v0.1.1

func (h *ReleaseAdminHandler) List(c *gin.Context)

GET /api/v1/admin/releases

func (*ReleaseAdminHandler) Publish added in v0.1.1

func (h *ReleaseAdminHandler) Publish(c *gin.Context)

POST /api/v1/admin/releases/:id/actions/publish

func (*ReleaseAdminHandler) Unyank added in v0.1.1

func (h *ReleaseAdminHandler) Unyank(c *gin.Context)

POST /api/v1/admin/releases/:id/actions/unyank

func (*ReleaseAdminHandler) Update added in v0.1.1

func (h *ReleaseAdminHandler) Update(c *gin.Context)

PATCH /api/v1/admin/releases/:id

Body: { name?, release_notes? }

Only display fields are mutable post-create. version / channel / status / artifacts are immutable from this endpoint — version & channel are part of the release identity (carve a new release if you need to change them); status moves through dedicated action endpoints.

func (*ReleaseAdminHandler) Yank added in v0.1.1

func (h *ReleaseAdminHandler) Yank(c *gin.Context)

POST /api/v1/admin/releases/:id/actions/yank

Body: { reason }

type ReleasePublicConfig added in v0.1.1

type ReleasePublicConfig struct {
	Service     *service.ReleaseService
	Store       *store.Store
	Storage     storage.Storage
	Logger      *slog.Logger
	BaseURL     string
	DownloadTTL time.Duration
}

type ReleasePublicHandler added in v0.1.1

type ReleasePublicHandler struct {
	// contains filtered or unexported fields
}

ReleasePublicHandler exposes the endpoints clients use:

POST /api/v1/license/download                              license-gated download URL
GET  /api/v1/releases/:product_slug/feed.xml               Sparkle appcast (per-platform)
GET  /api/v1/releases/:product_slug/feed.json              Velopack feed (per-platform)
GET  /api/v1/releases/:product_slug/upgrade.json           Tauri manifest (single latest)

Auth model: feeds are PUBLIC for every channel — stable, beta, alpha, dev. Industry convention (Sparkle / Tauri / npm / GitHub Releases): trust = the artifact's Ed25519 signature, NOT URL secrecy. Genuinely private builds belong on internal CI/CD distribution (private R2 bucket, TestFlight, Firebase App Distribution); they don't ship through these feeds at all.

License gating happens at app start (the SDK calls /license/verify), not at update time. License rotation never bricks installed clients.

func NewReleasePublicHandler added in v0.1.1

func NewReleasePublicHandler(c ReleasePublicConfig) *ReleasePublicHandler

func (*ReleasePublicHandler) Download added in v0.1.1

func (h *ReleasePublicHandler) Download(c *gin.Context)

POST /api/v1/license/download

Body: { license_key, platform, version?, channel? }

func (*ReleasePublicHandler) FeedSparkle added in v0.1.1

func (h *ReleasePublicHandler) FeedSparkle(c *gin.Context)

GET /api/v1/releases/:product_slug/feed.xml — Sparkle appcast

func (*ReleasePublicHandler) FeedTauri added in v0.1.1

func (h *ReleasePublicHandler) FeedTauri(c *gin.Context)

GET /api/v1/releases/:product_slug/upgrade.json — Tauri (single-release manifest)

func (*ReleasePublicHandler) FeedVelopack added in v0.1.1

func (h *ReleasePublicHandler) FeedVelopack(c *gin.Context)

GET /api/v1/releases/:product_slug/feed.json — Velopack feed

type ReleaseSigningAdminHandler added in v0.1.1

type ReleaseSigningAdminHandler struct {
	// contains filtered or unexported fields
}

ReleaseSigningAdminHandler exposes admin-only signing key management.

Operational note: the API never returns the encrypted private key, only the public key and metadata. Callers (the admin UI) embed the public key into client app binaries; the private key never leaves the server.

func NewReleaseSigningAdminHandler added in v0.1.1

func NewReleaseSigningAdminHandler(svc *service.ReleaseSigningService, st *store.Store) *ReleaseSigningAdminHandler

func (*ReleaseSigningAdminHandler) Deactivate added in v0.1.1

func (h *ReleaseSigningAdminHandler) Deactivate(c *gin.Context)

DELETE /api/v1/admin/products/:id/signing-key

Deactivates the current active key without creating a replacement. Future releases will be unsigned until a new key is generated.

Request body: { "note": "..." } // optional

func (*ReleaseSigningAdminHandler) DownloadPublicKey added in v0.1.1

func (h *ReleaseSigningAdminHandler) DownloadPublicKey(c *gin.Context)

GET /api/v1/admin/products/:id/signing-key/public.pem

Returns the active public key as a PEM document for direct download. Operators embed this file in their client app source tree (e.g. public_key.pem next to Sparkle's Info.plist or Tauri's tauri.conf.json).

func (*ReleaseSigningAdminHandler) DownloadPublicKeyTauri added in v0.1.1

func (h *ReleaseSigningAdminHandler) DownloadPublicKeyTauri(c *gin.Context)

GET /api/v1/admin/products/:id/signing-key/tauri-pubkey

Returns the active public key in Tauri's minisign-wrapped format (base64 of "Ed" + 8-byte key_id + 32-byte raw key). Tauri's `tauri.conf.json -> bundle.updater.pubkey` field expects exactly this shape; the raw PEM/Sparkle key fails Tauri's verifier.

func (*ReleaseSigningAdminHandler) Generate added in v0.1.1

func (h *ReleaseSigningAdminHandler) Generate(c *gin.Context)

POST /api/v1/admin/products/:id/signing-key

Generates a fresh keypair for the product. Fails 409 if an active key already exists; the admin must rotate instead.

func (*ReleaseSigningAdminHandler) List added in v0.1.1

GET /api/v1/admin/products/:id/signing-keys

Returns the full signing-key history for a product. Active key first, then inactive sorted by creation time desc.

func (*ReleaseSigningAdminHandler) Rotate added in v0.1.1

func (h *ReleaseSigningAdminHandler) Rotate(c *gin.Context)

POST /api/v1/admin/products/:id/signing-key/rotate

Request body: { "note": "..." } // optional but recommended

Generates a new active key and deactivates the previous one (if any).

type SeatHandler

type SeatHandler struct {
	// contains filtered or unexported fields
}

func NewSeatHandler

func NewSeatHandler(svc *service.SeatService) *SeatHandler

func (*SeatHandler) AcceptInvite added in v0.1.1

func (h *SeatHandler) AcceptInvite(c *gin.Context)

AcceptInvite consumes the plain token shipped in the seat-invite email and binds the seat to a user account (creating one keyed off the seat email if necessary).

Auth-free: the token IS the proof of email ownership. We deliberately don't accept the email from the request — using the token's stored seat.email guarantees the inviter's intent.

func (*SeatHandler) AddSeat

func (h *SeatHandler) AddSeat(c *gin.Context)

func (*SeatHandler) ListSeats

func (h *SeatHandler) ListSeats(c *gin.Context)

func (*SeatHandler) RemoveSeat

func (h *SeatHandler) RemoveSeat(c *gin.Context)

type SetupHandler

type SetupHandler struct {
	Store *store.Store
}

SetupHandler manages the first-run setup wizard.

func NewSetupHandler

func NewSetupHandler(s *store.Store) *SetupHandler

func (*SetupHandler) Initialize

func (h *SetupHandler) Initialize(c *gin.Context)

Initialize completes setup in one call. This is the ONLY endpoint that allows creating the first owner without authentication. POST /api/v1/setup/initialize

func (*SetupHandler) Status

func (h *SetupHandler) Status(c *gin.Context)

Status returns whether setup is needed and which step the wizard is on. GET /api/v1/setup/status

type SystemHandler

type SystemHandler struct {
	Store *store.Store

	RepoOwner string
	RepoName  string
	// contains filtered or unexported fields
}

func NewSystemHandler

func NewSystemHandler(s *store.Store) *SystemHandler

func (*SystemHandler) CheckUpdate

func (h *SystemHandler) CheckUpdate(c *gin.Context)

CheckUpdate checks GitHub for a newer release. Results are cached for 1 hour. On startup, the background checker calls this periodically so the dashboard always shows fresh update status without the admin clicking anything.

func (*SystemHandler) GetMigrationStatus

func (h *SystemHandler) GetMigrationStatus(c *gin.Context)

func (*SystemHandler) GetVersion

func (h *SystemHandler) GetVersion(c *gin.Context)

func (*SystemHandler) StartAutoCheck

func (h *SystemHandler) StartAutoCheck(done <-chan struct{})

StartAutoCheck runs a background loop that checks for updates every 6 hours. The result is cached so the admin dashboard always has fresh data.

type UsageHandler

type UsageHandler struct {
	// contains filtered or unexported fields
}

func NewUsageHandler

func NewUsageHandler(svc *service.UsageService) *UsageHandler

func (*UsageHandler) GetQuotaStatus

func (h *UsageHandler) GetQuotaStatus(c *gin.Context)

func (*UsageHandler) RecordUsage

func (h *UsageHandler) RecordUsage(c *gin.Context)

type WebhookAdminHandler

type WebhookAdminHandler struct {
	Store   *store.Store
	Webhook *service.WebhookService
}

func NewWebhookAdminHandler

func NewWebhookAdminHandler(s *store.Store, wh *service.WebhookService) *WebhookAdminHandler

func (*WebhookAdminHandler) CreateWebhook

func (h *WebhookAdminHandler) CreateWebhook(c *gin.Context)

func (*WebhookAdminHandler) DeleteWebhook

func (h *WebhookAdminHandler) DeleteWebhook(c *gin.Context)

func (*WebhookAdminHandler) GetDelivery added in v0.1.1

func (h *WebhookAdminHandler) GetDelivery(c *gin.Context)

GET /admin/webhooks/:id/deliveries/:delivery_id

Detail view used by the admin UI to show the full payload + raw response body for diagnosing a failed delivery.

func (*WebhookAdminHandler) ListDeliveries

func (h *WebhookAdminHandler) ListDeliveries(c *gin.Context)

func (*WebhookAdminHandler) ListWebhooks

func (h *WebhookAdminHandler) ListWebhooks(c *gin.Context)

func (*WebhookAdminHandler) ResendDelivery added in v0.1.1

func (h *WebhookAdminHandler) ResendDelivery(c *gin.Context)

POST /admin/webhooks/:id/deliveries/:delivery_id/resend

Manual re-fire of a previous delivery. Common during integration: the receiver was down / mis-configured and the admin wants to replay an event without trying to recreate the original action. The replay carries the SAME payload bytes (so receiver-side idempotency keys still match) but a fresh X-Keygate-Delivery and a new row in the deliveries table so retry counters are clean.

func (*WebhookAdminHandler) TestWebhook

func (h *WebhookAdminHandler) TestWebhook(c *gin.Context)

func (*WebhookAdminHandler) UpdateWebhook

func (h *WebhookAdminHandler) UpdateWebhook(c *gin.Context)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL