Documentation
¶
Overview ¶
Package webhook is an Arandu module for webhooks both ways, as spatie/laravel-webhook-server and spatie/laravel-webhook-client are in Laravel, in one package.
Sending: endpoints a tenant subscribes to events, each with a sealed signing secret and sealed extra headers; the events outbox delivers to them through hesape/webhook -- one durable record and one queued job per event and endpoint, a signed request through a transport that refuses private addresses, retries with backoff and Retry-After. Outgoing builds a call in code, as webhook-server's WebhookCall. An endpoint signs with hesape's scheme or adds webhook-server's DefaultSigner: the hex HMAC-SHA256 of the body.
Receiving: a Receiver per system that calls the application, mounted at ReceivePrefix/<name>, as webhook-client's configs. A call is checked against its signature, offered to the Profile, stored with the headers the receiver keeps, and processed on the queue by the receiver's Processor; the sender gets the Responder's answer at once. Old calls are cleaned on a schedule.
The files are laid out by role:
module.go -> registration, routes, handlers, jobs, schedule, migrations config.go -> what the application passes in model.go -> the endpoint, the received call, the delivery record policy.go -> who may do what service.go -> the use cases, and Model access after authorization server.go -> sending: the Manager underneath, Outgoing, the resolver client.go -> receiving: the pipeline and its processing job signature.go -> the signers, the validators and the seal
Index ¶
- Constants
- Variables
- func Actions() []security.Action
- func SignBody(secret []byte, body []byte) string
- type Arandu
- type Call
- func (c Call) Body() []byte
- func (c *Call) Failed(err error, now time.Time)
- func (c Call) Form() (url.Values, error)
- func (row *Call) Fresh(ctx context.Context, g auth.Grant, with ...string) (*Call, error)
- func (c Call) Header(name string) string
- func (c Call) Headers() map[string][]string
- func (c Call) JSON(v any) error
- func (c *Call) Processed(now time.Time)
- func (row *Call) Replicate(except ...string) (*Call, error)
- type CallCollection
- func (c CallCollection) Contains(key any) bool
- func (c CallCollection) Except(keys ...any) CallCollection
- func (c CallCollection) Find(key any) *Call
- func (c CallCollection) FindOrFail(key any) (*Call, error)
- func (c CallCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (CallCollection, error)
- func (c CallCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error
- func (c CallCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error
- func (c CallCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error
- func (c CallCollection) ModelKeys() []any
- func (c CallCollection) Only(keys ...any) CallCollection
- func (c CallCollection) Pluck(column string) []any
- func (c CallCollection) Rows() model.Rows
- func (c CallCollection) ToArray() []map[string]any
- func (c CallCollection) Unique() CallCollection
- type CallFilter
- type CallPolicy
- type CallQuery
- func (q *CallQuery) AddSelect(columns ...any) *CallQuery
- func (q *CallQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *CallQuery) Base() *model.Builder
- func (q *CallQuery) Chunk(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *CallQuery) Clone() *CallQuery
- func (q *CallQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)
- func (q *CallQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Call, error)
- func (q *CallQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Call, error]
- func (q *CallQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, ...) (CallCollection, *pagination.CursorPage, error)
- func (q *CallQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *CallQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)
- func (q *CallQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)
- func (q *CallQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) Each(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *CallQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)
- func (q *CallQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Call, error)
- func (q *CallQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (CallCollection, error)
- func (q *CallQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Call, error)
- func (q *CallQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Call, error)
- func (q *CallQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Call, error)
- func (q *CallQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Call, error)
- func (q *CallQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Call, error)
- func (q *CallQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Call, error)
- func (q *CallQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Call, error)
- func (q *CallQuery) ForPage(page, perPage int) *CallQuery
- func (q *CallQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Call, error)
- func (q *CallQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (CallCollection, error)
- func (q *CallQuery) GroupBy(groups ...any) *CallQuery
- func (q *CallQuery) Has(relation, operator string, count int, boolean string, ...) *CallQuery
- func (q *CallQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *CallQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *CallQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *CallQuery) Join(table any, first any, args ...any) *CallQuery
- func (q *CallQuery) Latest(column ...string) *CallQuery
- func (q *CallQuery) Limit(value int) *CallQuery
- func (q *CallQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *CallQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *CallQuery) New() (*Call, error)
- func (q *CallQuery) Offset(value int) *CallQuery
- func (q *CallQuery) Oldest(column ...string) *CallQuery
- func (q *CallQuery) OrDoesntHave(relation string) *CallQuery
- func (q *CallQuery) OrHas(relation, operator string, count int) *CallQuery
- func (q *CallQuery) OrWhere(column any, args ...any) *CallQuery
- func (q *CallQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) OrWhereHas(relation string, callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) OrWhereNot(column any, args ...any) *CallQuery
- func (q *CallQuery) OrWhereRelation(relation string, column any, args ...any) *CallQuery
- func (q *CallQuery) OrderBy(column any, direction ...string) *CallQuery
- func (q *CallQuery) OrderByDesc(column any) *CallQuery
- func (q *CallQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (CallCollection, *pagination.LengthAwarePage, error)
- func (q *CallQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)
- func (q *CallQuery) Select(columns ...any) *CallQuery
- func (q *CallQuery) SelectRaw(expression string, bindings ...any) *CallQuery
- func (q *CallQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (CallCollection, *pagination.Page, error)
- func (q *CallQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Call, error)
- func (q *CallQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *CallQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *CallQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)
- func (q *CallQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
- func (q *CallQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Call, error)
- func (q *CallQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, ...) (int64, error)
- func (q *CallQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *CallQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *CallQuery) Where(column any, args ...any) *CallQuery
- func (q *CallQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *CallQuery
- func (q *CallQuery) WhereBetween(column any, from, to any) *CallQuery
- func (q *CallQuery) WhereColumn(first any, args ...any) *CallQuery
- func (q *CallQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) WhereExists(callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) WhereHas(relation string, callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *CallQuery
- func (q *CallQuery) WhereIn(column any, values []any) *CallQuery
- func (q *CallQuery) WhereKey(id any) *CallQuery
- func (q *CallQuery) WhereNot(column any, args ...any) *CallQuery
- func (q *CallQuery) WhereNotExists(callback func(*query.Builder)) *CallQuery
- func (q *CallQuery) WhereNotIn(column any, values []any) *CallQuery
- func (q *CallQuery) WhereNotNull(columns ...any) *CallQuery
- func (q *CallQuery) WhereNull(columns ...any) *CallQuery
- func (q *CallQuery) WhereRelation(relation string, column any, args ...any) *CallQuery
- func (q *CallQuery) With(relations ...string) *CallQuery
- func (q *CallQuery) WithAvg(relation, column string) *CallQuery
- func (q *CallQuery) WithCount(relations ...string) *CallQuery
- func (q *CallQuery) WithExists(relation string) *CallQuery
- func (q *CallQuery) WithMax(relation, column string) *CallQuery
- func (q *CallQuery) WithMin(relation, column string) *CallQuery
- func (q *CallQuery) WithSum(relation, column string) *CallQuery
- func (q *CallQuery) Without(relations ...string) *CallQuery
- func (q *CallQuery) WithoutGlobalScope(identifier string) *CallQuery
- func (q *CallQuery) WithoutGlobalScopes(identifiers ...string) *CallQuery
- type CallResource
- type CallService
- func (s *CallService) Find(ctx context.Context, actor security.Subject, id string) (*Call, error)
- func (s *CallService) List(ctx context.Context, actor security.Subject, filter CallFilter, q data.Query) ([]*Call, error)
- func (s *CallService) Process(ctx context.Context, actor security.Subject, id string) error
- type CallStatus
- type Config
- type Delivery
- type DeliveryCollection
- func (c DeliveryCollection) Contains(key any) bool
- func (c DeliveryCollection) Except(keys ...any) DeliveryCollection
- func (c DeliveryCollection) Find(key any) *Delivery
- func (c DeliveryCollection) FindOrFail(key any) (*Delivery, error)
- func (c DeliveryCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (DeliveryCollection, error)
- func (c DeliveryCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error
- func (c DeliveryCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error
- func (c DeliveryCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error
- func (c DeliveryCollection) ModelKeys() []any
- func (c DeliveryCollection) Only(keys ...any) DeliveryCollection
- func (c DeliveryCollection) Pluck(column string) []any
- func (c DeliveryCollection) Rows() model.Rows
- func (c DeliveryCollection) ToArray() []map[string]any
- func (c DeliveryCollection) Unique() DeliveryCollection
- type DeliveryQuery
- func (q *DeliveryQuery) AddSelect(columns ...any) *DeliveryQuery
- func (q *DeliveryQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *DeliveryQuery) Base() *model.Builder
- func (q *DeliveryQuery) Chunk(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *DeliveryQuery) Clone() *DeliveryQuery
- func (q *DeliveryQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)
- func (q *DeliveryQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Delivery, error)
- func (q *DeliveryQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Delivery, error]
- func (q *DeliveryQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, ...) (DeliveryCollection, *pagination.CursorPage, error)
- func (q *DeliveryQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *DeliveryQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)
- func (q *DeliveryQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)
- func (q *DeliveryQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) Each(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *DeliveryQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)
- func (q *DeliveryQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (DeliveryCollection, error)
- func (q *DeliveryQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Delivery, error)
- func (q *DeliveryQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Delivery, error)
- func (q *DeliveryQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Delivery, error)
- func (q *DeliveryQuery) ForPage(page, perPage int) *DeliveryQuery
- func (q *DeliveryQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Delivery, error)
- func (q *DeliveryQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (DeliveryCollection, error)
- func (q *DeliveryQuery) GroupBy(groups ...any) *DeliveryQuery
- func (q *DeliveryQuery) Has(relation, operator string, count int, boolean string, ...) *DeliveryQuery
- func (q *DeliveryQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *DeliveryQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *DeliveryQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *DeliveryQuery) Join(table any, first any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) Latest(column ...string) *DeliveryQuery
- func (q *DeliveryQuery) Limit(value int) *DeliveryQuery
- func (q *DeliveryQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *DeliveryQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *DeliveryQuery) New() (*Delivery, error)
- func (q *DeliveryQuery) Offset(value int) *DeliveryQuery
- func (q *DeliveryQuery) Oldest(column ...string) *DeliveryQuery
- func (q *DeliveryQuery) OrDoesntHave(relation string) *DeliveryQuery
- func (q *DeliveryQuery) OrHas(relation, operator string, count int) *DeliveryQuery
- func (q *DeliveryQuery) OrWhere(column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) OrWhereHas(relation string, callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) OrWhereNot(column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) OrWhereRelation(relation string, column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) OrderBy(column any, direction ...string) *DeliveryQuery
- func (q *DeliveryQuery) OrderByDesc(column any) *DeliveryQuery
- func (q *DeliveryQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (DeliveryCollection, *pagination.LengthAwarePage, error)
- func (q *DeliveryQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)
- func (q *DeliveryQuery) Select(columns ...any) *DeliveryQuery
- func (q *DeliveryQuery) SelectRaw(expression string, bindings ...any) *DeliveryQuery
- func (q *DeliveryQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (DeliveryCollection, *pagination.Page, error)
- func (q *DeliveryQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Delivery, error)
- func (q *DeliveryQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *DeliveryQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *DeliveryQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)
- func (q *DeliveryQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
- func (q *DeliveryQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Delivery, error)
- func (q *DeliveryQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, ...) (int64, error)
- func (q *DeliveryQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *DeliveryQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *DeliveryQuery) Where(column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *DeliveryQuery
- func (q *DeliveryQuery) WhereBetween(column any, from, to any) *DeliveryQuery
- func (q *DeliveryQuery) WhereColumn(first any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) WhereExists(callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) WhereHas(relation string, callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *DeliveryQuery
- func (q *DeliveryQuery) WhereIn(column any, values []any) *DeliveryQuery
- func (q *DeliveryQuery) WhereKey(id any) *DeliveryQuery
- func (q *DeliveryQuery) WhereNot(column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) WhereNotExists(callback func(*query.Builder)) *DeliveryQuery
- func (q *DeliveryQuery) WhereNotIn(column any, values []any) *DeliveryQuery
- func (q *DeliveryQuery) WhereNotNull(columns ...any) *DeliveryQuery
- func (q *DeliveryQuery) WhereNull(columns ...any) *DeliveryQuery
- func (q *DeliveryQuery) WhereRelation(relation string, column any, args ...any) *DeliveryQuery
- func (q *DeliveryQuery) With(relations ...string) *DeliveryQuery
- func (q *DeliveryQuery) WithAvg(relation, column string) *DeliveryQuery
- func (q *DeliveryQuery) WithCount(relations ...string) *DeliveryQuery
- func (q *DeliveryQuery) WithExists(relation string) *DeliveryQuery
- func (q *DeliveryQuery) WithMax(relation, column string) *DeliveryQuery
- func (q *DeliveryQuery) WithMin(relation, column string) *DeliveryQuery
- func (q *DeliveryQuery) WithSum(relation, column string) *DeliveryQuery
- func (q *DeliveryQuery) Without(relations ...string) *DeliveryQuery
- func (q *DeliveryQuery) WithoutGlobalScope(identifier string) *DeliveryQuery
- func (q *DeliveryQuery) WithoutGlobalScopes(identifiers ...string) *DeliveryQuery
- type DeliveryResource
- type Endpoint
- type EndpointCollection
- func (c EndpointCollection) Contains(key any) bool
- func (c EndpointCollection) Except(keys ...any) EndpointCollection
- func (c EndpointCollection) Find(key any) *Endpoint
- func (c EndpointCollection) FindOrFail(key any) (*Endpoint, error)
- func (c EndpointCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (EndpointCollection, error)
- func (c EndpointCollection) Load(ctx context.Context, g auth.Grant, relations ...string) error
- func (c EndpointCollection) LoadCount(ctx context.Context, g auth.Grant, relations ...string) error
- func (c EndpointCollection) LoadMissing(ctx context.Context, g auth.Grant, relations ...string) error
- func (c EndpointCollection) ModelKeys() []any
- func (c EndpointCollection) Only(keys ...any) EndpointCollection
- func (c EndpointCollection) Pluck(column string) []any
- func (c EndpointCollection) Rows() model.Rows
- func (c EndpointCollection) ToArray() []map[string]any
- func (c EndpointCollection) Unique() EndpointCollection
- type EndpointPolicy
- type EndpointQuery
- func (q *EndpointQuery) AddSelect(columns ...any) *EndpointQuery
- func (q *EndpointQuery) Avg(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *EndpointQuery) Base() *model.Builder
- func (q *EndpointQuery) Chunk(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *EndpointQuery) Clone() *EndpointQuery
- func (q *EndpointQuery) Count(ctx context.Context, g auth.Grant, columns ...any) (int64, error)
- func (q *EndpointQuery) Create(ctx context.Context, g auth.Grant, attributes map[string]any) (*Endpoint, error)
- func (q *EndpointQuery) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[*Endpoint, error]
- func (q *EndpointQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, ...) (EndpointCollection, *pagination.CursorPage, error)
- func (q *EndpointQuery) Decrement(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *EndpointQuery) Delete(ctx context.Context, g auth.Grant) (int64, error)
- func (q *EndpointQuery) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)
- func (q *EndpointQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) Each(ctx context.Context, g auth.Grant, count int, ...) error
- func (q *EndpointQuery) Exists(ctx context.Context, g auth.Grant) (bool, error)
- func (q *EndpointQuery) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (EndpointCollection, error)
- func (q *EndpointQuery) FindOrFail(ctx context.Context, g auth.Grant, id any, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) FindOrNew(ctx context.Context, g auth.Grant, id any, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) First(ctx context.Context, g auth.Grant, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) FirstOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Endpoint, error)
- func (q *EndpointQuery) FirstOrFail(ctx context.Context, g auth.Grant, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) FirstOrNew(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Endpoint, error)
- func (q *EndpointQuery) FirstWhere(ctx context.Context, g auth.Grant, column any, args ...any) (*Endpoint, error)
- func (q *EndpointQuery) ForPage(page, perPage int) *EndpointQuery
- func (q *EndpointQuery) ForceCreate(ctx context.Context, g auth.Grant, attributes map[string]any) (*Endpoint, error)
- func (q *EndpointQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (EndpointCollection, error)
- func (q *EndpointQuery) GroupBy(groups ...any) *EndpointQuery
- func (q *EndpointQuery) Has(relation, operator string, count int, boolean string, ...) *EndpointQuery
- func (q *EndpointQuery) Increment(ctx context.Context, g auth.Grant, column string, amount any, ...) (int64, error)
- func (q *EndpointQuery) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *EndpointQuery) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (q *EndpointQuery) Join(table any, first any, args ...any) *EndpointQuery
- func (q *EndpointQuery) Latest(column ...string) *EndpointQuery
- func (q *EndpointQuery) Limit(value int) *EndpointQuery
- func (q *EndpointQuery) Max(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *EndpointQuery) Min(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *EndpointQuery) New() (*Endpoint, error)
- func (q *EndpointQuery) Offset(value int) *EndpointQuery
- func (q *EndpointQuery) Oldest(column ...string) *EndpointQuery
- func (q *EndpointQuery) OrDoesntHave(relation string) *EndpointQuery
- func (q *EndpointQuery) OrHas(relation, operator string, count int) *EndpointQuery
- func (q *EndpointQuery) OrWhere(column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) OrWhereHas(relation string, callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) OrWhereNot(column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) OrWhereRelation(relation string, column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) OrderBy(column any, direction ...string) *EndpointQuery
- func (q *EndpointQuery) OrderByDesc(column any) *EndpointQuery
- func (q *EndpointQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (EndpointCollection, *pagination.LengthAwarePage, error)
- func (q *EndpointQuery) Pluck(ctx context.Context, g auth.Grant, column string) ([]any, error)
- func (q *EndpointQuery) Select(columns ...any) *EndpointQuery
- func (q *EndpointQuery) SelectRaw(expression string, bindings ...any) *EndpointQuery
- func (q *EndpointQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, ...) (EndpointCollection, *pagination.Page, error)
- func (q *EndpointQuery) Sole(ctx context.Context, g auth.Grant, columns ...any) (*Endpoint, error)
- func (q *EndpointQuery) SoleValue(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *EndpointQuery) Sum(ctx context.Context, g auth.Grant, column any) (any, error)
- func (q *EndpointQuery) Touch(ctx context.Context, g auth.Grant, column ...string) (int64, error)
- func (q *EndpointQuery) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
- func (q *EndpointQuery) UpdateOrCreate(ctx context.Context, g auth.Grant, attributes, values map[string]any) (*Endpoint, error)
- func (q *EndpointQuery) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, ...) (int64, error)
- func (q *EndpointQuery) Value(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *EndpointQuery) ValueOrFail(ctx context.Context, g auth.Grant, column string) (any, error)
- func (q *EndpointQuery) Where(column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *EndpointQuery
- func (q *EndpointQuery) WhereBetween(column any, from, to any) *EndpointQuery
- func (q *EndpointQuery) WhereColumn(first any, args ...any) *EndpointQuery
- func (q *EndpointQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) WhereExists(callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) WhereHas(relation string, callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *EndpointQuery
- func (q *EndpointQuery) WhereIn(column any, values []any) *EndpointQuery
- func (q *EndpointQuery) WhereKey(id any) *EndpointQuery
- func (q *EndpointQuery) WhereNot(column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) WhereNotExists(callback func(*query.Builder)) *EndpointQuery
- func (q *EndpointQuery) WhereNotIn(column any, values []any) *EndpointQuery
- func (q *EndpointQuery) WhereNotNull(columns ...any) *EndpointQuery
- func (q *EndpointQuery) WhereNull(columns ...any) *EndpointQuery
- func (q *EndpointQuery) WhereRelation(relation string, column any, args ...any) *EndpointQuery
- func (q *EndpointQuery) With(relations ...string) *EndpointQuery
- func (q *EndpointQuery) WithAvg(relation, column string) *EndpointQuery
- func (q *EndpointQuery) WithCount(relations ...string) *EndpointQuery
- func (q *EndpointQuery) WithExists(relation string) *EndpointQuery
- func (q *EndpointQuery) WithMax(relation, column string) *EndpointQuery
- func (q *EndpointQuery) WithMin(relation, column string) *EndpointQuery
- func (q *EndpointQuery) WithSum(relation, column string) *EndpointQuery
- func (q *EndpointQuery) Without(relations ...string) *EndpointQuery
- func (q *EndpointQuery) WithoutGlobalScope(identifier string) *EndpointQuery
- func (q *EndpointQuery) WithoutGlobalScopes(identifiers ...string) *EndpointQuery
- type EndpointRequest
- type EndpointResource
- type EndpointService
- func (s *EndpointService) Create(ctx context.Context, actor security.Subject, in EndpointRequest) (*Endpoint, string, error)
- func (s *EndpointService) Delete(ctx context.Context, actor security.Subject, id string) error
- func (s *EndpointService) Deliveries(ctx context.Context, actor security.Subject, id string, limit int) ([]*Delivery, error)
- func (s *EndpointService) Find(ctx context.Context, actor security.Subject, id string) (*Endpoint, error)
- func (s *EndpointService) HeaderNames(ctx context.Context, actor security.Subject, id string) ([]string, error)
- func (s *EndpointService) List(ctx context.Context, actor security.Subject, q data.Query) ([]*Endpoint, error)
- func (s *EndpointService) Secret(ctx context.Context, actor security.Subject, id string) (string, error)
- func (s *EndpointService) Test(ctx context.Context, actor security.Subject, id string) error
- func (s *EndpointService) Update(ctx context.Context, actor security.Subject, id string, in EndpointRequest) (*Endpoint, error)
- type Flag
- type HMAC
- type Module
- func (m *Module) CallService() *CallService
- func (m *Module) EndpointService() *EndpointService
- func (m *Module) Manager() *hwebhook.Manager
- func (m *Module) Migrations() []foundation.Migration
- func (m *Module) Name() string
- func (m *Module) Outgoing() *Outgoing
- func (m *Module) Publisher() events.Publisher
- func (m *Module) ReceivePrefix() string
- func (m *Module) RegisterJobHandlers(worker *queue.Worker) error
- func (m *Module) Routes(r *fhttp.Router)
- func (m *Module) Schedule() []foundation.Task
- type Outgoing
- func (o *Outgoing) Dispatch(ctx context.Context, g security.Grant) error
- func (o *Outgoing) DispatchIf(ctx context.Context, cond bool, g security.Grant) error
- func (o *Outgoing) DispatchUnless(ctx context.Context, cond bool, g security.Grant) error
- func (o *Outgoing) Event(name string) *Outgoing
- func (o *Outgoing) Payload(v any) *Outgoing
- func (o *Outgoing) RawBody(body []byte) *Outgoing
- func (o *Outgoing) SignWithHMAC(header string) *Outgoing
- func (o *Outgoing) URL(u string) *Outgoing
- func (o *Outgoing) UUID(id string) *Outgoing
- func (o *Outgoing) UseSecret(name string) *Outgoing
- func (o *Outgoing) WithHeaders(headers map[string]string) *Outgoing
- type ProcessEverything
- type Processor
- type ProcessorFunc
- type Profile
- type ProfileFunc
- type Receiver
- type RespondOK
- type Responder
- type ResponderFunc
- type Server
- type SignatureValidator
- type SignatureValidatorFunc
Constants ¶
const ( // DefaultPrefix is where the management routes are mounted when Config // leaves Prefix empty. DefaultPrefix = "/webhook" // DefaultReceivePrefix is where the receivers are mounted when Config // leaves ReceivePrefix empty: a receiver named "billing" answers at // /webhooks/billing. DefaultReceivePrefix = "/webhooks" // DefaultPageSize is how many records one page answers with when Config // leaves PageSize at zero. DefaultPageSize = 25 // MaxPageSize is the ceiling PageSize is refused above. MaxPageSize = 200 // DefaultQueue is the queue the deliveries and the processing of received // calls travel on. DefaultQueue = "webhooks" // DefaultUserAgent is what an outgoing call says it is. DefaultUserAgent = "Arandu-Webhook/1.0" // DefaultTimeout is how long an outgoing call may take. DefaultTimeout = 10 * time.Second // DefaultDeleteAfterDays is how old a received call is when the clean // removes it, as webhook-client's delete_after_days. DefaultDeleteAfterDays = 30 // DefaultCleanSpec is when the scheduled clean runs: every day at 03:20. DefaultCleanSpec = "20 3 * * *" // DefaultSignatureHeader is the header a body-HMAC signature travels in, // as webhook-server's and webhook-client's signature_header_name. DefaultSignatureHeader = "Signature" // DefaultMaxBodyBytes is the largest body a receiver reads. DefaultMaxBodyBytes = 1 << 20 // DefaultTries is how many times a received call is processed before it // is left failed. DefaultTries = 3 // MaxHeaders is how many extra headers an endpoint may carry. MaxHeaders = 20 // MinSecretBytes is the shortest signing secret accepted. MinSecretBytes = 32 )
The defaults for the optional settings. They are constants rather than literals inside Config.withDefaults, so the value a reader finds here is the value the package uses.
const ( // SignerArandu signs with hesape/webhook's scheme: X-Arandu-Signature, // sha256= over the timestamp, the delivery id and the body. SignerArandu = "arandu" // SignerHMAC adds webhook-server's DefaultSigner: the hex HMAC-SHA256 of // the body, in the endpoint's SignatureHeader. SignerHMAC = "hmac" )
The signers of an endpoint.
const ( // EndpointView is reading one endpoint, and its deliveries. EndpointView security.Action = "webhook.endpoint.view" // EndpointList is paging through the endpoints. EndpointList security.Action = "webhook.endpoint.list" // EndpointCreate is adding one. EndpointCreate security.Action = "webhook.endpoint.create" // EndpointUpdate is changing one, including turning it off. EndpointUpdate security.Action = "webhook.endpoint.update" // EndpointDelete is removing one. EndpointDelete security.Action = "webhook.endpoint.delete" // EndpointSecret is reading an endpoint's signing secret. EndpointSecret security.Action = "webhook.endpoint.secret" // EndpointTest is sending one webhook.test call to an endpoint. EndpointTest security.Action = "webhook.endpoint.test" // CallView is reading one received call. CallView security.Action = "webhook.call.view" // CallList is paging through the received calls. CallList security.Action = "webhook.call.list" // CallProcess is sending a received call to its processor again. CallProcess security.Action = "webhook.call.process" // CallReceive is storing a call whose signature checked, and CallClean // removing old calls. Nobody holds them: the receiver and the scheduled // clean issue their own Grant for the tenant the application configured, // and the policy refuses them to any subject. CallReceive security.Action = "webhook.call.receive" CallClean security.Action = "webhook.call.clean" )
The actions of the package. Constants rather than strings at the call site: a typo in an action name would silently authorize nothing, or worse, everything. arandu-permission fills a Subject's Actions with them.
const AllEvents = "*"
AllEvents is the subscription to every event.
const DefaultEvent = "webhook.call"
DefaultEvent is the event name of an Outgoing call that names none.
const DefaultTolerance = 5 * time.Minute
DefaultTolerance is how far a signed timestamp may be from now before an Arandu signature is refused as a replay.
const ProcessJob = "webhook.process"
ProcessJob is the queued job that hands a stored call to its receiver's Processor: webhook-client's ProcessWebhookJob.
const TestEvent = "webhook.test"
TestEvent is the event the test button sends.
Variables ¶
var ( // ErrInvalidSignature is a call whose signature does not check, as // webhook-client's InvalidWebhookSignature. It is answered 403: sending // the same bytes again cannot make it valid, so a 5xx would only invite // the sender to retry. ErrInvalidSignature = statusError{/* contains filtered or unexported fields */} // ErrBodyTooLarge is a body above the receiver's MaxBodyBytes. ErrBodyTooLarge = statusError{/* contains filtered or unexported fields */} )
The refusals of a receiver. Each answers the sender with the status it carries and no detail.
var ( // ErrURLNotSet is a call with no address. ErrURLNotSet = errors.New("webhook: the call has no URL") // ErrSecretNotSet is a call with no secret to sign it with. ErrSecretNotSet = errors.New("webhook: the call has no secret: name one of Config.Server.Secrets with UseSecret") // ErrUnknownSecret is a call naming a secret the configuration does not // have. ErrUnknownSecret = errors.New("webhook: no secret of that name in Config.Server.Secrets") // ErrReservedHeader is an extra header the delivery writes itself. ErrReservedHeader = errors.New("webhook: the header is written by the delivery itself") )
The refusals of an Outgoing call, as webhook-server's CouldNotCallWebhook.
var ErrNoReceiver = errors.New("webhook: the call's receiver is not configured any more")
ErrNoReceiver is a call whose receiver the configuration no longer has.
var ErrNotFound = fmt.Errorf("webhook: record not found: %w", model.ErrModelNotFound)
ErrNotFound is returned when no row matches, including when the row exists in another tenant. The two cases are deliberately indistinguishable.
It wraps model.ErrModelNotFound, so the router answers it with 404.
Functions ¶
Types ¶
type Arandu ¶
type Arandu struct {
// HeaderPrefix is the senders' header prefix. Empty means X-Arandu.
HeaderPrefix string
// Tolerance is the accepted clock difference. Zero means
// DefaultTolerance.
Tolerance time.Duration
// Now is the clock, replaceable by a test. Nil is time.Now.
Now func() time.Time
}
Arandu checks hesape/webhook's scheme: the Signature, Timestamp and Delivery-ID headers under HeaderPrefix, sha256= over the timestamp, the delivery id and the body. A timestamp further than Tolerance from now is refused, so a captured call cannot be sent again later.
type Call ¶
type Call struct {
model.Model
ID string `db:"id"`
TenantID string `db:"tenant_id"`
// Name is the receiver it arrived at.
Name string `db:"name"`
// Method and URL are how it arrived.
Method string `db:"method"`
URL string `db:"url"`
// HeaderData is the JSON object of the headers the receiver keeps, by
// lowercase name.
HeaderData string `db:"headers"`
// Payload is the body, exactly as it arrived.
Payload string `db:"payload"`
// Status is where its processing stands.
Status CallStatus `db:"status"`
// Attempts is how many times it was processed.
Attempts int `db:"attempts"`
// Exception is the message of the last processing that failed, empty
// when the last one did not.
Exception string `db:"exception"`
// ProcessedAt is when it was processed; it means something only when
// Status is CallProcessed.
ProcessedAt time.Time `db:"processed_at"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
Call is one webhook another system sent to a receiver of this application: webhook-client's WebhookCall. The body is kept exactly as it arrived, because those are the bytes the signature was checked over.
Calls, CallQuery and CallCollection are generated beside this file, in CallQuery.go, by aru model:build.
func (*Call) Failed ¶
Failed records what the processing answered, as webhook-client's saveException. Only the message is kept: a trace names the application's files, and the call row is read by whoever reads the panel.
func (*Call) Fresh ¶
Fresh reads the row again, as a new Call; it shadows the untyped one the embedded model promotes.
type CallCollection ¶
type CallCollection []*Call
CallCollection is rows of Call, as a query returns them.
func CallCollectionOf ¶
func CallCollectionOf(rows model.Rows) CallCollection
CallCollectionOf converts rows of the table of Call. A nil input is a nil collection.
func (CallCollection) Contains ¶
func (c CallCollection) Contains(key any) bool
func (CallCollection) Except ¶
func (c CallCollection) Except(keys ...any) CallCollection
func (CallCollection) Find ¶
func (c CallCollection) Find(key any) *Call
func (CallCollection) FindOrFail ¶
func (c CallCollection) FindOrFail(key any) (*Call, error)
func (CallCollection) Fresh ¶
func (c CallCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (CallCollection, error)
func (CallCollection) LoadMissing ¶
func (CallCollection) ModelKeys ¶
func (c CallCollection) ModelKeys() []any
func (CallCollection) Only ¶
func (c CallCollection) Only(keys ...any) CallCollection
func (CallCollection) Pluck ¶
func (c CallCollection) Pluck(column string) []any
func (CallCollection) Rows ¶
func (c CallCollection) Rows() model.Rows
Rows converts the collection back to the core's rows.
func (CallCollection) ToArray ¶
func (c CallCollection) ToArray() []map[string]any
func (CallCollection) Unique ¶
func (c CallCollection) Unique() CallCollection
type CallFilter ¶
type CallFilter struct {
// Name is a receiver's name.
Name string
// Status is one of the CallStatus values.
Status CallStatus
}
CallFilter narrows a listing of calls.
type CallPolicy ¶
type CallPolicy struct{}
CallPolicy is the only authority over who reads and reprocesses a received Call.
type CallQuery ¶
type CallQuery struct {
// contains filtered or unexported fields
}
CallQuery is a query on the table of Call.
The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Call rows or a value; there is no way to run one without a Grant.
func Calls ¶
Calls starts a query on the table of Call, through db.
Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.
func (*CallQuery) Base ¶
Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of model.go -- and for the factory, which builds rows through it.
func (*CallQuery) CursorPaginate ¶
func (q *CallQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (CallCollection, *pagination.CursorPage, error)
func (*CallQuery) DoesntExist ¶
func (*CallQuery) DoesntHave ¶
func (*CallQuery) FindOrFail ¶
func (*CallQuery) FirstOrCreate ¶
func (*CallQuery) FirstOrFail ¶
func (*CallQuery) FirstOrNew ¶
func (*CallQuery) FirstWhere ¶
func (*CallQuery) ForceCreate ¶
func (*CallQuery) InsertOrIgnore ¶
func (*CallQuery) New ¶
New returns an empty Call on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.
func (*CallQuery) OrDoesntHave ¶
func (*CallQuery) OrWhere ¶
OrWhere adds an or-where clause; a func(*CallQuery) in place of the column adds a group.
func (*CallQuery) OrWhereDoesntHave ¶
func (*CallQuery) OrWhereHas ¶
func (*CallQuery) OrWhereNot ¶
OrWhereNot adds an or-joined negated where clause, or a negated group.
func (*CallQuery) OrWhereRelation ¶
func (*CallQuery) OrderByDesc ¶
func (*CallQuery) Paginate ¶
func (q *CallQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (CallCollection, *pagination.LengthAwarePage, error)
func (*CallQuery) SimplePaginate ¶
func (q *CallQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (CallCollection, *pagination.Page, error)
func (*CallQuery) UpdateOrCreate ¶
func (*CallQuery) ValueOrFail ¶
func (*CallQuery) Where ¶
Where adds a where clause; a func(*CallQuery) in place of the column adds a group.
func (*CallQuery) WhereBelongsTo ¶
func (*CallQuery) WhereBetween ¶
func (*CallQuery) WhereDoesntHave ¶
func (*CallQuery) WhereExists ¶
func (*CallQuery) WhereHasCount ¶
func (*CallQuery) WhereNotExists ¶
func (*CallQuery) WhereNotNull ¶
func (*CallQuery) WhereRelation ¶
func (*CallQuery) WithExists ¶
func (*CallQuery) WithoutGlobalScope ¶
func (*CallQuery) WithoutGlobalScopes ¶
type CallResource ¶
type CallResource struct {
// contains filtered or unexported fields
}
CallResource is the list of fields one received call may answer with.
func NewCallResource ¶
func NewCallResource(c *Call) CallResource
NewCallResource snapshots one call for the response.
func (CallResource) ToArray ¶
func (r CallResource) ToArray() map[string]any
ToArray returns the fields that may leave, by name.
func (CallResource) With ¶
func (r CallResource) With() map[string]any
With adds nothing beside the fields.
type CallService ¶
type CallService struct {
// contains filtered or unexported fields
}
CallService is the use cases of the receiving side's record: reading the calls, processing one again, and the clean. It owns the database handle; every exported method asks the policy before it reads or writes.
type CallStatus ¶
type CallStatus string
CallStatus is where a received call stands.
const ( // CallReceived is stored and waiting for the queue. CallReceived CallStatus = "received" // CallProcessed is handled. CallProcessed CallStatus = "processed" // CallFailed is the last processing having failed. The queue may still // retry it. CallFailed CallStatus = "failed" )
type Config ¶
type Config struct {
// Prefix is the path the management routes are mounted under. Empty means
// DefaultPrefix.
Prefix string
// PageSize is how many records one page answers with. Zero means
// DefaultPageSize; anything above MaxPageSize is refused.
PageSize int
// Key is the application's key (APP_KEY). The endpoints' signing secrets
// and extra headers are sealed with a key derived from it for this purpose
// alone. Required, at least MinSecretBytes long.
Key []byte
// Server is the sending side.
Server Server
// ReceivePrefix is the path every receiver is mounted under. Empty means
// DefaultReceivePrefix. The application exempts it from the CSRF check,
// because a call from another system carries no session:
//
// middleware.CSRFProtect(csrf, sessions.IDFromRequest, middleware.CSRFExcept(webhookModule.ReceivePrefix()+"/"))
ReceivePrefix string
// Receivers are the receiving side: webhook-client's configs, one per
// system that calls this application.
Receivers []Receiver
// DeleteAfterDays is how old a received call is when the scheduled clean
// removes it. Zero means DefaultDeleteAfterDays.
DeleteAfterDays int
// CleanSpec is the five-field cron expression the clean runs on. Empty
// means DefaultCleanSpec; "-" schedules none.
CleanSpec string
}
Config is what the application passes when it wires this package: the two config files of spatie/laravel-webhook-server and laravel-webhook-client, as one typed struct. A misspelled key in a map is a setting that silently keeps its default; a field that does not exist does not compile.
It names no tenant for the management routes: those sit behind RequireAuth, so their tenant is the one the Grant carries, from the session. A Receiver names its tenant, because a call from another system arrives with no session and its signature is what admits it.
type Delivery ¶
type Delivery struct {
model.Model
ID string `db:"id"`
TenantID string `db:"tenant_id"`
EventID string `db:"event_id"`
EventName string `db:"event_name"`
EndpointID string `db:"endpoint_id"`
URL string `db:"url"`
// Status is pending, processing, delivered or failed.
Status string `db:"status"`
Attempts int64 `db:"attempts"`
// Permanent is a failure retrying cannot fix.
Permanent Flag `db:"permanent"`
ResponseStatus *int64 `db:"response_status"`
LastError *string `db:"last_error"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
DeliveredAt *time.Time `db:"delivered_at"`
}
Delivery is the record hesape/webhook keeps of one call to one endpoint: its status, its attempts, the receiver's last answer. This package reads it and never writes it; the worker does.
Deliveries, DeliveryQuery and DeliveryCollection are generated beside this file, in DeliveryQuery.go, by aru model:build.
type DeliveryCollection ¶
type DeliveryCollection []*Delivery
DeliveryCollection is rows of Delivery, as a query returns them.
func DeliveryCollectionOf ¶
func DeliveryCollectionOf(rows model.Rows) DeliveryCollection
DeliveryCollectionOf converts rows of the table of Delivery. A nil input is a nil collection.
func (DeliveryCollection) Contains ¶
func (c DeliveryCollection) Contains(key any) bool
func (DeliveryCollection) Except ¶
func (c DeliveryCollection) Except(keys ...any) DeliveryCollection
func (DeliveryCollection) Find ¶
func (c DeliveryCollection) Find(key any) *Delivery
func (DeliveryCollection) FindOrFail ¶
func (c DeliveryCollection) FindOrFail(key any) (*Delivery, error)
func (DeliveryCollection) Fresh ¶
func (c DeliveryCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (DeliveryCollection, error)
func (DeliveryCollection) LoadMissing ¶
func (DeliveryCollection) ModelKeys ¶
func (c DeliveryCollection) ModelKeys() []any
func (DeliveryCollection) Only ¶
func (c DeliveryCollection) Only(keys ...any) DeliveryCollection
func (DeliveryCollection) Pluck ¶
func (c DeliveryCollection) Pluck(column string) []any
func (DeliveryCollection) Rows ¶
func (c DeliveryCollection) Rows() model.Rows
Rows converts the collection back to the core's rows.
func (DeliveryCollection) ToArray ¶
func (c DeliveryCollection) ToArray() []map[string]any
func (DeliveryCollection) Unique ¶
func (c DeliveryCollection) Unique() DeliveryCollection
type DeliveryQuery ¶
type DeliveryQuery struct {
// contains filtered or unexported fields
}
DeliveryQuery is a query on the table of Delivery.
The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Delivery rows or a value; there is no way to run one without a Grant.
func Deliveries ¶
func Deliveries(db model.DB) *DeliveryQuery
Deliveries starts a query on the table of Delivery, through db.
Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.
func (*DeliveryQuery) AddSelect ¶
func (q *DeliveryQuery) AddSelect(columns ...any) *DeliveryQuery
func (*DeliveryQuery) Base ¶
func (q *DeliveryQuery) Base() *model.Builder
Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of model.go -- and for the factory, which builds rows through it.
func (*DeliveryQuery) Clone ¶
func (q *DeliveryQuery) Clone() *DeliveryQuery
Clone returns an independent copy of the query.
func (*DeliveryQuery) CursorPaginate ¶
func (q *DeliveryQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (DeliveryCollection, *pagination.CursorPage, error)
func (*DeliveryQuery) DoesntExist ¶
func (*DeliveryQuery) DoesntHave ¶
func (q *DeliveryQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) FindMany ¶
func (q *DeliveryQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (DeliveryCollection, error)
func (*DeliveryQuery) FindOrFail ¶
func (*DeliveryQuery) FirstOrCreate ¶
func (*DeliveryQuery) FirstOrFail ¶
func (*DeliveryQuery) FirstOrNew ¶
func (*DeliveryQuery) FirstWhere ¶
func (*DeliveryQuery) ForPage ¶
func (q *DeliveryQuery) ForPage(page, perPage int) *DeliveryQuery
func (*DeliveryQuery) ForceCreate ¶
func (*DeliveryQuery) Get ¶
func (q *DeliveryQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (DeliveryCollection, error)
Get runs the query and returns the rows.
func (*DeliveryQuery) GroupBy ¶
func (q *DeliveryQuery) GroupBy(groups ...any) *DeliveryQuery
func (*DeliveryQuery) Has ¶
func (q *DeliveryQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) InsertOrIgnore ¶
func (*DeliveryQuery) Join ¶
func (q *DeliveryQuery) Join(table any, first any, args ...any) *DeliveryQuery
func (*DeliveryQuery) Latest ¶
func (q *DeliveryQuery) Latest(column ...string) *DeliveryQuery
func (*DeliveryQuery) Limit ¶
func (q *DeliveryQuery) Limit(value int) *DeliveryQuery
func (*DeliveryQuery) New ¶
func (q *DeliveryQuery) New() (*Delivery, error)
New returns an empty Delivery on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.
func (*DeliveryQuery) Offset ¶
func (q *DeliveryQuery) Offset(value int) *DeliveryQuery
func (*DeliveryQuery) Oldest ¶
func (q *DeliveryQuery) Oldest(column ...string) *DeliveryQuery
func (*DeliveryQuery) OrDoesntHave ¶
func (q *DeliveryQuery) OrDoesntHave(relation string) *DeliveryQuery
func (*DeliveryQuery) OrHas ¶
func (q *DeliveryQuery) OrHas(relation, operator string, count int) *DeliveryQuery
func (*DeliveryQuery) OrWhere ¶
func (q *DeliveryQuery) OrWhere(column any, args ...any) *DeliveryQuery
OrWhere adds an or-where clause; a func(*DeliveryQuery) in place of the column adds a group.
func (*DeliveryQuery) OrWhereDoesntHave ¶
func (q *DeliveryQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) OrWhereHas ¶
func (q *DeliveryQuery) OrWhereHas(relation string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) OrWhereNot ¶
func (q *DeliveryQuery) OrWhereNot(column any, args ...any) *DeliveryQuery
OrWhereNot adds an or-joined negated where clause, or a negated group.
func (*DeliveryQuery) OrWhereRelation ¶
func (q *DeliveryQuery) OrWhereRelation(relation string, column any, args ...any) *DeliveryQuery
func (*DeliveryQuery) OrderBy ¶
func (q *DeliveryQuery) OrderBy(column any, direction ...string) *DeliveryQuery
func (*DeliveryQuery) OrderByDesc ¶
func (q *DeliveryQuery) OrderByDesc(column any) *DeliveryQuery
func (*DeliveryQuery) Paginate ¶
func (q *DeliveryQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (DeliveryCollection, *pagination.LengthAwarePage, error)
func (*DeliveryQuery) Select ¶
func (q *DeliveryQuery) Select(columns ...any) *DeliveryQuery
func (*DeliveryQuery) SelectRaw ¶
func (q *DeliveryQuery) SelectRaw(expression string, bindings ...any) *DeliveryQuery
func (*DeliveryQuery) SimplePaginate ¶
func (q *DeliveryQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (DeliveryCollection, *pagination.Page, error)
func (*DeliveryQuery) UpdateOrCreate ¶
func (*DeliveryQuery) ValueOrFail ¶
func (*DeliveryQuery) Where ¶
func (q *DeliveryQuery) Where(column any, args ...any) *DeliveryQuery
Where adds a where clause; a func(*DeliveryQuery) in place of the column adds a group.
func (*DeliveryQuery) WhereBelongsTo ¶
func (q *DeliveryQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *DeliveryQuery
func (*DeliveryQuery) WhereBetween ¶
func (q *DeliveryQuery) WhereBetween(column any, from, to any) *DeliveryQuery
func (*DeliveryQuery) WhereColumn ¶
func (q *DeliveryQuery) WhereColumn(first any, args ...any) *DeliveryQuery
func (*DeliveryQuery) WhereDoesntHave ¶
func (q *DeliveryQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) WhereExists ¶
func (q *DeliveryQuery) WhereExists(callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) WhereHas ¶
func (q *DeliveryQuery) WhereHas(relation string, callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) WhereHasCount ¶
func (q *DeliveryQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *DeliveryQuery
func (*DeliveryQuery) WhereIn ¶
func (q *DeliveryQuery) WhereIn(column any, values []any) *DeliveryQuery
func (*DeliveryQuery) WhereKey ¶
func (q *DeliveryQuery) WhereKey(id any) *DeliveryQuery
func (*DeliveryQuery) WhereNot ¶
func (q *DeliveryQuery) WhereNot(column any, args ...any) *DeliveryQuery
WhereNot adds a negated where clause, or a negated group.
func (*DeliveryQuery) WhereNotExists ¶
func (q *DeliveryQuery) WhereNotExists(callback func(*query.Builder)) *DeliveryQuery
func (*DeliveryQuery) WhereNotIn ¶
func (q *DeliveryQuery) WhereNotIn(column any, values []any) *DeliveryQuery
func (*DeliveryQuery) WhereNotNull ¶
func (q *DeliveryQuery) WhereNotNull(columns ...any) *DeliveryQuery
func (*DeliveryQuery) WhereNull ¶
func (q *DeliveryQuery) WhereNull(columns ...any) *DeliveryQuery
func (*DeliveryQuery) WhereRelation ¶
func (q *DeliveryQuery) WhereRelation(relation string, column any, args ...any) *DeliveryQuery
func (*DeliveryQuery) With ¶
func (q *DeliveryQuery) With(relations ...string) *DeliveryQuery
func (*DeliveryQuery) WithAvg ¶
func (q *DeliveryQuery) WithAvg(relation, column string) *DeliveryQuery
func (*DeliveryQuery) WithCount ¶
func (q *DeliveryQuery) WithCount(relations ...string) *DeliveryQuery
func (*DeliveryQuery) WithExists ¶
func (q *DeliveryQuery) WithExists(relation string) *DeliveryQuery
func (*DeliveryQuery) WithMax ¶
func (q *DeliveryQuery) WithMax(relation, column string) *DeliveryQuery
func (*DeliveryQuery) WithMin ¶
func (q *DeliveryQuery) WithMin(relation, column string) *DeliveryQuery
func (*DeliveryQuery) WithSum ¶
func (q *DeliveryQuery) WithSum(relation, column string) *DeliveryQuery
func (*DeliveryQuery) Without ¶
func (q *DeliveryQuery) Without(relations ...string) *DeliveryQuery
func (*DeliveryQuery) WithoutGlobalScope ¶
func (q *DeliveryQuery) WithoutGlobalScope(identifier string) *DeliveryQuery
func (*DeliveryQuery) WithoutGlobalScopes ¶
func (q *DeliveryQuery) WithoutGlobalScopes(identifiers ...string) *DeliveryQuery
type DeliveryResource ¶
type DeliveryResource struct {
// contains filtered or unexported fields
}
DeliveryResource is the list of fields one delivery may answer with. The headers, the body and the secret reference stay in the record.
func NewDeliveryResource ¶
func NewDeliveryResource(d *Delivery) DeliveryResource
NewDeliveryResource snapshots one delivery for the response.
func (DeliveryResource) ToArray ¶
func (r DeliveryResource) ToArray() map[string]any
ToArray returns the fields that may leave, by name.
func (DeliveryResource) With ¶
func (r DeliveryResource) With() map[string]any
With adds nothing beside the fields.
type Endpoint ¶
type Endpoint struct {
model.Model
ID string `db:"id"`
TenantID string `db:"tenant_id"`
// Name is what a person calls the endpoint.
Name string `db:"name"`
// URL is the absolute http or https address the calls go to.
URL string `db:"url"`
// Events is the comma-separated list of event names it receives; "*"
// receives every event.
Events string `db:"events"`
// Signer is how its calls are signed: SignerArandu or SignerHMAC.
Signer string `db:"signer"`
// SignatureHeader is the header a SignerHMAC signature travels in.
SignatureHeader string `db:"signature_header"`
// Secret is the sealed signing secret. It never leaves in a response.
Secret string `db:"secret"`
// Headers is the sealed JSON object of extra headers, empty when none.
Headers string `db:"headers"`
// Active is whether it receives events.
Active Flag `db:"active"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
Endpoint is one destination the application sends to: an address, the events it subscribes to, how its calls are signed, and the extra headers they carry. The signing secret and the headers are sealed at rest.
Endpoints, EndpointQuery and EndpointCollection are generated beside this file, in EndpointQuery.go, by aru model:build.
func (*Endpoint) Fresh ¶
Fresh reads the row again, as a new Endpoint; it shadows the untyped one the embedded model promotes.
type EndpointCollection ¶
type EndpointCollection []*Endpoint
EndpointCollection is rows of Endpoint, as a query returns them.
func EndpointCollectionOf ¶
func EndpointCollectionOf(rows model.Rows) EndpointCollection
EndpointCollectionOf converts rows of the table of Endpoint. A nil input is a nil collection.
func (EndpointCollection) Contains ¶
func (c EndpointCollection) Contains(key any) bool
func (EndpointCollection) Except ¶
func (c EndpointCollection) Except(keys ...any) EndpointCollection
func (EndpointCollection) Find ¶
func (c EndpointCollection) Find(key any) *Endpoint
func (EndpointCollection) FindOrFail ¶
func (c EndpointCollection) FindOrFail(key any) (*Endpoint, error)
func (EndpointCollection) Fresh ¶
func (c EndpointCollection) Fresh(ctx context.Context, g auth.Grant, with ...string) (EndpointCollection, error)
func (EndpointCollection) LoadMissing ¶
func (EndpointCollection) ModelKeys ¶
func (c EndpointCollection) ModelKeys() []any
func (EndpointCollection) Only ¶
func (c EndpointCollection) Only(keys ...any) EndpointCollection
func (EndpointCollection) Pluck ¶
func (c EndpointCollection) Pluck(column string) []any
func (EndpointCollection) Rows ¶
func (c EndpointCollection) Rows() model.Rows
Rows converts the collection back to the core's rows.
func (EndpointCollection) ToArray ¶
func (c EndpointCollection) ToArray() []map[string]any
func (EndpointCollection) Unique ¶
func (c EndpointCollection) Unique() EndpointCollection
type EndpointPolicy ¶
type EndpointPolicy struct{}
EndpointPolicy is the only authority over who does what with an Endpoint.
It denies unless the subject of the endpoint's tenant carries the action.
type EndpointQuery ¶
type EndpointQuery struct {
// contains filtered or unexported fields
}
EndpointQuery is a query on the table of Endpoint.
The methods that build return the query, so they chain. The methods that run take a context and an auth.Grant, and return Endpoint rows or a value; there is no way to run one without a Grant.
func Endpoints ¶
func Endpoints(db model.DB) *EndpointQuery
Endpoints starts a query on the table of Endpoint, through db.
Global scopes are on and, unless the table is Global, every statement is filtered by the tenant of the Grant its terminal takes.
func (*EndpointQuery) AddSelect ¶
func (q *EndpointQuery) AddSelect(columns ...any) *EndpointQuery
func (*EndpointQuery) Base ¶
func (q *EndpointQuery) Base() *model.Builder
Base returns the core builder the query forwards to. It is for code in this package -- a local scope in the custom block of model.go -- and for the factory, which builds rows through it.
func (*EndpointQuery) Clone ¶
func (q *EndpointQuery) Clone() *EndpointQuery
Clone returns an independent copy of the query.
func (*EndpointQuery) CursorPaginate ¶
func (q *EndpointQuery) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, opts pagination.Options, columns ...any) (EndpointCollection, *pagination.CursorPage, error)
func (*EndpointQuery) DoesntExist ¶
func (*EndpointQuery) DoesntHave ¶
func (q *EndpointQuery) DoesntHave(relation, boolean string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) FindMany ¶
func (q *EndpointQuery) FindMany(ctx context.Context, g auth.Grant, ids []any, columns ...any) (EndpointCollection, error)
func (*EndpointQuery) FindOrFail ¶
func (*EndpointQuery) FirstOrCreate ¶
func (*EndpointQuery) FirstOrFail ¶
func (*EndpointQuery) FirstOrNew ¶
func (*EndpointQuery) FirstWhere ¶
func (*EndpointQuery) ForPage ¶
func (q *EndpointQuery) ForPage(page, perPage int) *EndpointQuery
func (*EndpointQuery) ForceCreate ¶
func (*EndpointQuery) Get ¶
func (q *EndpointQuery) Get(ctx context.Context, g auth.Grant, columns ...any) (EndpointCollection, error)
Get runs the query and returns the rows.
func (*EndpointQuery) GroupBy ¶
func (q *EndpointQuery) GroupBy(groups ...any) *EndpointQuery
func (*EndpointQuery) Has ¶
func (q *EndpointQuery) Has(relation, operator string, count int, boolean string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) InsertOrIgnore ¶
func (*EndpointQuery) Join ¶
func (q *EndpointQuery) Join(table any, first any, args ...any) *EndpointQuery
func (*EndpointQuery) Latest ¶
func (q *EndpointQuery) Latest(column ...string) *EndpointQuery
func (*EndpointQuery) Limit ¶
func (q *EndpointQuery) Limit(value int) *EndpointQuery
func (*EndpointQuery) New ¶
func (q *EndpointQuery) New() (*Endpoint, error)
New returns an empty Endpoint on the query's connection, not yet saved, filled with what WithAttributes recorded on the query.
func (*EndpointQuery) Offset ¶
func (q *EndpointQuery) Offset(value int) *EndpointQuery
func (*EndpointQuery) Oldest ¶
func (q *EndpointQuery) Oldest(column ...string) *EndpointQuery
func (*EndpointQuery) OrDoesntHave ¶
func (q *EndpointQuery) OrDoesntHave(relation string) *EndpointQuery
func (*EndpointQuery) OrHas ¶
func (q *EndpointQuery) OrHas(relation, operator string, count int) *EndpointQuery
func (*EndpointQuery) OrWhere ¶
func (q *EndpointQuery) OrWhere(column any, args ...any) *EndpointQuery
OrWhere adds an or-where clause; a func(*EndpointQuery) in place of the column adds a group.
func (*EndpointQuery) OrWhereDoesntHave ¶
func (q *EndpointQuery) OrWhereDoesntHave(relation string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) OrWhereHas ¶
func (q *EndpointQuery) OrWhereHas(relation string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) OrWhereNot ¶
func (q *EndpointQuery) OrWhereNot(column any, args ...any) *EndpointQuery
OrWhereNot adds an or-joined negated where clause, or a negated group.
func (*EndpointQuery) OrWhereRelation ¶
func (q *EndpointQuery) OrWhereRelation(relation string, column any, args ...any) *EndpointQuery
func (*EndpointQuery) OrderBy ¶
func (q *EndpointQuery) OrderBy(column any, direction ...string) *EndpointQuery
func (*EndpointQuery) OrderByDesc ¶
func (q *EndpointQuery) OrderByDesc(column any) *EndpointQuery
func (*EndpointQuery) Paginate ¶
func (q *EndpointQuery) Paginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (EndpointCollection, *pagination.LengthAwarePage, error)
func (*EndpointQuery) Select ¶
func (q *EndpointQuery) Select(columns ...any) *EndpointQuery
func (*EndpointQuery) SelectRaw ¶
func (q *EndpointQuery) SelectRaw(expression string, bindings ...any) *EndpointQuery
func (*EndpointQuery) SimplePaginate ¶
func (q *EndpointQuery) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, opts pagination.Options, columns ...any) (EndpointCollection, *pagination.Page, error)
func (*EndpointQuery) UpdateOrCreate ¶
func (*EndpointQuery) ValueOrFail ¶
func (*EndpointQuery) Where ¶
func (q *EndpointQuery) Where(column any, args ...any) *EndpointQuery
Where adds a where clause; a func(*EndpointQuery) in place of the column adds a group.
func (*EndpointQuery) WhereBelongsTo ¶
func (q *EndpointQuery) WhereBelongsTo(relationshipName string, related ...model.Entity) *EndpointQuery
func (*EndpointQuery) WhereBetween ¶
func (q *EndpointQuery) WhereBetween(column any, from, to any) *EndpointQuery
func (*EndpointQuery) WhereColumn ¶
func (q *EndpointQuery) WhereColumn(first any, args ...any) *EndpointQuery
func (*EndpointQuery) WhereDoesntHave ¶
func (q *EndpointQuery) WhereDoesntHave(relation string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) WhereExists ¶
func (q *EndpointQuery) WhereExists(callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) WhereHas ¶
func (q *EndpointQuery) WhereHas(relation string, callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) WhereHasCount ¶
func (q *EndpointQuery) WhereHasCount(relation string, callback func(*query.Builder), operator string, count int) *EndpointQuery
func (*EndpointQuery) WhereIn ¶
func (q *EndpointQuery) WhereIn(column any, values []any) *EndpointQuery
func (*EndpointQuery) WhereKey ¶
func (q *EndpointQuery) WhereKey(id any) *EndpointQuery
func (*EndpointQuery) WhereNot ¶
func (q *EndpointQuery) WhereNot(column any, args ...any) *EndpointQuery
WhereNot adds a negated where clause, or a negated group.
func (*EndpointQuery) WhereNotExists ¶
func (q *EndpointQuery) WhereNotExists(callback func(*query.Builder)) *EndpointQuery
func (*EndpointQuery) WhereNotIn ¶
func (q *EndpointQuery) WhereNotIn(column any, values []any) *EndpointQuery
func (*EndpointQuery) WhereNotNull ¶
func (q *EndpointQuery) WhereNotNull(columns ...any) *EndpointQuery
func (*EndpointQuery) WhereNull ¶
func (q *EndpointQuery) WhereNull(columns ...any) *EndpointQuery
func (*EndpointQuery) WhereRelation ¶
func (q *EndpointQuery) WhereRelation(relation string, column any, args ...any) *EndpointQuery
func (*EndpointQuery) With ¶
func (q *EndpointQuery) With(relations ...string) *EndpointQuery
func (*EndpointQuery) WithAvg ¶
func (q *EndpointQuery) WithAvg(relation, column string) *EndpointQuery
func (*EndpointQuery) WithCount ¶
func (q *EndpointQuery) WithCount(relations ...string) *EndpointQuery
func (*EndpointQuery) WithExists ¶
func (q *EndpointQuery) WithExists(relation string) *EndpointQuery
func (*EndpointQuery) WithMax ¶
func (q *EndpointQuery) WithMax(relation, column string) *EndpointQuery
func (*EndpointQuery) WithMin ¶
func (q *EndpointQuery) WithMin(relation, column string) *EndpointQuery
func (*EndpointQuery) WithSum ¶
func (q *EndpointQuery) WithSum(relation, column string) *EndpointQuery
func (*EndpointQuery) Without ¶
func (q *EndpointQuery) Without(relations ...string) *EndpointQuery
func (*EndpointQuery) WithoutGlobalScope ¶
func (q *EndpointQuery) WithoutGlobalScope(identifier string) *EndpointQuery
func (*EndpointQuery) WithoutGlobalScopes ¶
func (q *EndpointQuery) WithoutGlobalScopes(identifiers ...string) *EndpointQuery
type EndpointRequest ¶
type EndpointRequest struct {
Name string
URL string
// Events are the event names it receives; AllEvents receives every one.
Events []string
// Signer is SignerArandu (empty means it) or SignerHMAC.
Signer string
// SignatureHeader is where a SignerHMAC signature goes. Empty means
// DefaultSignatureHeader.
SignatureHeader string
// Headers is "Name: value" per line. On an update, empty keeps the stored
// headers, which are never shown back.
Headers string
Active bool
}
EndpointRequest is an endpoint as a form or a client sends it.
There is no TenantID here and there must never be one: the tenant comes from the Grant, which comes from the session.
type EndpointResource ¶
type EndpointResource struct {
// contains filtered or unexported fields
}
EndpointResource is the list of fields one endpoint may answer with. The secret, the sealed headers and the tenant are not among them.
func NewEndpointResource ¶
func NewEndpointResource(e *Endpoint) EndpointResource
NewEndpointResource snapshots one endpoint for the response.
func (EndpointResource) ToArray ¶
func (r EndpointResource) ToArray() map[string]any
ToArray returns the fields that may leave, by name.
func (EndpointResource) With ¶
func (r EndpointResource) With() map[string]any
With adds nothing beside the fields.
type EndpointService ¶
type EndpointService struct {
// contains filtered or unexported fields
}
EndpointService is the use cases of the sending side: the endpoints, their secrets, the test call and the record of deliveries. It owns the database handle; every exported method asks the policy before it reads or writes.
func (*EndpointService) Create ¶
func (s *EndpointService) Create(ctx context.Context, actor security.Subject, in EndpointRequest) (*Endpoint, string, error)
Create adds an endpoint with a new signing secret, answered in clear this once for the person to give the receiver.
func (*EndpointService) Delete ¶
Delete removes an endpoint. Deliveries already queued still go out.
func (*EndpointService) Deliveries ¶
func (s *EndpointService) Deliveries(ctx context.Context, actor security.Subject, id string, limit int) ([]*Delivery, error)
Deliveries returns an endpoint's latest deliveries, newest first: what webhook-server tells through its WebhookCallSucceeded and WebhookCallFailed events, read from the record each attempt leaves.
func (*EndpointService) Find ¶
func (s *EndpointService) Find(ctx context.Context, actor security.Subject, id string) (*Endpoint, error)
Find returns one endpoint, and asks the policy about it once it is read.
func (*EndpointService) HeaderNames ¶
func (s *EndpointService) HeaderNames(ctx context.Context, actor security.Subject, id string) ([]string, error)
HeaderNames returns the names of an endpoint's extra headers, for its form. The values are never shown back.
func (*EndpointService) List ¶
func (s *EndpointService) List(ctx context.Context, actor security.Subject, q data.Query) ([]*Endpoint, error)
List returns a page of the tenant's endpoints, by name.
func (*EndpointService) Secret ¶
func (s *EndpointService) Secret(ctx context.Context, actor security.Subject, id string) (string, error)
Secret returns an endpoint's signing secret, for the panel's copy button.
type Flag ¶
type Flag bool
Flag is a yes-or-no stored as 0 or 1, which every engine reads the same.
type HMAC ¶
HMAC is webhook-client's DefaultSignatureValidator: the header carries the hex HMAC-SHA256 of the body under the shared secret. Prefix is what comes before the hex, such as "sha256=" for a sender that writes one; empty means none.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module is what the application registers.
func New ¶
New returns the module, or the reason it cannot be built.
sessions is where the management routes take their subject from; nil mounts none of them, for an application that manages endpoints from its own screens through the services. The receivers need no session.
func (*Module) CallService ¶
func (m *Module) CallService() *CallService
CallService is the receiving side's record, for an application that reads it from its own screens. Every method asks the policy.
func (*Module) EndpointService ¶
func (m *Module) EndpointService() *EndpointService
EndpointService is the sending side's use cases, for an application that calls them from its own screens. Every method asks the policy.
func (*Module) Manager ¶
Manager is hesape/webhook's Manager underneath, for an application that dispatches to endpoints of its own.
func (*Module) Migrations ¶
func (m *Module) Migrations() []foundation.Migration
Migrations declares the schema this module owns: its two tables, and the deliveries table of hesape/webhook underneath. An application that already runs hesape/webhook's Manager has that migration applied, and the migrator skips a name it has run.
func (*Module) Outgoing ¶
Outgoing starts a call built in code, as webhook-server's WebhookCall::create.
func (*Module) Publisher ¶
Publisher is the events outbox's listener that delivers each event to the tenant's endpoints subscribed to it. The application adds it to its relay's publishers.
func (*Module) ReceivePrefix ¶
ReceivePrefix is the path the receivers answer under, for the application's CSRF exemption.
func (*Module) RegisterJobHandlers ¶
RegisterJobHandlers gives the worker the deliveries and the processing of received calls. The worker is the application's, started by its worker command.
func (*Module) Routes ¶
Routes registers the receivers, and the management routes behind RequireAuth when the module has a session store.
A receiver is reached by a system with no session: its signature admits it. Its route is registered on r itself, and the guarded group is built after, so no management route lands outside the guard.
func (*Module) Schedule ¶
func (m *Module) Schedule() []foundation.Task
Schedule declares the daily clean of old received calls, as webhook-client's model:prune of WebhookCall, in each receiver's tenant. CleanSpec "-" declares none.
type Outgoing ¶
type Outgoing struct {
// contains filtered or unexported fields
}
Outgoing is one call built in code, as webhook-server's WebhookCall:
err := webhooks.Outgoing().
URL("https://example.com/hooks").
Event("order.paid").
Payload(map[string]any{"order": id}).
UseSecret("partners").
Dispatch(ctx, g)
Dispatch records the delivery and its queued job in one transaction; the worker sends it, signed, and retries it. g carries hwebhook.ActionDispatch for the tenant the call belongs to: the application decided to send, and that decision is the Grant.
func (*Outgoing) DispatchIf ¶
DispatchIf dispatches when cond holds, as webhook-server's dispatchIf.
func (*Outgoing) DispatchUnless ¶
DispatchUnless dispatches unless cond holds.
func (*Outgoing) RawBody ¶
RawBody sets the body as it is, as webhook-server's sendRawBody. It is sent as application/json.
func (*Outgoing) SignWithHMAC ¶
SignWithHMAC adds webhook-server's DefaultSigner signature -- the hex HMAC-SHA256 of the body -- in the header named, beside the Arandu one. Empty means DefaultSignatureHeader.
func (*Outgoing) UUID ¶
UUID sets the call's identity. A call dispatched twice with one identity to one address is delivered once. Empty means a new one.
type ProcessEverything ¶
type ProcessEverything struct{}
ProcessEverything is webhook-client's ProcessEverythingWebhookProfile.
func (ProcessEverything) ShouldProcess ¶
func (ProcessEverything) ShouldProcess(*http.Request, []byte) bool
ShouldProcess answers true.
type Processor ¶
Processor handles a stored call on the queue: webhook-client's process_webhook_job. g is the Grant of the call's tenant, for whatever the processing reads and writes. An error leaves the call failed, with the message kept, and the queue tries again until the receiver's Tries are spent; nil marks it processed.
type ProcessorFunc ¶
ProcessorFunc adapts a function to Processor.
type Profile ¶
Profile decides whether a call whose signature checked is stored and processed: webhook-client's WebhookProfile. A call it turns down is answered like any other and kept nowhere.
type ProfileFunc ¶
ProfileFunc adapts a function to Profile.
func (ProfileFunc) ShouldProcess ¶
func (f ProfileFunc) ShouldProcess(r *http.Request, body []byte) bool
ShouldProcess calls f.
type Receiver ¶
type Receiver struct {
// Name identifies the receiver, its route and its calls: lowercase
// letters, digits and dashes.
Name string
// Tenant is whose calls these are. It comes from the application's
// configuration, never from the request.
Tenant string
// Methods are the HTTP methods accepted. Empty means POST.
Methods []string
// Secret is the signing secret the sender shares; PreviousSecrets are
// still accepted while the sender rotates. Required unless Validator is
// the application's own.
Secret string
PreviousSecrets []string
// Validator checks the signature. Nil means HMAC{Header:
// DefaultSignatureHeader}, webhook-client's DefaultSignatureValidator.
Validator SignatureValidator
// Profile decides whether a valid call is stored and processed. Nil
// processes every call.
Profile Profile
// Respond answers the sender. Nil answers 200 {"message":"ok"}.
Respond Responder
// StoreHeaders are the request headers kept with the call; "*" keeps
// them all. Empty keeps none.
StoreHeaders []string
// Process handles a stored call on the queue: webhook-client's
// process_webhook_job. Required.
Process Processor
// Tries is how many times a call is processed before it stays failed.
// Zero means DefaultTries.
Tries int
// MaxBodyBytes is the largest body read. Zero means DefaultMaxBodyBytes.
MaxBodyBytes int64
// OnInvalidSignature is called when a request fails the signature check,
// as webhook-client's InvalidWebhookSignatureEvent. Optional.
OnInvalidSignature func(r *http.Request, receiver string)
}
Receiver is one system that calls this application: webhook-client's config entry, mounted at ReceivePrefix + "/" + Name.
type RespondOK ¶
type RespondOK struct{}
RespondOK is webhook-client's DefaultRespondsTo: 200 {"message":"ok"}.
type Responder ¶
Responder answers the sender once a call is taken: webhook-client's RespondsToWebhook. call is nil when the Profile turned the call down.
type ResponderFunc ¶
ResponderFunc adapts a function to Responder.
func (ResponderFunc) Respond ¶
func (f ResponderFunc) Respond(w http.ResponseWriter, r *http.Request, call *Call) error
Respond calls f.
type Server ¶
type Server struct {
// Queue is the queue deliveries travel on. Empty means DefaultQueue.
Queue string
// UserAgent is sent with every call. Empty means DefaultUserAgent.
UserAgent string
// Timeout is how long one call may take. Zero means DefaultTimeout.
Timeout time.Duration
// Retention is how long a delivery's record is kept. Zero means
// hesape/webhook's DefaultRetention.
Retention time.Duration
// HeaderPrefix renames the delivery headers, X-Arandu-Signature becoming
// <HeaderPrefix>-Signature, so a receiver reads the product's name. The
// signature covers the timestamp, the delivery id and the body, never a
// header's name, so renaming does not change what is verified. Empty keeps
// X-Arandu.
HeaderPrefix string
// HTTPClient carries the calls. Nil uses hesape's client, which refuses
// private and loopback addresses on every hop.
HTTPClient *http.Client
// Events is the list an endpoint may subscribe to. Empty accepts any
// event name.
Events []string
// Secrets are named signing secrets for calls built with Outgoing, as
// webhook-server's useSecret. Each is at least MinSecretBytes long.
Secrets map[string]string
}
Server is the sending side: webhook-server's config.
type SignatureValidator ¶
type SignatureValidator interface {
Valid(r *http.Request, body []byte, secrets hwebhook.SecretSet) bool
}
SignatureValidator decides whether a received call was signed by the sender that shares the receiver's secret: webhook-client's SignatureValidator. secrets holds the current secret and the ones still accepted during a rotation; body is exactly what arrived.
type SignatureValidatorFunc ¶
SignatureValidatorFunc adapts a function to SignatureValidator.