179 lines
5.4 KiB
Go
179 lines
5.4 KiB
Go
package policysvc
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/user/internal/domain/common"
|
|
"galaxy/user/internal/domain/policy"
|
|
"galaxy/user/internal/ports"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestApplySanctionServiceExecutePublishesEvent(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{}
|
|
|
|
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,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.Execute(context.Background(), ApplySanctionInput{
|
|
UserID: userID.String(),
|
|
SanctionCode: string(policy.SanctionCodeLoginBlock),
|
|
Scope: "auth",
|
|
ReasonCode: "policy_blocked",
|
|
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
|
AppliedAt: now.Add(-time.Minute).Format(time.RFC3339Nano),
|
|
ExpiresAt: now.Add(time.Hour).Format(time.RFC3339Nano),
|
|
})
|
|
require.NoError(t, err)
|
|
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)
|
|
}
|
|
|
|
func TestRemoveSanctionServiceExecuteMissingDoesNotPublishEvent(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{}
|
|
|
|
service, 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 = service.Execute(context.Background(), RemoveSanctionInput{
|
|
UserID: userID.String(),
|
|
SanctionCode: string(policy.SanctionCodeLoginBlock),
|
|
ReasonCode: "manual_remove",
|
|
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Empty(t, publisher.sanctionEvents)
|
|
}
|
|
|
|
func TestSetLimitServiceExecutePublishesEvent(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{}
|
|
|
|
service, err := NewSetLimitServiceWithObservability(
|
|
fakeAccountStore{existsByUserID: map[common.UserID]bool{userID: true}},
|
|
sanctionStore,
|
|
limitStore,
|
|
&fakePolicyLifecycleStore{sanctions: sanctionStore, limits: limitStore},
|
|
fixedClock{now: now},
|
|
fixedIDGenerator{limitRecordID: policy.LimitRecordID("limit-1")},
|
|
nil,
|
|
nil,
|
|
publisher,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.Execute(context.Background(), SetLimitInput{
|
|
UserID: userID.String(),
|
|
LimitCode: string(policy.LimitCodeMaxOwnedPrivateGames),
|
|
Value: 5,
|
|
ReasonCode: "manual_override",
|
|
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
|
AppliedAt: now.Add(-time.Minute).Format(time.RFC3339Nano),
|
|
ExpiresAt: now.Add(time.Hour).Format(time.RFC3339Nano),
|
|
})
|
|
require.NoError(t, err)
|
|
require.Len(t, publisher.limitEvents, 1)
|
|
require.Equal(t, ports.LimitChangedOperationSet, publisher.limitEvents[0].Operation)
|
|
require.NotNil(t, publisher.limitEvents[0].Value)
|
|
require.Equal(t, 5, *publisher.limitEvents[0].Value)
|
|
}
|
|
|
|
func TestRemoveLimitServiceExecuteMissingDoesNotPublishEvent(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{}
|
|
|
|
service, err := NewRemoveLimitServiceWithObservability(
|
|
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 = service.Execute(context.Background(), RemoveLimitInput{
|
|
UserID: userID.String(),
|
|
LimitCode: string(policy.LimitCodeMaxOwnedPrivateGames),
|
|
ReasonCode: "manual_remove",
|
|
Actor: ActorInput{Type: "admin", ID: "admin-1"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Empty(t, publisher.limitEvents)
|
|
}
|
|
|
|
type recordingPolicyPublisher struct {
|
|
sanctionEvents []ports.SanctionChangedEvent
|
|
limitEvents []ports.LimitChangedEvent
|
|
}
|
|
|
|
func (publisher *recordingPolicyPublisher) PublishSanctionChanged(_ context.Context, event ports.SanctionChangedEvent) error {
|
|
if err := event.Validate(); err != nil {
|
|
return err
|
|
}
|
|
publisher.sanctionEvents = append(publisher.sanctionEvents, event)
|
|
return nil
|
|
}
|
|
|
|
func (publisher *recordingPolicyPublisher) PublishLimitChanged(_ context.Context, event ports.LimitChangedEvent) error {
|
|
if err := event.Validate(); err != nil {
|
|
return err
|
|
}
|
|
publisher.limitEvents = append(publisher.limitEvents, event)
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
_ ports.SanctionChangedPublisher = (*recordingPolicyPublisher)(nil)
|
|
_ ports.LimitChangedPublisher = (*recordingPolicyPublisher)(nil)
|
|
)
|