feat(orion): add rest api for waitlist
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package waitlist
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/flowy-live/llink/internal/utils"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type WaitlistEntry struct {
|
||||
Id int `db:"id"`
|
||||
Email string `db:"email"`
|
||||
Metadata map[string]string `db:"metadata"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
InvitedAt *time.Time `db:"invited_at"`
|
||||
}
|
||||
|
||||
var (
|
||||
AlreadyInWaitlistError = errors.New("already in the waitlist")
|
||||
EntryNotFoundError = errors.New("not found")
|
||||
)
|
||||
|
||||
type GetWaitlistFilter string
|
||||
|
||||
const (
|
||||
GetWaitlistFilterAll GetWaitlistFilter = "all"
|
||||
GetWaitlistFilterInvitedOnly GetWaitlistFilter = "invited-only"
|
||||
GetWaitlistFilterUninvitedOnly GetWaitlistFilter = "uninvited-only"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
// returns AlreadyInWaitlistError if already in the waitlist
|
||||
// any other error is a failure
|
||||
AddToWaitlist(ctx context.Context, email string, metadata map[string]string) error
|
||||
GetWaitlist(ctx context.Context, filter GetWaitlistFilter) ([]*WaitlistEntry, error)
|
||||
// returns error if not found
|
||||
GetWaitlistEntryByEmail(ctx context.Context, email string) (*WaitlistEntry, error)
|
||||
MarkWaitlistEntryInvited(ctx context.Context, email string) error
|
||||
}
|
||||
|
||||
type serviceImpl struct {
|
||||
repo repository
|
||||
}
|
||||
|
||||
func NewService(pool *pgxpool.Pool) Service {
|
||||
return &serviceImpl{
|
||||
repo: newRepository(pool),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *serviceImpl) AddToWaitlist(ctx context.Context, email string, metadata map[string]string) error {
|
||||
normalizedEmail, err := utils.NormalizeEmail(email)
|
||||
if err != nil {
|
||||
return errors.New("invalid email")
|
||||
}
|
||||
|
||||
if metadata == nil {
|
||||
metadata = map[string]string{}
|
||||
}
|
||||
|
||||
_, err = s.repo.create(ctx, normalizedEmail, metadata)
|
||||
if err != nil {
|
||||
if errors.Is(err, errAlreadyExists) {
|
||||
return AlreadyInWaitlistError
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *serviceImpl) GetWaitlist(ctx context.Context, filter GetWaitlistFilter) ([]*WaitlistEntry, error) {
|
||||
return s.repo.getAll(ctx, filter)
|
||||
}
|
||||
|
||||
func (s *serviceImpl) GetWaitlistEntryByEmail(ctx context.Context, email string) (*WaitlistEntry, error) {
|
||||
normalizedEmail, err := utils.NormalizeEmail(email)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid email")
|
||||
}
|
||||
|
||||
entry, err := s.repo.getByEmail(ctx, normalizedEmail)
|
||||
if err != nil {
|
||||
if errors.Is(err, errNotFound) {
|
||||
return nil, EntryNotFoundError
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
func (s *serviceImpl) MarkWaitlistEntryInvited(ctx context.Context, email string) error {
|
||||
normalizedEmail, err := utils.NormalizeEmail(email)
|
||||
if err != nil {
|
||||
return errors.New("invalid email")
|
||||
}
|
||||
|
||||
err = s.repo.markInvited(ctx, normalizedEmail)
|
||||
if err != nil {
|
||||
if errors.Is(err, errNotFound) {
|
||||
return EntryNotFoundError
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user