95 lines
3.0 KiB
Go
95 lines
3.0 KiB
Go
package network
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/flowy-live/llink/internal/utils"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
type Reader interface {
|
|
// GetByID returns ErrNotFound if network doesn't exist.
|
|
GetByID(ctx context.Context, id string) (*Network, error)
|
|
// ListForHuman returns ErrInvalidHumanId if humanId is empty.
|
|
ListForHuman(ctx context.Context, humanId string) ([]*Network, error)
|
|
// IsMember returns ErrInvalidHumanId if humanId is empty.
|
|
IsMember(ctx context.Context, networkID, humanId string) (bool, error)
|
|
// ListAll returns all networks with their members
|
|
ListAll(ctx context.Context) ([]*Network, error)
|
|
// ListAllMemberships returns humanId -> networkIds for every human with at
|
|
// least one membership. Humans with zero memberships are absent from the map.
|
|
// Used by the membership reconciler to diff the Firestore mirror.
|
|
ListAllMemberships(ctx context.Context) (map[string][]string, error)
|
|
|
|
CountSeats(ctx context.Context, networkID string) (int, error)
|
|
// ListInvitationsForEmail returns ErrInvalidEmail if normalization fails.
|
|
ListInvitationsForEmail(ctx context.Context, email string) ([]*Invitation, error)
|
|
ListInvitationsForNetwork(ctx context.Context, networkID string) ([]*Invitation, error)
|
|
}
|
|
|
|
type readerImpl struct {
|
|
pool *pgxpool.Pool
|
|
repo repository
|
|
}
|
|
|
|
// newReader returns the concrete reader. Used by NewService to embed without
|
|
// going through the Reader interface (which would hide pool/repo).
|
|
func newReader(pool *pgxpool.Pool) *readerImpl {
|
|
return &readerImpl{
|
|
pool: pool,
|
|
repo: newRepository(pool),
|
|
}
|
|
}
|
|
|
|
func NewReader(pool *pgxpool.Pool) Reader {
|
|
return newReader(pool)
|
|
}
|
|
|
|
func (r *readerImpl) GetByID(ctx context.Context, id string) (*Network, error) {
|
|
n, err := r.repo.getByID(ctx, id)
|
|
if errors.Is(err, errNotFound) {
|
|
return nil, ErrNotFound
|
|
}
|
|
return n, err
|
|
}
|
|
|
|
func (r *readerImpl) ListForHuman(ctx context.Context, humanId string) ([]*Network, error) {
|
|
if humanId == "" {
|
|
return nil, ErrInvalidHumanId
|
|
}
|
|
return r.repo.getNetworksForHuman(ctx, humanId)
|
|
}
|
|
|
|
func (r *readerImpl) IsMember(ctx context.Context, networkID, humanId string) (bool, error) {
|
|
if humanId == "" {
|
|
return false, ErrInvalidHumanId
|
|
}
|
|
return r.repo.isMember(ctx, networkID, humanId)
|
|
}
|
|
|
|
func (r *readerImpl) ListAll(ctx context.Context) ([]*Network, error) {
|
|
return r.repo.listAll(ctx)
|
|
}
|
|
|
|
func (r *readerImpl) ListAllMemberships(ctx context.Context) (map[string][]string, error) {
|
|
return r.repo.listAllMemberships(ctx)
|
|
}
|
|
|
|
func (r *readerImpl) CountSeats(ctx context.Context, networkID string) (int, error) {
|
|
return r.repo.countSeats(ctx, r.pool, networkID)
|
|
}
|
|
|
|
func (r *readerImpl) ListInvitationsForEmail(ctx context.Context, email string) ([]*Invitation, error) {
|
|
normalized, err := utils.NormalizeEmail(email)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: %w", ErrInvalidEmail, err)
|
|
}
|
|
return r.repo.getInvitationsByEmail(ctx, normalized)
|
|
}
|
|
|
|
func (r *readerImpl) ListInvitationsForNetwork(ctx context.Context, networkID string) ([]*Invitation, error) {
|
|
return r.repo.getInvitationsByNetwork(ctx, networkID)
|
|
}
|