feat: authsession service
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package testkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"galaxy/authsession/internal/domain/challenge"
|
||||
"galaxy/authsession/internal/domain/common"
|
||||
"galaxy/authsession/internal/ports"
|
||||
)
|
||||
|
||||
// InMemorySendEmailCodeAbuseProtector is a deterministic map-backed
|
||||
// SendEmailCodeAbuseProtector double suitable for service tests.
|
||||
type InMemorySendEmailCodeAbuseProtector struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// Err is returned directly from CheckAndReserve when set.
|
||||
Err error
|
||||
|
||||
reservedUntil map[common.Email]time.Time
|
||||
}
|
||||
|
||||
// CheckAndReserve applies the fixed resend cooldown using input.Now as the
|
||||
// authoritative decision timestamp.
|
||||
func (p *InMemorySendEmailCodeAbuseProtector) CheckAndReserve(ctx context.Context, input ports.SendEmailCodeAbuseInput) (ports.SendEmailCodeAbuseResult, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return ports.SendEmailCodeAbuseResult{}, err
|
||||
}
|
||||
if err := input.Validate(); err != nil {
|
||||
return ports.SendEmailCodeAbuseResult{}, fmt.Errorf("check send email code abuse: %w", err)
|
||||
}
|
||||
if p.Err != nil {
|
||||
return ports.SendEmailCodeAbuseResult{}, p.Err
|
||||
}
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if p.reservedUntil == nil {
|
||||
p.reservedUntil = make(map[common.Email]time.Time)
|
||||
}
|
||||
|
||||
reservedUntil, exists := p.reservedUntil[input.Email]
|
||||
if exists && input.Now.Before(reservedUntil) {
|
||||
return ports.SendEmailCodeAbuseResult{
|
||||
Outcome: ports.SendEmailCodeAbuseOutcomeThrottled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
p.reservedUntil[input.Email] = input.Now.UTC().Add(challenge.ResendThrottleCooldown)
|
||||
return ports.SendEmailCodeAbuseResult{
|
||||
Outcome: ports.SendEmailCodeAbuseOutcomeAllowed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ ports.SendEmailCodeAbuseProtector = (*InMemorySendEmailCodeAbuseProtector)(nil)
|
||||
Reference in New Issue
Block a user