feat: support time_zone for user registration context
This commit is contained in:
@@ -46,6 +46,7 @@ func TestPublicHTTPEndToEndSendThenConfirm(t *testing.T) {
|
||||
"challenge_id": "challenge-1",
|
||||
"code": attempts[0].Input.Code,
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
}
|
||||
confirmResponse := postJSONValue(t, server.URL+"/api/v1/public/auth/confirm-email-code", confirmBody)
|
||||
|
||||
@@ -104,13 +105,36 @@ func TestPublicHTTPEndToEndInvalidClientPublicKey(t *testing.T) {
|
||||
response := postJSON(
|
||||
t,
|
||||
server.URL+"/api/v1/public/auth/confirm-email-code",
|
||||
`{"challenge_id":"challenge-123","code":"123456","client_public_key":"invalid"}`,
|
||||
`{"challenge_id":"challenge-123","code":"123456","client_public_key":"invalid","time_zone":"`+publicConfirmTimeZone+`"}`,
|
||||
)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, response.StatusCode)
|
||||
assert.JSONEq(t, `{"error":{"code":"invalid_client_public_key","message":"client_public_key is not a valid base64-encoded raw 32-byte Ed25519 public key"}}`, response.Body)
|
||||
}
|
||||
|
||||
func TestPublicHTTPEndToEndInvalidTimeZone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := newEndToEndApp(t, endToEndOptions{
|
||||
SeedChallenge: seedChallengeOptions{
|
||||
ID: "challenge-123",
|
||||
Code: "123456",
|
||||
Status: challenge.StatusSent,
|
||||
},
|
||||
})
|
||||
server := httptest.NewServer(app.handler)
|
||||
defer server.Close()
|
||||
|
||||
response := postJSON(
|
||||
t,
|
||||
server.URL+"/api/v1/public/auth/confirm-email-code",
|
||||
`{"challenge_id":"challenge-123","code":"123456","client_public_key":"`+validClientPublicKey+`","time_zone":"Mars/Olympus"}`,
|
||||
)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, response.StatusCode)
|
||||
assert.JSONEq(t, `{"error":{"code":"invalid_request","message":"time_zone must be a valid IANA time zone name"}}`, response.Body)
|
||||
}
|
||||
|
||||
func TestPublicHTTPEndToEndChallengeNotFound(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -122,6 +146,7 @@ func TestPublicHTTPEndToEndChallengeNotFound(t *testing.T) {
|
||||
"challenge_id": "missing",
|
||||
"code": "123456",
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusNotFound, response.StatusCode)
|
||||
@@ -146,6 +171,7 @@ func TestPublicHTTPEndToEndChallengeExpired(t *testing.T) {
|
||||
"challenge_id": "challenge-123",
|
||||
"code": "123456",
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusGone, response.StatusCode)
|
||||
@@ -169,6 +195,7 @@ func TestPublicHTTPEndToEndInvalidCode(t *testing.T) {
|
||||
"challenge_id": "challenge-123",
|
||||
"code": "654321",
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, response.StatusCode)
|
||||
@@ -192,6 +219,7 @@ func TestPublicHTTPEndToEndThrottledChallengeConfirmReturnsInvalidCode(t *testin
|
||||
"challenge_id": "challenge-123",
|
||||
"code": "123456",
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, response.StatusCode)
|
||||
@@ -226,6 +254,7 @@ func TestPublicHTTPEndToEndSessionLimitExceeded(t *testing.T) {
|
||||
"challenge_id": "challenge-1",
|
||||
"code": attempts[0].Input.Code,
|
||||
"client_public_key": validClientPublicKey,
|
||||
"time_zone": publicConfirmTimeZone,
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusConflict, confirmResponse.StatusCode)
|
||||
|
||||
@@ -35,6 +35,7 @@ type confirmEmailCodeRequest struct {
|
||||
ChallengeID string `json:"challenge_id"`
|
||||
Code string `json:"code"`
|
||||
ClientPublicKey string `json:"client_public_key"`
|
||||
TimeZone string `json:"time_zone"`
|
||||
}
|
||||
|
||||
type confirmEmailCodeResponse struct {
|
||||
@@ -142,6 +143,7 @@ func handleConfirmEmailCode(useCase ConfirmEmailCodeUseCase, timeout time.Durati
|
||||
ChallengeID: request.ChallengeID,
|
||||
Code: request.Code,
|
||||
ClientPublicKey: request.ClientPublicKey,
|
||||
TimeZone: request.TimeZone,
|
||||
})
|
||||
if err != nil {
|
||||
abortWithProjection(c, projectConfirmEmailCodeError(err))
|
||||
@@ -195,6 +197,11 @@ func validateConfirmEmailCodeRequest(request *confirmEmailCodeRequest) error {
|
||||
return errors.New("client_public_key must not be empty")
|
||||
}
|
||||
|
||||
request.TimeZone = strings.TrimSpace(request.TimeZone)
|
||||
if request.TimeZone == "" {
|
||||
return errors.New("time_zone must not be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ import (
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
const publicConfirmTimeZone = "Europe/Kaliningrad"
|
||||
|
||||
func TestSendEmailCodeHandlerSuccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -58,6 +60,7 @@ func TestConfirmEmailCodeHandlerSuccess(t *testing.T) {
|
||||
ChallengeID: "challenge-123",
|
||||
Code: "123456",
|
||||
ClientPublicKey: "public-key-material",
|
||||
TimeZone: publicConfirmTimeZone,
|
||||
}, input)
|
||||
return confirmemailcode.Result{DeviceSessionID: "device-session-123"}, nil
|
||||
}),
|
||||
@@ -67,7 +70,7 @@ func TestConfirmEmailCodeHandlerSuccess(t *testing.T) {
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"/api/v1/public/auth/confirm-email-code",
|
||||
bytes.NewBufferString(`{"challenge_id":" challenge-123 ","code":" 123456 ","client_public_key":" public-key-material "}`),
|
||||
bytes.NewBufferString(`{"challenge_id":" challenge-123 ","code":" 123456 ","client_public_key":" public-key-material ","time_zone":" `+publicConfirmTimeZone+` "}`),
|
||||
)
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
@@ -133,10 +136,17 @@ func TestPublicAuthHandlersRejectInvalidRequests(t *testing.T) {
|
||||
{
|
||||
name: "empty code",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":" ","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":" ","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: `{"error":{"code":"invalid_request","message":"code must not be empty"}}`,
|
||||
},
|
||||
{
|
||||
name: "empty time zone",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":" "}`,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: `{"error":{"code":"invalid_request","message":"time_zone must not be empty"}}`,
|
||||
},
|
||||
}
|
||||
|
||||
handler := mustNewHandler(t, DefaultConfig(), Dependencies{
|
||||
@@ -198,7 +208,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm invalid client public key",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -213,7 +223,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm challenge not found",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -228,7 +238,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm challenge expired",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -243,7 +253,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm blocked by policy",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -258,7 +268,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm session limit exceeded",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -273,7 +283,7 @@ func TestPublicAuthHandlersMapServiceErrors(t *testing.T) {
|
||||
{
|
||||
name: "confirm hides internal error",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -363,7 +373,7 @@ func TestPublicAuthHandlersRejectInvalidSuccessPayloads(t *testing.T) {
|
||||
{
|
||||
name: "confirm blank device session id",
|
||||
target: "/api/v1/public/auth/confirm-email-code",
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`,
|
||||
body: `{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"` + publicConfirmTimeZone + `"}`,
|
||||
deps: Dependencies{
|
||||
SendEmailCode: sendEmailCodeFunc(func(context.Context, sendemailcode.Input) (sendemailcode.Result, error) {
|
||||
return sendemailcode.Result{}, errors.New("unexpected call")
|
||||
@@ -413,7 +423,7 @@ func TestPublicAuthLogsDoNotContainSensitiveFields(t *testing.T) {
|
||||
request := httptest.NewRequest(
|
||||
http.MethodPost,
|
||||
"/api/v1/public/auth/confirm-email-code",
|
||||
bytes.NewBufferString(`{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material"}`),
|
||||
bytes.NewBufferString(`{"challenge_id":"challenge-123","code":"123456","client_public_key":"public-key-material","time_zone":"`+publicConfirmTimeZone+`"}`),
|
||||
)
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user