Files
llink/go/internal/human/pushnotify/service.go
T

71 lines
2.2 KiB
Go

package pushnotify
import (
"context"
"github.com/jackc/pgx/v5/pgxpool"
)
// Service is the full surface for per-device push token storage. HTTP handlers
// use Register/Unregister; the worker's notifier uses ListForHumans and
// DeleteByToken. Both consumers share the same underlying repository.
type Service interface {
// Register upserts a token for the given human. Returns ErrInvalidToken /
// ErrInvalidPlatform on bad input.
Register(ctx context.Context, humanID string, in RegisterInput) error
// Unregister removes a token, scoped to the calling human so a user can't
// delete another user's token. Returns ErrNotFound if the token doesn't
// belong to humanID (or doesn't exist).
Unregister(ctx context.Context, humanID, token string) error
// ListForHumans returns every push token belonging to any of the given
// human IDs. Returns an empty slice when nothing matches.
ListForHumans(ctx context.Context, humanIDs []string) ([]*PushToken, error)
// DeleteByToken removes a token regardless of owning human. Used by the
// notifier to clean up after Expo returns DeviceNotRegistered.
DeleteByToken(ctx context.Context, token string) error
}
type RegisterInput struct {
Token string
Platform Platform
AppVersion string
}
type serviceImpl struct {
repo repository
}
func NewService(pool *pgxpool.Pool) Service {
return &serviceImpl{repo: newRepository(pool)}
}
func (s *serviceImpl) Register(ctx context.Context, humanID string, in RegisterInput) error {
if !in.Platform.Valid() {
return ErrInvalidPlatform
}
if !IsValidExpoToken(in.Token) {
return ErrInvalidToken
}
return s.repo.upsert(ctx, &PushToken{
Token: in.Token,
HumanID: humanID,
Platform: in.Platform,
AppVersion: in.AppVersion,
})
}
func (s *serviceImpl) Unregister(ctx context.Context, humanID, token string) error {
if token == "" {
return ErrInvalidToken
}
return s.repo.deleteForHuman(ctx, humanID, token)
}
func (s *serviceImpl) ListForHumans(ctx context.Context, humanIDs []string) ([]*PushToken, error) {
return s.repo.listForHumans(ctx, humanIDs)
}
func (s *serviceImpl) DeleteByToken(ctx context.Context, token string) error {
return s.repo.deleteByToken(ctx, token)
}