Files
sxchnge/backend/product/verification/store/request.go
T

103 lines
2.6 KiB
Go

package verification
import (
verificationmodel "git.sendico.io/tech/sxchnge/product/verification/model"
"strings"
"time"
"git.sendico.io/tech/sxchnge/shared/ratelimit/store"
"go.mongodb.org/mongo-driver/v2/bson"
)
type IssuanceLimit struct {
ScopeKind string
ScopeHash string
Limit int
WindowStart time.Time
ExpiresAt time.Time
}
func NewIssuanceLimit(scopeKind, scopeValue string, limit int, window time.Duration, now time.Time) IssuanceLimit {
windowStart := now.UTC().Truncate(window)
return IssuanceLimit{
ScopeKind: strings.TrimSpace(scopeKind),
ScopeHash: ratelimits.HashScope(scopeKind, scopeValue),
Limit: limit,
WindowStart: windowStart,
ExpiresAt: windowStart.Add(window),
}
}
type TokenKind = string
const (
TokenKindOTP TokenKind = "otp"
TokenKindLink TokenKind = "link"
)
type Request struct {
AccountRef bson.ObjectID
Purpose verificationmodel.VerificationPurpose
Target string
ContextRef string
Ttl time.Duration
Kind TokenKind
MaxRetries *int
Cooldown *time.Duration
IdempotencyKey *string // Optional key to make Create idempotent for retries.
IssuanceLimits []IssuanceLimit
}
func (r *Request) WithIssuanceLimits(limits ...IssuanceLimit) *Request {
r.IssuanceLimits = append([]IssuanceLimit(nil), limits...)
return r
}
func newRequest(accountRef bson.ObjectID, purpose verificationmodel.VerificationPurpose, target string, kind TokenKind) *Request {
return &Request{
AccountRef: accountRef,
Purpose: purpose,
Target: target,
Kind: kind,
Ttl: 15 * time.Minute, // default TTL for verification tokens
}
}
func NewLinkRequest(accountRef bson.ObjectID, purpose verificationmodel.VerificationPurpose, target string) *Request {
return newRequest(accountRef, purpose, target, TokenKindLink)
}
func NewOTPRequest(accountRef bson.ObjectID, purpose verificationmodel.VerificationPurpose, target string) *Request {
return newRequest(accountRef, purpose, target, TokenKindOTP)
}
func (r *Request) WithTTL(ttl time.Duration) *Request {
r.Ttl = ttl
return r
}
func (r *Request) WithMaxRetries(maxRetries int) *Request {
r.MaxRetries = &maxRetries
return r
}
func (r *Request) WithCooldown(cooldown time.Duration) *Request {
r.Cooldown = &cooldown
return r
}
func (r *Request) WithIdempotencyKey(key string) *Request {
normalized := strings.TrimSpace(key)
if normalized == "" {
r.IdempotencyKey = nil
return r
}
r.IdempotencyKey = &normalized
return r
}
func (r *Request) WithContextRef(contextRef string) *Request {
r.ContextRef = strings.TrimSpace(contextRef)
return r
}