99 lines
2.4 KiB
Go
99 lines
2.4 KiB
Go
package domain
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ErrInviteIDMissing = errors.New("invite id is required")
|
|
ErrCodeMissing = errors.New("invite code is required")
|
|
ErrInviteExpired = errors.New("invite is expired")
|
|
ErrInviteConsumed = errors.New("invite is already consumed")
|
|
)
|
|
|
|
type Invite struct {
|
|
ID string `json:"id"`
|
|
Code string `json:"code"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
ConsumedAt *time.Time `json:"consumed_at"`
|
|
}
|
|
|
|
type InviteRepository interface {
|
|
CreateInvite(ctx context.Context, inviterUserID string, code string, expiresAt time.Time) (*Invite, error)
|
|
DeleteInvite(ctx context.Context, userID string, inviteID string) error
|
|
ConsumeInvite(ctx context.Context, inviteID string, inviteeUserID string) error
|
|
GetInvite(ctx context.Context, code string) (*Invite, error)
|
|
GetInvites(ctx context.Context, userID string) ([]Invite, error)
|
|
}
|
|
|
|
type InviteService struct {
|
|
repo InviteRepository
|
|
}
|
|
|
|
func NewInviteService(r InviteRepository) *InviteService {
|
|
return &InviteService{repo: r}
|
|
}
|
|
|
|
func (s *InviteService) CreateInvite(ctx context.Context, inviterUserID string) (*Invite, error) {
|
|
if inviterUserID == "" {
|
|
return nil, ErrUserIDMissing
|
|
}
|
|
|
|
token, err := generateSecureToken(32)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
code := hashToken(token)
|
|
expiresAt := time.Now().Add(time.Hour * 24 * 7)
|
|
|
|
return s.repo.CreateInvite(ctx, inviterUserID, code, expiresAt)
|
|
}
|
|
|
|
func (s *InviteService) DeleteInvite(ctx context.Context, userID string, inviteID string) error {
|
|
if userID == "" {
|
|
return ErrUserIDMissing
|
|
}
|
|
if inviteID == "" {
|
|
return ErrInviteIDMissing
|
|
}
|
|
|
|
return s.repo.DeleteInvite(ctx, userID, inviteID)
|
|
}
|
|
|
|
func (s *InviteService) ConsumeInvite(ctx context.Context, inviteID string, inviteeUserID string) error {
|
|
if inviteeUserID == "" {
|
|
return ErrUserIDMissing
|
|
}
|
|
|
|
return s.repo.ConsumeInvite(ctx, inviteID, inviteeUserID)
|
|
}
|
|
|
|
func (s *InviteService) GetInvite(ctx context.Context, code string) (*Invite, error) {
|
|
if code == "" {
|
|
return nil, ErrCodeMissing
|
|
}
|
|
|
|
invite, err := s.repo.GetInvite(ctx, code)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if invite.ExpiresAt.Before(time.Now()) {
|
|
return nil, ErrInviteExpired
|
|
}
|
|
if invite.ConsumedAt != nil {
|
|
return nil, ErrInviteConsumed
|
|
}
|
|
|
|
return invite, nil
|
|
}
|
|
|
|
func (s *InviteService) GetInvites(ctx context.Context, userID string) ([]Invite, error) {
|
|
if userID == "" {
|
|
return nil, ErrUserIDMissing
|
|
}
|
|
|
|
return s.repo.GetInvites(ctx, userID)
|
|
}
|