Documentation
¶
Overview ¶
Package webpush is the Web Push (RFC 8030 + VAPID) usernotify.Sink: it delivers a Notification to every browser PushSubscription registered by each recipient, via the browsers' push services.
Index ¶
- Constants
- func GenerateVAPIDKeys() (privateKey, publicKey string, err error)
- type MemSubscriptionStore
- func (m *MemSubscriptionStore) DeleteByEndpoint(_ context.Context, userID, endpoint string) error
- func (m *MemSubscriptionStore) ListForUsers(_ context.Context, userIDs []string) ([]*Subscription, error)
- func (m *MemSubscriptionStore) Prune(_ context.Context, endpoint string) error
- func (m *MemSubscriptionStore) Touch(_ context.Context, endpoint string, at time.Time) error
- func (m *MemSubscriptionStore) Upsert(_ context.Context, s *Subscription) error
- type MongoSubscriptionStore
- func (s *MongoSubscriptionStore) DeleteByEndpoint(ctx context.Context, userID, endpoint string) error
- func (s *MongoSubscriptionStore) EnsureSchema(ctx context.Context) error
- func (s *MongoSubscriptionStore) ListForUsers(ctx context.Context, userIDs []string) ([]*Subscription, error)
- func (s *MongoSubscriptionStore) Prune(ctx context.Context, endpoint string) error
- func (s *MongoSubscriptionStore) Touch(ctx context.Context, endpoint string, at time.Time) error
- func (s *MongoSubscriptionStore) Upsert(ctx context.Context, sub *Subscription) error
- type Sink
- type SinkOptions
- type Subscription
- type SubscriptionStore
Constants ¶
const SubscriptionsCollectionName = "push_subscriptions"
SubscriptionsCollectionName backs the cloud-mode SubscriptionStore.
Variables ¶
This section is empty.
Functions ¶
func GenerateVAPIDKeys ¶
GenerateVAPIDKeys mints a fresh VAPID keypair (private, public) for the `iterion server webpush-keys` helper.
Types ¶
type MemSubscriptionStore ¶
type MemSubscriptionStore struct {
// contains filtered or unexported fields
}
MemSubscriptionStore is the in-memory SubscriptionStore for tests and local mode.
func NewMemSubscriptionStore ¶
func NewMemSubscriptionStore() *MemSubscriptionStore
func (*MemSubscriptionStore) DeleteByEndpoint ¶
func (m *MemSubscriptionStore) DeleteByEndpoint(_ context.Context, userID, endpoint string) error
func (*MemSubscriptionStore) ListForUsers ¶
func (m *MemSubscriptionStore) ListForUsers(_ context.Context, userIDs []string) ([]*Subscription, error)
func (*MemSubscriptionStore) Prune ¶
func (m *MemSubscriptionStore) Prune(_ context.Context, endpoint string) error
func (*MemSubscriptionStore) Upsert ¶
func (m *MemSubscriptionStore) Upsert(_ context.Context, s *Subscription) error
type MongoSubscriptionStore ¶
type MongoSubscriptionStore struct {
// contains filtered or unexported fields
}
MongoSubscriptionStore is the cloud-mode SubscriptionStore.
func NewMongoSubscriptionStore ¶
func NewMongoSubscriptionStore(db *mongo.Database) *MongoSubscriptionStore
func (*MongoSubscriptionStore) DeleteByEndpoint ¶
func (s *MongoSubscriptionStore) DeleteByEndpoint(ctx context.Context, userID, endpoint string) error
func (*MongoSubscriptionStore) EnsureSchema ¶
func (s *MongoSubscriptionStore) EnsureSchema(ctx context.Context) error
func (*MongoSubscriptionStore) ListForUsers ¶
func (s *MongoSubscriptionStore) ListForUsers(ctx context.Context, userIDs []string) ([]*Subscription, error)
func (*MongoSubscriptionStore) Prune ¶
func (s *MongoSubscriptionStore) Prune(ctx context.Context, endpoint string) error
func (*MongoSubscriptionStore) Upsert ¶
func (s *MongoSubscriptionStore) Upsert(ctx context.Context, sub *Subscription) error
type Sink ¶
type Sink struct {
// contains filtered or unexported fields
}
Sink implements usernotify.Sink over Web Push.
func NewSink ¶
func NewSink(store SubscriptionStore, opts SinkOptions, logger *iterlog.Logger) *Sink
func (*Sink) Deliver ¶
func (s *Sink) Deliver(ctx context.Context, n usernotify.Notification) error
Deliver pushes n to every registered browser of every recipient — one subscription query, then bounded-parallel HTTP sends (each is a blocking call to an external push service; serialized they can outlast the deliver budget). A push endpoint the service reports dead (404/410 Gone) is pruned. Deliver only errors when nothing could be delivered despite at least one live subscription — a recipient with no subscriptions is not a failure.
type SinkOptions ¶
type SinkOptions struct {
VAPIDPublicKey string
VAPIDPrivateKey string
// Subscriber is the VAPID contact (mailto: or https: URL) push services
// may use to reach the operator.
Subscriber string
// HTTPClient overrides the client used to reach push services (tests).
HTTPClient *http.Client
}
SinkOptions configures the web-push sink. The VAPID keypair must be shared by every server replica (it is the sender identity browsers pin at subscribe time).
type Subscription ¶
type Subscription struct {
ID string `json:"id" bson:"_id"`
TenantID string `json:"tenant_id" bson:"tenant_id"`
UserID string `json:"user_id" bson:"user_id"`
Endpoint string `json:"endpoint" bson:"endpoint"`
P256dh string `json:"p256dh" bson:"p256dh"`
Auth string `json:"auth" bson:"auth"`
UserAgent string `json:"user_agent,omitempty" bson:"user_agent,omitempty"`
CreatedAt time.Time `json:"created_at" bson:"created_at"`
LastUsedAt time.Time `json:"last_used_at,omitempty" bson:"last_used_at,omitempty"`
}
Subscription is one browser push registration (one user × one browser profile × one device). The endpoint is the push service's capability URL and is globally unique. A subscription belongs to the USER, not a team: TenantID records where it was enrolled (provenance) but delivery must not filter on it — a multi-team user enrolls once and receives notifications for runs of every team that resolves them as a recipient (recipient resolution is already tenant-scoped upstream).
type SubscriptionStore ¶
type SubscriptionStore interface {
// Upsert registers (or refreshes) a subscription, keyed on its endpoint.
Upsert(ctx context.Context, s *Subscription) error
// ListForUsers returns every subscription of the given users in one
// query (a notification fans out to all recipients at once). Not
// tenant-filtered — see the Subscription doc.
ListForUsers(ctx context.Context, userIDs []string) ([]*Subscription, error)
// DeleteByEndpoint removes the caller's own subscription (unsubscribe).
DeleteByEndpoint(ctx context.Context, userID, endpoint string) error
// Prune removes a subscription the push service reported dead (404/410).
Prune(ctx context.Context, endpoint string) error
// Touch refreshes last_used_at after a successful delivery. Best-effort.
Touch(ctx context.Context, endpoint string, at time.Time) error
}
SubscriptionStore persists browser push registrations.