feat: added invite system
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user