624 lines
21 KiB
Go
624 lines
21 KiB
Go
package adminusers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/user/internal/domain/account"
|
|
"galaxy/user/internal/domain/common"
|
|
"galaxy/user/internal/domain/entitlement"
|
|
"galaxy/user/internal/domain/policy"
|
|
"galaxy/user/internal/ports"
|
|
"galaxy/user/internal/service/entitlementsvc"
|
|
"galaxy/user/internal/service/shared"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestByIDGetterExecuteReturnsAggregate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
service, err := NewByIDGetter(
|
|
newFakeAdminAccountStore(validAdminUserAccount("user-123", "pilot@example.com", "Pilot Nova", now)),
|
|
&fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-123"): validAdminFreeSnapshot(common.UserID("user-123"), now),
|
|
},
|
|
},
|
|
fakeAdminSanctionStore{
|
|
byUserID: map[common.UserID][]policy.SanctionRecord{
|
|
common.UserID("user-123"): {
|
|
validAdminActiveSanction(common.UserID("user-123"), policy.SanctionCodeLoginBlock, now.Add(-time.Hour)),
|
|
expiredAdminSanction(common.UserID("user-123"), policy.SanctionCodeGameJoinBlock, now.Add(-2*time.Hour)),
|
|
},
|
|
},
|
|
},
|
|
fakeAdminLimitStore{
|
|
byUserID: map[common.UserID][]policy.LimitRecord{
|
|
common.UserID("user-123"): {
|
|
validAdminActiveLimit(common.UserID("user-123"), policy.LimitCodeMaxOwnedPrivateGames, 3, now.Add(-time.Hour)),
|
|
},
|
|
},
|
|
},
|
|
adminFixedClock{now: now},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), GetUserByIDInput{UserID: " user-123 "})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "user-123", result.User.UserID)
|
|
require.Equal(t, "pilot@example.com", result.User.Email)
|
|
require.Len(t, result.User.ActiveSanctions, 1)
|
|
require.Equal(t, string(policy.SanctionCodeLoginBlock), result.User.ActiveSanctions[0].SanctionCode)
|
|
require.Len(t, result.User.ActiveLimits, 1)
|
|
require.Equal(t, string(policy.LimitCodeMaxOwnedPrivateGames), result.User.ActiveLimits[0].LimitCode)
|
|
}
|
|
|
|
func TestByEmailGetterExecuteUnknownUserReturnsNotFound(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
service, err := NewByEmailGetter(
|
|
newFakeAdminAccountStore(),
|
|
&fakeAdminEntitlementSnapshotStore{},
|
|
fakeAdminSanctionStore{},
|
|
fakeAdminLimitStore{},
|
|
adminFixedClock{now: time.Unix(1_775_240_500, 0).UTC()},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.Execute(context.Background(), GetUserByEmailInput{Email: "missing@example.com"})
|
|
require.Error(t, err)
|
|
require.Equal(t, shared.ErrorCodeSubjectNotFound, shared.CodeOf(err))
|
|
}
|
|
|
|
func TestByRaceNameGetterExecuteReturnsAggregate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
service, err := NewByRaceNameGetter(
|
|
newFakeAdminAccountStore(validAdminUserAccount("user-123", "pilot@example.com", "Pilot Nova", now)),
|
|
&fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-123"): validAdminFreeSnapshot(common.UserID("user-123"), now),
|
|
},
|
|
},
|
|
fakeAdminSanctionStore{},
|
|
fakeAdminLimitStore{},
|
|
adminFixedClock{now: now},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), GetUserByRaceNameInput{RaceName: " Pilot Nova "})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "user-123", result.User.UserID)
|
|
require.Equal(t, "Pilot Nova", result.User.RaceName)
|
|
}
|
|
|
|
func TestListerExecuteAppliesCombinedFiltersWithLogicalAND(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
firstExpiry := now.Add(48 * time.Hour)
|
|
secondExpiry := now.Add(72 * time.Hour)
|
|
before := now.Add(96 * time.Hour)
|
|
after := now.Add(24 * time.Hour)
|
|
canLogin := false
|
|
canCreatePrivateGame := false
|
|
canJoinGame := false
|
|
|
|
accountStore := newFakeAdminAccountStore(
|
|
validAdminUserAccount("user-300", "u300@example.com", "User 300", now),
|
|
validAdminUserAccount("user-200", "u200@example.com", "User 200", now),
|
|
validAdminUserAccount("user-100", "u100@example.com", "User 100", now),
|
|
)
|
|
snapshotStore := &fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-300"): validAdminPaidSnapshot(common.UserID("user-300"), now, firstExpiry),
|
|
common.UserID("user-200"): validAdminPaidSnapshot(common.UserID("user-200"), now, secondExpiry),
|
|
common.UserID("user-100"): validAdminPaidSnapshot(common.UserID("user-100"), now, secondExpiry),
|
|
},
|
|
}
|
|
sanctionStore := fakeAdminSanctionStore{
|
|
byUserID: map[common.UserID][]policy.SanctionRecord{
|
|
common.UserID("user-300"): {
|
|
validAdminActiveSanction(common.UserID("user-300"), policy.SanctionCodeLoginBlock, now.Add(-time.Hour)),
|
|
},
|
|
common.UserID("user-200"): {
|
|
validAdminActiveSanction(common.UserID("user-200"), policy.SanctionCodeLoginBlock, now.Add(-time.Hour)),
|
|
},
|
|
common.UserID("user-100"): {
|
|
validAdminActiveSanction(common.UserID("user-100"), policy.SanctionCodeLoginBlock, now.Add(-time.Hour)),
|
|
},
|
|
},
|
|
}
|
|
limitStore := fakeAdminLimitStore{
|
|
byUserID: map[common.UserID][]policy.LimitRecord{
|
|
common.UserID("user-300"): {
|
|
validAdminActiveLimit(common.UserID("user-300"), policy.LimitCodeMaxOwnedPrivateGames, 3, now.Add(-time.Hour)),
|
|
},
|
|
common.UserID("user-100"): {
|
|
validAdminActiveLimit(common.UserID("user-100"), policy.LimitCodeMaxOwnedPrivateGames, 3, now.Add(-time.Hour)),
|
|
},
|
|
},
|
|
}
|
|
listStore := &fakeAdminListStore{
|
|
pages: map[string]ports.ListUsersResult{
|
|
"": {
|
|
UserIDs: []common.UserID{common.UserID("user-300")},
|
|
NextPageToken: "cursor-1",
|
|
},
|
|
"cursor-1": {
|
|
UserIDs: []common.UserID{common.UserID("user-200")},
|
|
NextPageToken: "cursor-2",
|
|
},
|
|
"cursor-2": {
|
|
UserIDs: []common.UserID{common.UserID("user-100")},
|
|
NextPageToken: "",
|
|
},
|
|
},
|
|
}
|
|
|
|
service, err := NewLister(accountStore, snapshotStore, sanctionStore, limitStore, adminFixedClock{now: now}, listStore)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), ListUsersInput{
|
|
PageSize: 2,
|
|
PaidState: "paid",
|
|
PaidExpiresBefore: &before,
|
|
PaidExpiresAfter: &after,
|
|
DeclaredCountry: "DE",
|
|
SanctionCode: "login_block",
|
|
LimitCode: "max_owned_private_games",
|
|
CanLogin: &canLogin,
|
|
CanCreatePrivateGame: &canCreatePrivateGame,
|
|
CanJoinGame: &canJoinGame,
|
|
})
|
|
require.NoError(t, err)
|
|
require.Len(t, result.Items, 2)
|
|
require.Equal(t, "user-300", result.Items[0].UserID)
|
|
require.Equal(t, "user-100", result.Items[1].UserID)
|
|
require.Equal(t, "", result.NextPageToken)
|
|
require.Len(t, listStore.calls, 3)
|
|
for _, call := range listStore.calls {
|
|
require.Equal(t, 1, call.PageSize)
|
|
require.Equal(t, entitlement.PaidStatePaid, call.Filters.PaidState)
|
|
require.Equal(t, common.CountryCode("DE"), call.Filters.DeclaredCountry)
|
|
require.Equal(t, policy.SanctionCodeLoginBlock, call.Filters.SanctionCode)
|
|
require.Equal(t, policy.LimitCodeMaxOwnedPrivateGames, call.Filters.LimitCode)
|
|
}
|
|
}
|
|
|
|
func TestListerExecuteDefaultAndMaximumPageSize(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
accountStore := newFakeAdminAccountStore(
|
|
validAdminUserAccount("user-300", "u300@example.com", "User 300", now),
|
|
validAdminUserAccount("user-200", "u200@example.com", "User 200", now),
|
|
validAdminUserAccount("user-100", "u100@example.com", "User 100", now),
|
|
)
|
|
snapshotStore := &fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-300"): validAdminFreeSnapshot(common.UserID("user-300"), now),
|
|
common.UserID("user-200"): validAdminFreeSnapshot(common.UserID("user-200"), now),
|
|
common.UserID("user-100"): validAdminFreeSnapshot(common.UserID("user-100"), now),
|
|
},
|
|
}
|
|
|
|
t.Run("default page size", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
listStore := &fakeAdminListStore{
|
|
pages: map[string]ports.ListUsersResult{
|
|
"": {
|
|
UserIDs: []common.UserID{common.UserID("user-300")},
|
|
NextPageToken: "cursor-1",
|
|
},
|
|
"cursor-1": {
|
|
UserIDs: []common.UserID{common.UserID("user-200")},
|
|
NextPageToken: "cursor-2",
|
|
},
|
|
"cursor-2": {
|
|
UserIDs: []common.UserID{common.UserID("user-100")},
|
|
NextPageToken: "",
|
|
},
|
|
},
|
|
}
|
|
service, err := NewLister(accountStore, snapshotStore, fakeAdminSanctionStore{}, fakeAdminLimitStore{}, adminFixedClock{now: now}, listStore)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), ListUsersInput{})
|
|
require.NoError(t, err)
|
|
require.Len(t, result.Items, 3)
|
|
})
|
|
|
|
t.Run("maximum page size", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
listStore := &fakeAdminListStore{
|
|
pages: map[string]ports.ListUsersResult{
|
|
"": {
|
|
UserIDs: []common.UserID{common.UserID("user-300")},
|
|
NextPageToken: "",
|
|
},
|
|
},
|
|
}
|
|
service, err := NewLister(accountStore, snapshotStore, fakeAdminSanctionStore{}, fakeAdminLimitStore{}, adminFixedClock{now: now}, listStore)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), ListUsersInput{PageSize: ports.MaxUserListPageSize})
|
|
require.NoError(t, err)
|
|
require.Len(t, result.Items, 1)
|
|
})
|
|
|
|
t.Run("above maximum is rejected", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
service, err := NewLister(accountStore, snapshotStore, fakeAdminSanctionStore{}, fakeAdminLimitStore{}, adminFixedClock{now: now}, &fakeAdminListStore{})
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.Execute(context.Background(), ListUsersInput{PageSize: ports.MaxUserListPageSize + 1})
|
|
require.Error(t, err)
|
|
require.Equal(t, shared.ErrorCodeInvalidRequest, shared.CodeOf(err))
|
|
require.Equal(t, "page_size must be between 1 and 200", err.Error())
|
|
})
|
|
}
|
|
|
|
func TestListerExecuteInvalidPageTokenReturnsInvalidRequest(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
service, err := NewLister(
|
|
newFakeAdminAccountStore(validAdminUserAccount("user-123", "pilot@example.com", "Pilot Nova", now)),
|
|
&fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-123"): validAdminFreeSnapshot(common.UserID("user-123"), now),
|
|
},
|
|
},
|
|
fakeAdminSanctionStore{},
|
|
fakeAdminLimitStore{},
|
|
adminFixedClock{now: now},
|
|
&fakeAdminListStore{err: fmt.Errorf("wrapped: %w", ports.ErrInvalidPageToken)},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
_, err = service.Execute(context.Background(), ListUsersInput{PageToken: "bad-token"})
|
|
require.Error(t, err)
|
|
require.Equal(t, shared.ErrorCodeInvalidRequest, shared.CodeOf(err))
|
|
require.Equal(t, "page_token is invalid or does not match current filters", err.Error())
|
|
}
|
|
|
|
func TestListerExecuteRepairsExpiredPaidSnapshotBeforeFiltering(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_500, 0).UTC()
|
|
expiredAt := now.Add(-time.Hour)
|
|
accountStore := newFakeAdminAccountStore(validAdminUserAccount("user-123", "pilot@example.com", "Pilot Nova", now))
|
|
snapshotStore := &fakeAdminEntitlementSnapshotStore{
|
|
byUserID: map[common.UserID]entitlement.CurrentSnapshot{
|
|
common.UserID("user-123"): {
|
|
UserID: common.UserID("user-123"),
|
|
PlanCode: entitlement.PlanCodePaidMonthly,
|
|
IsPaid: true,
|
|
StartsAt: now.Add(-30 * 24 * time.Hour),
|
|
EndsAt: adminTimePointer(expiredAt),
|
|
Source: common.Source("admin"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
ReasonCode: common.ReasonCode("manual_grant"),
|
|
UpdatedAt: expiredAt,
|
|
},
|
|
},
|
|
}
|
|
reader, err := entitlementsvc.NewReader(
|
|
snapshotStore,
|
|
&fakeAdminEntitlementLifecycleStore{snapshotStore: snapshotStore},
|
|
adminFixedClock{now: now},
|
|
adminReaderIDGenerator{recordID: entitlement.EntitlementRecordID("entitlement-repair-free-record")},
|
|
)
|
|
require.NoError(t, err)
|
|
listStore := &fakeAdminListStore{
|
|
pages: map[string]ports.ListUsersResult{
|
|
"": {
|
|
UserIDs: []common.UserID{common.UserID("user-123")},
|
|
NextPageToken: "",
|
|
},
|
|
},
|
|
}
|
|
service, err := NewLister(accountStore, reader, fakeAdminSanctionStore{}, fakeAdminLimitStore{}, adminFixedClock{now: now}, listStore)
|
|
require.NoError(t, err)
|
|
|
|
result, err := service.Execute(context.Background(), ListUsersInput{PaidState: "free"})
|
|
require.NoError(t, err)
|
|
require.Len(t, result.Items, 1)
|
|
require.Equal(t, "free", result.Items[0].Entitlement.PlanCode)
|
|
require.False(t, result.Items[0].Entitlement.IsPaid)
|
|
|
|
storedSnapshot, err := snapshotStore.GetByUserID(context.Background(), common.UserID("user-123"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, entitlement.PlanCodeFree, storedSnapshot.PlanCode)
|
|
require.False(t, storedSnapshot.IsPaid)
|
|
require.Equal(t, expiredAt, storedSnapshot.StartsAt)
|
|
}
|
|
|
|
type adminFixedClock struct {
|
|
now time.Time
|
|
}
|
|
|
|
func (clock adminFixedClock) Now() time.Time {
|
|
return clock.now
|
|
}
|
|
|
|
type adminReaderIDGenerator struct {
|
|
recordID entitlement.EntitlementRecordID
|
|
}
|
|
|
|
func (generator adminReaderIDGenerator) NewUserID() (common.UserID, error) {
|
|
return "", errors.New("unexpected NewUserID call")
|
|
}
|
|
|
|
func (generator adminReaderIDGenerator) NewInitialRaceName() (common.RaceName, error) {
|
|
return "", errors.New("unexpected NewInitialRaceName call")
|
|
}
|
|
|
|
func (generator adminReaderIDGenerator) NewEntitlementRecordID() (entitlement.EntitlementRecordID, error) {
|
|
return generator.recordID, nil
|
|
}
|
|
|
|
func (generator adminReaderIDGenerator) NewSanctionRecordID() (policy.SanctionRecordID, error) {
|
|
return "", errors.New("unexpected NewSanctionRecordID call")
|
|
}
|
|
|
|
func (generator adminReaderIDGenerator) NewLimitRecordID() (policy.LimitRecordID, error) {
|
|
return "", errors.New("unexpected NewLimitRecordID call")
|
|
}
|
|
|
|
type fakeAdminAccountStore struct {
|
|
byUserID map[common.UserID]account.UserAccount
|
|
byEmail map[common.Email]common.UserID
|
|
byRaceName map[common.RaceName]common.UserID
|
|
updateErr error
|
|
renameErr error
|
|
createErr error
|
|
existsByID map[common.UserID]bool
|
|
}
|
|
|
|
func newFakeAdminAccountStore(records ...account.UserAccount) *fakeAdminAccountStore {
|
|
store := &fakeAdminAccountStore{
|
|
byUserID: make(map[common.UserID]account.UserAccount, len(records)),
|
|
byEmail: make(map[common.Email]common.UserID, len(records)),
|
|
byRaceName: make(map[common.RaceName]common.UserID, len(records)),
|
|
existsByID: make(map[common.UserID]bool, len(records)),
|
|
}
|
|
|
|
for _, record := range records {
|
|
store.byUserID[record.UserID] = record
|
|
store.byEmail[record.Email] = record.UserID
|
|
store.byRaceName[record.RaceName] = record.UserID
|
|
store.existsByID[record.UserID] = true
|
|
}
|
|
|
|
return store
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) Create(context.Context, ports.CreateAccountInput) error {
|
|
return store.createErr
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) GetByUserID(_ context.Context, userID common.UserID) (account.UserAccount, error) {
|
|
record, ok := store.byUserID[userID]
|
|
if !ok {
|
|
return account.UserAccount{}, ports.ErrNotFound
|
|
}
|
|
|
|
return record, nil
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) GetByEmail(_ context.Context, email common.Email) (account.UserAccount, error) {
|
|
userID, ok := store.byEmail[email]
|
|
if !ok {
|
|
return account.UserAccount{}, ports.ErrNotFound
|
|
}
|
|
|
|
return store.byUserID[userID], nil
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) GetByRaceName(_ context.Context, raceName common.RaceName) (account.UserAccount, error) {
|
|
userID, ok := store.byRaceName[raceName]
|
|
if !ok {
|
|
return account.UserAccount{}, ports.ErrNotFound
|
|
}
|
|
|
|
return store.byUserID[userID], nil
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) ExistsByUserID(_ context.Context, userID common.UserID) (bool, error) {
|
|
return store.existsByID[userID], nil
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) RenameRaceName(context.Context, ports.RenameRaceNameInput) error {
|
|
return store.renameErr
|
|
}
|
|
|
|
func (store *fakeAdminAccountStore) Update(context.Context, account.UserAccount) error {
|
|
return store.updateErr
|
|
}
|
|
|
|
type fakeAdminEntitlementSnapshotStore struct {
|
|
byUserID map[common.UserID]entitlement.CurrentSnapshot
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementSnapshotStore) GetByUserID(_ context.Context, userID common.UserID) (entitlement.CurrentSnapshot, error) {
|
|
record, ok := store.byUserID[userID]
|
|
if !ok {
|
|
return entitlement.CurrentSnapshot{}, ports.ErrNotFound
|
|
}
|
|
|
|
return record, nil
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementSnapshotStore) Put(_ context.Context, record entitlement.CurrentSnapshot) error {
|
|
if store.byUserID == nil {
|
|
store.byUserID = make(map[common.UserID]entitlement.CurrentSnapshot)
|
|
}
|
|
store.byUserID[record.UserID] = record
|
|
return nil
|
|
}
|
|
|
|
type fakeAdminEntitlementLifecycleStore struct {
|
|
snapshotStore *fakeAdminEntitlementSnapshotStore
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementLifecycleStore) Grant(context.Context, ports.GrantEntitlementInput) error {
|
|
return errors.New("unexpected Grant call")
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementLifecycleStore) Extend(context.Context, ports.ExtendEntitlementInput) error {
|
|
return errors.New("unexpected Extend call")
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementLifecycleStore) Revoke(context.Context, ports.RevokeEntitlementInput) error {
|
|
return errors.New("unexpected Revoke call")
|
|
}
|
|
|
|
func (store *fakeAdminEntitlementLifecycleStore) RepairExpired(ctx context.Context, input ports.RepairExpiredEntitlementInput) error {
|
|
return store.snapshotStore.Put(ctx, input.NewSnapshot)
|
|
}
|
|
|
|
type fakeAdminSanctionStore struct {
|
|
byUserID map[common.UserID][]policy.SanctionRecord
|
|
}
|
|
|
|
func (store fakeAdminSanctionStore) Create(context.Context, policy.SanctionRecord) error {
|
|
return nil
|
|
}
|
|
|
|
func (store fakeAdminSanctionStore) GetByRecordID(context.Context, policy.SanctionRecordID) (policy.SanctionRecord, error) {
|
|
return policy.SanctionRecord{}, ports.ErrNotFound
|
|
}
|
|
|
|
func (store fakeAdminSanctionStore) ListByUserID(_ context.Context, userID common.UserID) ([]policy.SanctionRecord, error) {
|
|
return append([]policy.SanctionRecord(nil), store.byUserID[userID]...), nil
|
|
}
|
|
|
|
func (store fakeAdminSanctionStore) Update(context.Context, policy.SanctionRecord) error {
|
|
return nil
|
|
}
|
|
|
|
type fakeAdminLimitStore struct {
|
|
byUserID map[common.UserID][]policy.LimitRecord
|
|
}
|
|
|
|
func (store fakeAdminLimitStore) Create(context.Context, policy.LimitRecord) error {
|
|
return nil
|
|
}
|
|
|
|
func (store fakeAdminLimitStore) GetByRecordID(context.Context, policy.LimitRecordID) (policy.LimitRecord, error) {
|
|
return policy.LimitRecord{}, ports.ErrNotFound
|
|
}
|
|
|
|
func (store fakeAdminLimitStore) ListByUserID(_ context.Context, userID common.UserID) ([]policy.LimitRecord, error) {
|
|
return append([]policy.LimitRecord(nil), store.byUserID[userID]...), nil
|
|
}
|
|
|
|
func (store fakeAdminLimitStore) Update(context.Context, policy.LimitRecord) error {
|
|
return nil
|
|
}
|
|
|
|
type fakeAdminListStore struct {
|
|
pages map[string]ports.ListUsersResult
|
|
err error
|
|
calls []ports.ListUsersInput
|
|
}
|
|
|
|
func (store *fakeAdminListStore) ListUserIDs(_ context.Context, input ports.ListUsersInput) (ports.ListUsersResult, error) {
|
|
store.calls = append(store.calls, input)
|
|
if store.err != nil {
|
|
return ports.ListUsersResult{}, store.err
|
|
}
|
|
result, ok := store.pages[input.PageToken]
|
|
if !ok {
|
|
return ports.ListUsersResult{}, nil
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func validAdminUserAccount(userID string, email string, raceName string, now time.Time) account.UserAccount {
|
|
return account.UserAccount{
|
|
UserID: common.UserID(userID),
|
|
Email: common.Email(email),
|
|
RaceName: common.RaceName(raceName),
|
|
PreferredLanguage: common.LanguageTag("en"),
|
|
TimeZone: common.TimeZoneName("Europe/Kaliningrad"),
|
|
DeclaredCountry: common.CountryCode("DE"),
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
}
|
|
|
|
func validAdminFreeSnapshot(userID common.UserID, now time.Time) entitlement.CurrentSnapshot {
|
|
return entitlement.CurrentSnapshot{
|
|
UserID: userID,
|
|
PlanCode: entitlement.PlanCodeFree,
|
|
IsPaid: false,
|
|
StartsAt: now,
|
|
Source: common.Source("auth_registration"),
|
|
Actor: common.ActorRef{Type: common.ActorType("service"), ID: common.ActorID("user-service")},
|
|
ReasonCode: common.ReasonCode("initial_free_entitlement"),
|
|
UpdatedAt: now,
|
|
}
|
|
}
|
|
|
|
func validAdminPaidSnapshot(userID common.UserID, now time.Time, endsAt time.Time) entitlement.CurrentSnapshot {
|
|
return entitlement.CurrentSnapshot{
|
|
UserID: userID,
|
|
PlanCode: entitlement.PlanCodePaidMonthly,
|
|
IsPaid: true,
|
|
StartsAt: now.Add(-24 * time.Hour),
|
|
EndsAt: adminTimePointer(endsAt),
|
|
Source: common.Source("admin"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
ReasonCode: common.ReasonCode("manual_grant"),
|
|
UpdatedAt: now,
|
|
}
|
|
}
|
|
|
|
func validAdminActiveSanction(userID common.UserID, code policy.SanctionCode, appliedAt time.Time) policy.SanctionRecord {
|
|
return policy.SanctionRecord{
|
|
RecordID: policy.SanctionRecordID("sanction-" + string(code) + "-" + userID.String()),
|
|
UserID: userID,
|
|
SanctionCode: code,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("manual_block"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: appliedAt,
|
|
}
|
|
}
|
|
|
|
func expiredAdminSanction(userID common.UserID, code policy.SanctionCode, appliedAt time.Time) policy.SanctionRecord {
|
|
record := validAdminActiveSanction(userID, code, appliedAt)
|
|
record.ExpiresAt = adminTimePointer(appliedAt.Add(30 * time.Minute))
|
|
return record
|
|
}
|
|
|
|
func validAdminActiveLimit(userID common.UserID, code policy.LimitCode, value int, appliedAt time.Time) policy.LimitRecord {
|
|
return policy.LimitRecord{
|
|
RecordID: policy.LimitRecordID("limit-" + string(code) + "-" + userID.String()),
|
|
UserID: userID,
|
|
LimitCode: code,
|
|
Value: value,
|
|
ReasonCode: common.ReasonCode("manual_override"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: appliedAt,
|
|
}
|
|
}
|
|
|
|
func adminTimePointer(value time.Time) *time.Time {
|
|
copied := value.UTC()
|
|
return &copied
|
|
}
|