feat: authsession service
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package ports
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"galaxy/authsession/internal/domain/challenge"
|
||||
"galaxy/authsession/internal/domain/common"
|
||||
)
|
||||
|
||||
// SendEmailCodeAbuseProtector decides whether one public send-email-code
|
||||
// attempt may proceed immediately or must be throttled by the auth-side resend
|
||||
// cooldown.
|
||||
type SendEmailCodeAbuseProtector interface {
|
||||
// CheckAndReserve validates input, checks the current resend cooldown
|
||||
// decision for input.Email, and reserves a new cooldown window immediately
|
||||
// when the outcome is allowed.
|
||||
CheckAndReserve(ctx context.Context, input SendEmailCodeAbuseInput) (SendEmailCodeAbuseResult, error)
|
||||
}
|
||||
|
||||
// SendEmailCodeAbuseInput describes one resend-throttle decision request for
|
||||
// a normalized public send-email-code attempt.
|
||||
type SendEmailCodeAbuseInput struct {
|
||||
// Email identifies the normalized e-mail address addressed by the public
|
||||
// request.
|
||||
Email common.Email
|
||||
|
||||
// Now records when the send attempt is being evaluated.
|
||||
Now time.Time
|
||||
}
|
||||
|
||||
// Validate reports whether SendEmailCodeAbuseInput contains a complete resend
|
||||
// cooldown decision request.
|
||||
func (i SendEmailCodeAbuseInput) Validate() error {
|
||||
if err := i.Email.Validate(); err != nil {
|
||||
return fmt.Errorf("send email code abuse input email: %w", err)
|
||||
}
|
||||
if i.Now.IsZero() {
|
||||
return fmt.Errorf("send email code abuse input now must not be zero")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendEmailCodeAbuseOutcome identifies the coarse resend-throttle decision for
|
||||
// one public send-email-code attempt.
|
||||
type SendEmailCodeAbuseOutcome string
|
||||
|
||||
const (
|
||||
// SendEmailCodeAbuseOutcomeAllowed reports that the attempt may proceed and
|
||||
// that the cooldown window has been reserved immediately.
|
||||
SendEmailCodeAbuseOutcomeAllowed SendEmailCodeAbuseOutcome = "allowed"
|
||||
|
||||
// SendEmailCodeAbuseOutcomeThrottled reports that the cooldown window is
|
||||
// still active and that the caller must not extend it.
|
||||
SendEmailCodeAbuseOutcomeThrottled SendEmailCodeAbuseOutcome = "throttled"
|
||||
)
|
||||
|
||||
// IsKnown reports whether SendEmailCodeAbuseOutcome belongs to the stable
|
||||
// Stage-17 resend-throttle contract.
|
||||
func (o SendEmailCodeAbuseOutcome) IsKnown() bool {
|
||||
switch o {
|
||||
case SendEmailCodeAbuseOutcomeAllowed, SendEmailCodeAbuseOutcomeThrottled:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// SendEmailCodeAbuseResult describes one resend-throttle decision returned by
|
||||
// SendEmailCodeAbuseProtector.
|
||||
type SendEmailCodeAbuseResult struct {
|
||||
// Outcome reports whether the current send attempt may proceed or must be
|
||||
// throttled.
|
||||
Outcome SendEmailCodeAbuseOutcome
|
||||
}
|
||||
|
||||
// Validate reports whether SendEmailCodeAbuseResult satisfies the resend
|
||||
// cooldown contract.
|
||||
func (r SendEmailCodeAbuseResult) Validate() error {
|
||||
if !r.Outcome.IsKnown() {
|
||||
return fmt.Errorf("send email code abuse result outcome %q is unsupported", r.Outcome)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendEmailCodeThrottleStatusToChallengeStatus maps one resend-throttle
|
||||
// outcome to the challenge lifecycle state used by sendemailcode.
|
||||
func SendEmailCodeThrottleStatusToChallengeStatus(outcome SendEmailCodeAbuseOutcome) (challenge.Status, challenge.DeliveryState, error) {
|
||||
switch outcome {
|
||||
case SendEmailCodeAbuseOutcomeAllowed:
|
||||
return challenge.StatusPendingSend, challenge.DeliveryPending, nil
|
||||
case SendEmailCodeAbuseOutcomeThrottled:
|
||||
return challenge.StatusDeliveryThrottled, challenge.DeliveryThrottled, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("map send email code abuse outcome %q: unsupported outcome", outcome)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user