feat: support time_zone for user registration context
This commit is contained in:
@@ -11,10 +11,13 @@ import (
|
||||
"galaxy/authsession/internal/domain/common"
|
||||
"galaxy/authsession/internal/domain/devicesession"
|
||||
"galaxy/authsession/internal/domain/userresolution"
|
||||
"galaxy/authsession/internal/ports"
|
||||
"galaxy/authsession/internal/service/shared"
|
||||
"galaxy/authsession/internal/testkit"
|
||||
)
|
||||
|
||||
const confirmEmailCodeTimeZone = "Europe/Kaliningrad"
|
||||
|
||||
func TestExecuteConfirmsChallengeForExistingUser(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -31,6 +34,7 @@ func TestExecuteConfirmsChallengeForExistingUser(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "Execute() returned error: %v", err)
|
||||
@@ -75,6 +79,7 @@ func TestExecuteConfirmsChallengeByCreatingUser(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "Execute() returned error: %v", err)
|
||||
@@ -114,6 +119,7 @@ func TestExecuteConfirmsSuppressedChallenge(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "Execute() returned error: %v", err)
|
||||
@@ -132,6 +138,7 @@ func TestExecuteReturnsChallengeNotFound(t *testing.T) {
|
||||
ChallengeID: "missing",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeChallengeNotFound {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeChallengeNotFound)
|
||||
@@ -152,6 +159,7 @@ func TestExecuteReturnsChallengeExpiredAndMarksExpired(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeChallengeExpired {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeChallengeExpired)
|
||||
@@ -194,6 +202,7 @@ func TestExecuteReturnsChallengeExpiredForConfirmedChallengeAfterRetentionWindow
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeChallengeExpired {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeChallengeExpired)
|
||||
@@ -220,12 +229,32 @@ func TestExecuteReturnsInvalidClientPublicKey(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: "invalid",
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidClientPublicKey {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidClientPublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteReturnsInvalidRequestForInvalidTimeZone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
service := mustNewConfirmService(t, newConfirmDeps(t))
|
||||
|
||||
_, err := service.Execute(context.Background(), Input{
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: "Mars/Olympus",
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidRequest {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidRequest)
|
||||
}
|
||||
if err == nil || err.Error() != "time_zone must be a valid IANA time zone name" {
|
||||
require.Failf(t, "test failed", "Execute() error = %v, want invalid time_zone detail", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteInvalidCodeIncrementsAttempts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -239,6 +268,7 @@ func TestExecuteInvalidCodeIncrementsAttempts(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "000000",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidCode {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidCode)
|
||||
@@ -268,6 +298,7 @@ func TestExecuteFifthInvalidAttemptMarksChallengeFailed(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "000000",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidCode {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidCode)
|
||||
@@ -304,6 +335,7 @@ func TestExecuteDoesNotCreateSessionAfterTooManyAttempts(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidCode {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidCode)
|
||||
@@ -337,6 +369,7 @@ func TestExecuteReturnsSameSessionIDForIdempotentRetryAndRepublishes(t *testing.
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "Execute() returned error: %v", err)
|
||||
@@ -370,6 +403,7 @@ func TestExecuteReturnsInvalidCodeForDifferentKeyDuringIdempotentRetry(t *testin
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: alternatePublicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidCode {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidCode)
|
||||
@@ -425,6 +459,7 @@ func TestExecuteReturnsInvalidCodeForNonConfirmableStates(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeInvalidCode {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeInvalidCode)
|
||||
@@ -457,6 +492,7 @@ func TestExecuteMarksChallengeFailedAndReturnsBlockedByPolicy(t *testing.T) {
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeBlockedByPolicy {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeBlockedByPolicy)
|
||||
@@ -492,6 +528,7 @@ func TestExecuteReturnsSessionLimitExceededWithoutConsumingChallenge(t *testing.
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeSessionLimitExceeded {
|
||||
require.Failf(t, "test failed", "Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeSessionLimitExceeded)
|
||||
@@ -509,6 +546,57 @@ func TestExecuteReturnsSessionLimitExceededWithoutConsumingChallenge(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecutePassesRegistrationContextToUserDirectory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
deps := newConfirmDeps(t)
|
||||
recordingDirectory := &recordingEnsureUserDirectory{delegate: deps.userDirectory}
|
||||
deps.userDirectory = nil
|
||||
|
||||
if err := recordingDirectory.delegate.QueueCreatedUserIDs(common.UserID("user-created")); err != nil {
|
||||
require.Failf(t, "test failed", "QueueCreatedUserIDs() returned error: %v", err)
|
||||
}
|
||||
if err := deps.challengeStore.Create(context.Background(), sentChallengeFixture(t, deps.hasher, "challenge-1", "new@example.com", "654321", deps.now.Add(-time.Minute), deps.now.Add(time.Minute))); err != nil {
|
||||
require.Failf(t, "test failed", "Create() returned error: %v", err)
|
||||
}
|
||||
|
||||
service, err := New(
|
||||
deps.challengeStore,
|
||||
deps.sessionStore,
|
||||
recordingDirectory,
|
||||
deps.configProvider,
|
||||
deps.publisher,
|
||||
deps.idGenerator,
|
||||
deps.hasher,
|
||||
testkit.FixedClock{Time: deps.now},
|
||||
)
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "New() returned error: %v", err)
|
||||
}
|
||||
|
||||
_, err = service.Execute(context.Background(), Input{
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "Execute() returned error: %v", err)
|
||||
}
|
||||
if recordingDirectory.lastEnsureInput.Email != common.Email("new@example.com") {
|
||||
require.Failf(t, "test failed", "last ensure email = %q, want %q", recordingDirectory.lastEnsureInput.Email, common.Email("new@example.com"))
|
||||
}
|
||||
if recordingDirectory.lastEnsureInput.RegistrationContext == nil {
|
||||
require.FailNow(t, "last ensure registration context = nil, want value")
|
||||
}
|
||||
if recordingDirectory.lastEnsureInput.RegistrationContext.PreferredLanguage != "en" {
|
||||
require.Failf(t, "test failed", "preferred language = %q, want %q", recordingDirectory.lastEnsureInput.RegistrationContext.PreferredLanguage, "en")
|
||||
}
|
||||
if recordingDirectory.lastEnsureInput.RegistrationContext.TimeZone != confirmEmailCodeTimeZone {
|
||||
require.Failf(t, "test failed", "time zone = %q, want %q", recordingDirectory.lastEnsureInput.RegistrationContext.TimeZone, confirmEmailCodeTimeZone)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteReturnsServiceUnavailableThenSucceedsIdempotentlyAfterPublishFailure(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -526,6 +614,7 @@ func TestExecuteReturnsServiceUnavailableThenSucceedsIdempotentlyAfterPublishFai
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if shared.CodeOf(err) != shared.ErrorCodeServiceUnavailable {
|
||||
require.Failf(t, "test failed", "first Execute() error code = %q, want %q", shared.CodeOf(err), shared.ErrorCodeServiceUnavailable)
|
||||
@@ -536,6 +625,7 @@ func TestExecuteReturnsServiceUnavailableThenSucceedsIdempotentlyAfterPublishFai
|
||||
ChallengeID: "challenge-1",
|
||||
Code: "654321",
|
||||
ClientPublicKey: publicKeyString(),
|
||||
TimeZone: confirmEmailCodeTimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
require.Failf(t, "test failed", "second Execute() returned error: %v", err)
|
||||
@@ -680,3 +770,33 @@ func publicKeyString() string {
|
||||
func alternatePublicKeyString() string {
|
||||
return "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="
|
||||
}
|
||||
|
||||
// recordingEnsureUserDirectory records the last ensure input while delegating
|
||||
// behavior to the in-memory testkit directory.
|
||||
type recordingEnsureUserDirectory struct {
|
||||
delegate *testkit.InMemoryUserDirectory
|
||||
lastEnsureInput ports.EnsureUserInput
|
||||
}
|
||||
|
||||
func (d *recordingEnsureUserDirectory) ResolveByEmail(ctx context.Context, email common.Email) (userresolution.Result, error) {
|
||||
return d.delegate.ResolveByEmail(ctx, email)
|
||||
}
|
||||
|
||||
func (d *recordingEnsureUserDirectory) ExistsByUserID(ctx context.Context, userID common.UserID) (bool, error) {
|
||||
return d.delegate.ExistsByUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (d *recordingEnsureUserDirectory) EnsureUserByEmail(ctx context.Context, input ports.EnsureUserInput) (ports.EnsureUserResult, error) {
|
||||
d.lastEnsureInput = input
|
||||
return d.delegate.EnsureUserByEmail(ctx, input)
|
||||
}
|
||||
|
||||
func (d *recordingEnsureUserDirectory) BlockByUserID(ctx context.Context, input ports.BlockUserByIDInput) (ports.BlockUserResult, error) {
|
||||
return d.delegate.BlockByUserID(ctx, input)
|
||||
}
|
||||
|
||||
func (d *recordingEnsureUserDirectory) BlockByEmail(ctx context.Context, input ports.BlockUserByEmailInput) (ports.BlockUserResult, error) {
|
||||
return d.delegate.BlockByEmail(ctx, input)
|
||||
}
|
||||
|
||||
var _ ports.UserDirectory = (*recordingEnsureUserDirectory)(nil)
|
||||
|
||||
Reference in New Issue
Block a user