137 lines
4.2 KiB
Go
137 lines
4.2 KiB
Go
// Package account defines the logical user-account entities owned directly by
|
|
// User Service.
|
|
package account
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"galaxy/user/internal/domain/common"
|
|
)
|
|
|
|
// RaceNameCanonicalKey stores the policy-produced reservation key used to
|
|
// enforce replaceable race-name uniqueness.
|
|
type RaceNameCanonicalKey string
|
|
|
|
// String returns RaceNameCanonicalKey as its stored canonical string.
|
|
func (key RaceNameCanonicalKey) String() string {
|
|
return string(key)
|
|
}
|
|
|
|
// IsZero reports whether RaceNameCanonicalKey does not contain a usable value.
|
|
func (key RaceNameCanonicalKey) IsZero() bool {
|
|
return strings.TrimSpace(string(key)) == ""
|
|
}
|
|
|
|
// Validate reports whether RaceNameCanonicalKey is non-empty and trimmed.
|
|
func (key RaceNameCanonicalKey) Validate() error {
|
|
switch {
|
|
case key.IsZero():
|
|
return fmt.Errorf("race name canonical key must not be empty")
|
|
case strings.TrimSpace(string(key)) != string(key):
|
|
return fmt.Errorf("race name canonical key must not contain surrounding whitespace")
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// UserAccount stores the current editable account state of one regular user.
|
|
type UserAccount struct {
|
|
// UserID identifies the durable regular-user account.
|
|
UserID common.UserID
|
|
|
|
// Email stores the normalized login/contact address of the account.
|
|
Email common.Email
|
|
|
|
// RaceName stores the original-casing user-facing race name.
|
|
RaceName common.RaceName
|
|
|
|
// PreferredLanguage stores the current declared language tag.
|
|
PreferredLanguage common.LanguageTag
|
|
|
|
// TimeZone stores the current declared time-zone name.
|
|
TimeZone common.TimeZoneName
|
|
|
|
// DeclaredCountry stores the latest effective declared-country value. The
|
|
// zero value means the geo workflow has not synchronized any country yet.
|
|
DeclaredCountry common.CountryCode
|
|
|
|
// CreatedAt stores the account creation timestamp.
|
|
CreatedAt time.Time
|
|
|
|
// UpdatedAt stores the last account mutation timestamp.
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// Validate reports whether UserAccount satisfies the frozen Stage 02
|
|
// structural invariants.
|
|
func (record UserAccount) Validate() error {
|
|
if err := record.UserID.Validate(); err != nil {
|
|
return fmt.Errorf("user account user id: %w", err)
|
|
}
|
|
if err := record.Email.Validate(); err != nil {
|
|
return fmt.Errorf("user account email: %w", err)
|
|
}
|
|
if err := record.RaceName.Validate(); err != nil {
|
|
return fmt.Errorf("user account race name: %w", err)
|
|
}
|
|
if err := record.PreferredLanguage.Validate(); err != nil {
|
|
return fmt.Errorf("user account preferred language: %w", err)
|
|
}
|
|
if err := record.TimeZone.Validate(); err != nil {
|
|
return fmt.Errorf("user account time zone: %w", err)
|
|
}
|
|
if !record.DeclaredCountry.IsZero() {
|
|
if err := record.DeclaredCountry.Validate(); err != nil {
|
|
return fmt.Errorf("user account declared country: %w", err)
|
|
}
|
|
}
|
|
if err := common.ValidateTimestamp("user account created at", record.CreatedAt); err != nil {
|
|
return err
|
|
}
|
|
if err := common.ValidateTimestamp("user account updated at", record.UpdatedAt); err != nil {
|
|
return err
|
|
}
|
|
if record.UpdatedAt.Before(record.CreatedAt) {
|
|
return fmt.Errorf("user account updated at must not be before created at")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RaceNameReservation stores the current uniqueness reservation for one
|
|
// canonicalized race-name key.
|
|
type RaceNameReservation struct {
|
|
// CanonicalKey stores the policy-produced uniqueness key.
|
|
CanonicalKey RaceNameCanonicalKey
|
|
|
|
// UserID identifies the account that owns the reservation.
|
|
UserID common.UserID
|
|
|
|
// RaceName stores the original-casing name linked to the reservation.
|
|
RaceName common.RaceName
|
|
|
|
// ReservedAt stores when the reservation was acquired.
|
|
ReservedAt time.Time
|
|
}
|
|
|
|
// Validate reports whether RaceNameReservation satisfies the frozen Stage 02
|
|
// structural invariants.
|
|
func (record RaceNameReservation) Validate() error {
|
|
if err := record.CanonicalKey.Validate(); err != nil {
|
|
return fmt.Errorf("race name reservation canonical key: %w", err)
|
|
}
|
|
if err := record.UserID.Validate(); err != nil {
|
|
return fmt.Errorf("race name reservation user id: %w", err)
|
|
}
|
|
if err := record.RaceName.Validate(); err != nil {
|
|
return fmt.Errorf("race name reservation race name: %w", err)
|
|
}
|
|
if err := common.ValidateTimestamp("race name reservation reserved at", record.ReservedAt); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|