feat: game lobby service
This commit is contained in:
@@ -21,6 +21,7 @@ func TestApplySanctionServiceExecutePublishesEvent(t *testing.T) {
|
||||
limitStore := newFakeLimitStore()
|
||||
publisher := &recordingPolicyPublisher{}
|
||||
|
||||
lifecyclePublisher := &fakeLifecyclePublisher{}
|
||||
service, err := NewApplySanctionServiceWithObservability(
|
||||
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
||||
sanctionStore,
|
||||
@@ -31,6 +32,7 @@ func TestApplySanctionServiceExecutePublishesEvent(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
publisher,
|
||||
lifecyclePublisher,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -47,8 +49,130 @@ func TestApplySanctionServiceExecutePublishesEvent(t *testing.T) {
|
||||
require.Len(t, publisher.sanctionEvents, 1)
|
||||
require.Equal(t, ports.SanctionChangedOperationApplied, publisher.sanctionEvents[0].Operation)
|
||||
require.Equal(t, common.Source("admin_internal_api"), publisher.sanctionEvents[0].Source)
|
||||
require.Empty(t, lifecyclePublisher.events,
|
||||
"login_block must not emit a user.lifecycle.permanent_blocked event")
|
||||
}
|
||||
|
||||
func TestApplySanctionServiceExecutePermanentBlockPublishesLifecycleEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
now := time.Unix(1_775_240_000, 0).UTC()
|
||||
userID := common.UserID("user-123")
|
||||
sanctionStore := newFakeSanctionStore()
|
||||
limitStore := newFakeLimitStore()
|
||||
publisher := &recordingPolicyPublisher{}
|
||||
lifecyclePublisher := &fakeLifecyclePublisher{}
|
||||
|
||||
service, err := NewApplySanctionServiceWithObservability(
|
||||
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
||||
sanctionStore,
|
||||
limitStore,
|
||||
&fakePolicyLifecycleStore{sanctions: sanctionStore, limits: limitStore},
|
||||
fixedClock{now: now},
|
||||
fixedIDGenerator{sanctionRecordID: policy.SanctionRecordID("sanction-1")},
|
||||
nil,
|
||||
nil,
|
||||
publisher,
|
||||
lifecyclePublisher,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
appliedAt := now.Add(-time.Minute)
|
||||
_, err = service.Execute(context.Background(), ApplySanctionInput{
|
||||
UserID: userID.String(),
|
||||
SanctionCode: string(policy.SanctionCodePermanentBlock),
|
||||
Scope: "platform",
|
||||
ReasonCode: "terminal_policy_violation",
|
||||
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
||||
AppliedAt: appliedAt.Format(time.RFC3339Nano),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, publisher.sanctionEvents, 1)
|
||||
require.Len(t, lifecyclePublisher.events, 1)
|
||||
emitted := lifecyclePublisher.events[0]
|
||||
require.Equal(t, ports.UserLifecyclePermanentBlockedEventType, emitted.EventType)
|
||||
require.Equal(t, userID, emitted.UserID)
|
||||
require.True(t, emitted.OccurredAt.Equal(appliedAt.UTC()))
|
||||
require.Equal(t, common.Source("admin_internal_api"), emitted.Source)
|
||||
require.Equal(t, common.ReasonCode("terminal_policy_violation"), emitted.ReasonCode)
|
||||
require.Equal(t, common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")}, emitted.Actor)
|
||||
}
|
||||
|
||||
func TestRemoveSanctionServicePermanentBlockDoesNotEmitLifecycleEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
now := time.Unix(1_775_240_000, 0).UTC()
|
||||
userID := common.UserID("user-123")
|
||||
sanctionStore := newFakeSanctionStore()
|
||||
limitStore := newFakeLimitStore()
|
||||
publisher := &recordingPolicyPublisher{}
|
||||
lifecyclePublisher := &fakeLifecyclePublisher{}
|
||||
|
||||
// First, apply permanent_block so a subsequent remove has an active record
|
||||
// to target.
|
||||
applyService, err := NewApplySanctionServiceWithObservability(
|
||||
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
||||
sanctionStore,
|
||||
limitStore,
|
||||
&fakePolicyLifecycleStore{sanctions: sanctionStore, limits: limitStore},
|
||||
fixedClock{now: now},
|
||||
fixedIDGenerator{sanctionRecordID: policy.SanctionRecordID("sanction-1")},
|
||||
nil,
|
||||
nil,
|
||||
publisher,
|
||||
lifecyclePublisher,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = applyService.Execute(context.Background(), ApplySanctionInput{
|
||||
UserID: userID.String(),
|
||||
SanctionCode: string(policy.SanctionCodePermanentBlock),
|
||||
Scope: "platform",
|
||||
ReasonCode: "terminal_policy_violation",
|
||||
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
||||
AppliedAt: now.Add(-time.Hour).Format(time.RFC3339Nano),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, lifecyclePublisher.events, 1)
|
||||
|
||||
removeService, err := NewRemoveSanctionServiceWithObservability(
|
||||
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
||||
sanctionStore,
|
||||
limitStore,
|
||||
&fakePolicyLifecycleStore{sanctions: sanctionStore, limits: limitStore},
|
||||
fixedClock{now: now},
|
||||
fixedIDGenerator{},
|
||||
nil,
|
||||
nil,
|
||||
publisher,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = removeService.Execute(context.Background(), RemoveSanctionInput{
|
||||
UserID: userID.String(),
|
||||
SanctionCode: string(policy.SanctionCodePermanentBlock),
|
||||
ReasonCode: "appeal_granted",
|
||||
Actor: ActorInput{Type: "admin", ID: "admin-2"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, lifecyclePublisher.events, 1,
|
||||
"remove-sanction must not emit an additional lifecycle event")
|
||||
}
|
||||
|
||||
type fakeLifecyclePublisher struct {
|
||||
events []ports.UserLifecycleEvent
|
||||
}
|
||||
|
||||
func (publisher *fakeLifecyclePublisher) PublishUserLifecycleEvent(_ context.Context, event ports.UserLifecycleEvent) error {
|
||||
if err := event.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
publisher.events = append(publisher.events, event)
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ ports.UserLifecyclePublisher = (*fakeLifecyclePublisher)(nil)
|
||||
|
||||
func TestRemoveSanctionServiceExecuteMissingDoesNotPublishEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user