281 lines
8.8 KiB
Go
281 lines
8.8 KiB
Go
package policy
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/user/internal/domain/common"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestSanctionRecordValidateAt(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
expiresAt := now.Add(time.Hour)
|
|
removedAt := now.Add(30 * time.Minute)
|
|
|
|
tests := []struct {
|
|
name string
|
|
record SanctionRecord
|
|
wantErr bool
|
|
wantActive bool
|
|
}{
|
|
{
|
|
name: "active",
|
|
record: SanctionRecord{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy_blocked"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-time.Minute),
|
|
ExpiresAt: &expiresAt,
|
|
},
|
|
wantActive: true,
|
|
},
|
|
{
|
|
name: "expired",
|
|
record: SanctionRecord{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy_blocked"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-2 * time.Hour),
|
|
ExpiresAt: ptrTime(now.Add(-time.Minute)),
|
|
},
|
|
},
|
|
{
|
|
name: "removed",
|
|
record: SanctionRecord{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy_blocked"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
RemovedAt: &removedAt,
|
|
RemovedBy: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-2")},
|
|
RemovedReasonCode: common.ReasonCode("manual_remove"),
|
|
},
|
|
},
|
|
{
|
|
name: "future applied at",
|
|
record: SanctionRecord{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy_blocked"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(time.Minute),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := tt.record.ValidateAt(now)
|
|
if tt.wantErr {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.wantActive, tt.record.IsActiveAt(now))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestActiveSanctionsAt(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
records := []SanctionRecord{
|
|
{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeProfileUpdateBlock,
|
|
Scope: common.Scope("profile"),
|
|
ReasonCode: common.ReasonCode("moderation"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
},
|
|
{
|
|
RecordID: SanctionRecordID("sanction-2"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-2")},
|
|
AppliedAt: now.Add(-2 * time.Hour),
|
|
ExpiresAt: ptrTime(now.Add(-time.Minute)),
|
|
},
|
|
}
|
|
|
|
active, err := ActiveSanctionsAt(records, now)
|
|
require.NoError(t, err)
|
|
require.Len(t, active, 1)
|
|
require.Equal(t, SanctionCodeProfileUpdateBlock, active[0].SanctionCode)
|
|
}
|
|
|
|
func TestSanctionCodeCatalog(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.True(t, SanctionCodeLoginBlock.IsKnown())
|
|
require.True(t, SanctionCodePrivateGameCreateBlock.IsKnown())
|
|
require.True(t, SanctionCodePrivateGameManageBlock.IsKnown())
|
|
require.True(t, SanctionCodeGameJoinBlock.IsKnown())
|
|
require.True(t, SanctionCodeProfileUpdateBlock.IsKnown())
|
|
require.True(t, SanctionCodePermanentBlock.IsKnown())
|
|
require.False(t, SanctionCode("unknown_code").IsKnown())
|
|
}
|
|
|
|
func TestActiveSanctionsAtPermanentBlockCoexistsWithOtherCodes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
records := []SanctionRecord{
|
|
{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodePermanentBlock,
|
|
Scope: common.Scope("platform"),
|
|
ReasonCode: common.ReasonCode("terminal_policy_violation"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
},
|
|
{
|
|
RecordID: SanctionRecordID("sanction-2"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-2 * time.Hour),
|
|
},
|
|
}
|
|
|
|
active, err := ActiveSanctionsAt(records, now)
|
|
require.NoError(t, err)
|
|
require.Len(t, active, 2)
|
|
require.Equal(t, SanctionCodeLoginBlock, active[0].SanctionCode)
|
|
require.Equal(t, SanctionCodePermanentBlock, active[1].SanctionCode)
|
|
}
|
|
|
|
func TestActiveSanctionsAtDuplicateActiveCode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
_, err := ActiveSanctionsAt([]SanctionRecord{
|
|
{
|
|
RecordID: SanctionRecordID("sanction-1"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
},
|
|
{
|
|
RecordID: SanctionRecordID("sanction-2"),
|
|
UserID: common.UserID("user-123"),
|
|
SanctionCode: SanctionCodeLoginBlock,
|
|
Scope: common.Scope("auth"),
|
|
ReasonCode: common.ReasonCode("policy"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-2 * time.Hour),
|
|
},
|
|
}, now)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestLimitRecordValidateAtAndActiveLimits(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
|
|
record := LimitRecord{
|
|
RecordID: LimitRecordID("limit-1"),
|
|
UserID: common.UserID("user-123"),
|
|
LimitCode: LimitCodeMaxOwnedPrivateGames,
|
|
Value: 3,
|
|
ReasonCode: common.ReasonCode("manual_override"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin"), ID: common.ActorID("admin-1")},
|
|
AppliedAt: now.Add(-time.Minute),
|
|
}
|
|
require.NoError(t, record.ValidateAt(now))
|
|
require.True(t, record.IsActiveAt(now))
|
|
|
|
active, err := ActiveLimitsAt([]LimitRecord{
|
|
record,
|
|
{
|
|
RecordID: LimitRecordID("limit-2"),
|
|
UserID: common.UserID("user-123"),
|
|
LimitCode: LimitCodeMaxActivePrivateGames,
|
|
Value: 7,
|
|
ReasonCode: common.ReasonCode("manual_override"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
},
|
|
}, now)
|
|
require.NoError(t, err)
|
|
require.Len(t, active, 1)
|
|
require.Equal(t, LimitCodeMaxOwnedPrivateGames, active[0].LimitCode)
|
|
}
|
|
|
|
func TestLimitCodeSupportAndRetiredRecognition(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.True(t, LimitCodeMaxOwnedPrivateGames.IsSupported())
|
|
require.True(t, LimitCodeMaxPendingPublicApplications.IsSupported())
|
|
require.True(t, LimitCodeMaxActiveGameMemberships.IsSupported())
|
|
|
|
require.True(t, LimitCodeMaxActivePrivateGames.IsRetired())
|
|
require.True(t, LimitCodeMaxPendingPrivateJoinRequests.IsRetired())
|
|
require.True(t, LimitCodeMaxPendingPrivateInvitesSent.IsRetired())
|
|
|
|
require.True(t, LimitCodeMaxActivePrivateGames.IsRecognized())
|
|
require.False(t, LimitCode("unknown_limit").IsRecognized())
|
|
require.False(t, LimitCodeMaxActivePrivateGames.IsKnown())
|
|
}
|
|
|
|
func TestActiveLimitsAtDuplicateActiveCode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Unix(1_775_240_000, 0).UTC()
|
|
_, err := ActiveLimitsAt([]LimitRecord{
|
|
{
|
|
RecordID: LimitRecordID("limit-1"),
|
|
UserID: common.UserID("user-123"),
|
|
LimitCode: LimitCodeMaxOwnedPrivateGames,
|
|
Value: 2,
|
|
ReasonCode: common.ReasonCode("manual_override"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-time.Hour),
|
|
},
|
|
{
|
|
RecordID: LimitRecordID("limit-2"),
|
|
UserID: common.UserID("user-123"),
|
|
LimitCode: LimitCodeMaxOwnedPrivateGames,
|
|
Value: 5,
|
|
ReasonCode: common.ReasonCode("manual_override"),
|
|
Actor: common.ActorRef{Type: common.ActorType("admin")},
|
|
AppliedAt: now.Add(-2 * time.Hour),
|
|
},
|
|
}, now)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func ptrTime(value time.Time) *time.Time {
|
|
return &value
|
|
}
|