feat: game lobby service
This commit is contained in:
@@ -55,8 +55,9 @@ type UpdateMyProfileInput struct {
|
||||
// UserID stores the authenticated regular-user identifier.
|
||||
UserID string
|
||||
|
||||
// RaceName stores the requested exact replacement race name.
|
||||
RaceName string
|
||||
// DisplayName stores the requested replacement display name. An empty
|
||||
// value resets the stored display name.
|
||||
DisplayName string
|
||||
}
|
||||
|
||||
// UpdateMyProfileResult stores one self-service profile mutation result.
|
||||
@@ -123,6 +124,9 @@ func (service *AccountGetter) Execute(ctx context.Context, input GetMyAccountInp
|
||||
if err != nil {
|
||||
return GetMyAccountResult{}, err
|
||||
}
|
||||
if state.HasActiveSanction(policy.SanctionCodePermanentBlock) {
|
||||
return GetMyAccountResult{}, shared.Conflict()
|
||||
}
|
||||
|
||||
return GetMyAccountResult{Account: state.View()}, nil
|
||||
}
|
||||
@@ -131,7 +135,6 @@ func (service *AccountGetter) Execute(ctx context.Context, input GetMyAccountInp
|
||||
type ProfileUpdater struct {
|
||||
accounts ports.UserAccountStore
|
||||
loader *accountview.Loader
|
||||
policy ports.RaceNamePolicy
|
||||
clock ports.Clock
|
||||
logger *slog.Logger
|
||||
telemetry *telemetry.Runtime
|
||||
@@ -145,9 +148,8 @@ func NewProfileUpdater(
|
||||
sanctions ports.SanctionStore,
|
||||
limits ports.LimitStore,
|
||||
clock ports.Clock,
|
||||
policy ports.RaceNamePolicy,
|
||||
) (*ProfileUpdater, error) {
|
||||
return NewProfileUpdaterWithObservability(accounts, entitlements, sanctions, limits, clock, policy, nil, nil, nil)
|
||||
return NewProfileUpdaterWithObservability(accounts, entitlements, sanctions, limits, clock, nil, nil, nil)
|
||||
}
|
||||
|
||||
// NewProfileUpdaterWithObservability constructs one self-service
|
||||
@@ -158,7 +160,6 @@ func NewProfileUpdaterWithObservability(
|
||||
sanctions ports.SanctionStore,
|
||||
limits ports.LimitStore,
|
||||
clock ports.Clock,
|
||||
policy ports.RaceNamePolicy,
|
||||
logger *slog.Logger,
|
||||
telemetryRuntime *telemetry.Runtime,
|
||||
profilePublisher ports.ProfileChangedPublisher,
|
||||
@@ -167,14 +168,10 @@ func NewProfileUpdaterWithObservability(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("selfservice profile updater: %w", err)
|
||||
}
|
||||
if policy == nil {
|
||||
return nil, fmt.Errorf("selfservice profile updater: race-name policy must not be nil")
|
||||
}
|
||||
|
||||
return &ProfileUpdater{
|
||||
accounts: accounts,
|
||||
loader: loader,
|
||||
policy: policy,
|
||||
clock: clock,
|
||||
logger: logger,
|
||||
telemetry: telemetryRuntime,
|
||||
@@ -204,7 +201,7 @@ func (service *ProfileUpdater) Execute(ctx context.Context, input UpdateMyProfil
|
||||
return UpdateMyProfileResult{}, err
|
||||
}
|
||||
userIDString = userID.String()
|
||||
raceName, err := parseRaceName(input.RaceName)
|
||||
displayName, err := shared.ParseDisplayName(input.DisplayName)
|
||||
if err != nil {
|
||||
return UpdateMyProfileResult{}, err
|
||||
}
|
||||
@@ -213,33 +210,22 @@ func (service *ProfileUpdater) Execute(ctx context.Context, input UpdateMyProfil
|
||||
if err != nil {
|
||||
return UpdateMyProfileResult{}, err
|
||||
}
|
||||
if state.HasActiveSanction(policy.SanctionCodePermanentBlock) {
|
||||
return UpdateMyProfileResult{}, shared.Conflict()
|
||||
}
|
||||
if state.HasActiveSanction(policy.SanctionCodeProfileUpdateBlock) {
|
||||
return UpdateMyProfileResult{}, shared.Conflict()
|
||||
}
|
||||
if state.AccountRecord.RaceName == raceName {
|
||||
if state.AccountRecord.DisplayName == displayName {
|
||||
outcome = "noop"
|
||||
return UpdateMyProfileResult{Account: state.View()}, nil
|
||||
}
|
||||
|
||||
now := service.clock.Now().UTC()
|
||||
currentCanonicalKey, err := service.policy.CanonicalKey(state.AccountRecord.RaceName)
|
||||
if err != nil {
|
||||
return UpdateMyProfileResult{}, shared.ServiceUnavailable(fmt.Errorf("canonicalize current race name: %w", err))
|
||||
}
|
||||
reservation, err := shared.BuildRaceNameReservation(service.policy, userID, raceName, now)
|
||||
if err != nil {
|
||||
return UpdateMyProfileResult{}, shared.ServiceUnavailable(err)
|
||||
}
|
||||
if err := service.accounts.RenameRaceName(ctx, ports.RenameRaceNameInput{
|
||||
UserID: userID,
|
||||
CurrentCanonicalKey: currentCanonicalKey,
|
||||
NewRaceName: raceName,
|
||||
NewReservation: reservation,
|
||||
UpdatedAt: now,
|
||||
}); err != nil {
|
||||
if errors.Is(err, ports.ErrRaceNameConflict) && service.telemetry != nil {
|
||||
service.telemetry.RecordRaceNameReservationConflict(ctx, "update_my_profile")
|
||||
}
|
||||
record := state.AccountRecord
|
||||
record.DisplayName = displayName
|
||||
record.UpdatedAt = now
|
||||
if err := service.accounts.Update(ctx, record); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, ports.ErrNotFound):
|
||||
return UpdateMyProfileResult{}, shared.SubjectNotFound()
|
||||
@@ -344,6 +330,9 @@ func (service *SettingsUpdater) Execute(ctx context.Context, input UpdateMySetti
|
||||
if err != nil {
|
||||
return UpdateMySettingsResult{}, err
|
||||
}
|
||||
if state.HasActiveSanction(policy.SanctionCodePermanentBlock) {
|
||||
return UpdateMySettingsResult{}, shared.Conflict()
|
||||
}
|
||||
if state.HasActiveSanction(policy.SanctionCodeProfileUpdateBlock) {
|
||||
return UpdateMySettingsResult{}, shared.Conflict()
|
||||
}
|
||||
@@ -379,10 +368,6 @@ func (service *SettingsUpdater) Execute(ctx context.Context, input UpdateMySetti
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func parseRaceName(value string) (common.RaceName, error) {
|
||||
return shared.ParseRaceName(value)
|
||||
}
|
||||
|
||||
func parsePreferredLanguage(value string) (common.LanguageTag, error) {
|
||||
languageTag, err := shared.ParseLanguageTag(value)
|
||||
if err != nil {
|
||||
@@ -423,11 +408,12 @@ func (service *ProfileUpdater) publishProfileChanged(ctx context.Context, record
|
||||
}
|
||||
|
||||
event := ports.ProfileChangedEvent{
|
||||
UserID: record.UserID,
|
||||
OccurredAt: record.UpdatedAt.UTC(),
|
||||
Source: gatewaySelfServiceSource,
|
||||
Operation: ports.ProfileChangedOperationUpdated,
|
||||
RaceName: record.RaceName,
|
||||
UserID: record.UserID,
|
||||
OccurredAt: record.UpdatedAt.UTC(),
|
||||
Source: gatewaySelfServiceSource,
|
||||
Operation: ports.ProfileChangedOperationUpdated,
|
||||
UserName: record.UserName,
|
||||
DisplayName: record.DisplayName,
|
||||
}
|
||||
if err := service.profilePublisher.PublishProfileChanged(ctx, event); err != nil {
|
||||
if service.telemetry != nil {
|
||||
|
||||
Reference in New Issue
Block a user