From caea0a888e4b2a52ed8a8a8614d7f4423b00aadc Mon Sep 17 00:00:00 2001 From: Deepjyoti Barman Date: Tue, 24 Sep 2024 12:58:25 +0530 Subject: [PATCH] Add more tests for the newly added validations --- recipe/emailpassword/api/implementation.go | 36 ++-- recipe/emailpassword/api/utils.go | 7 +- recipe/emailpassword/authFlow_test.go | 202 +++++++++++++++++++++ recipe/emailpassword/passwordReset_test.go | 92 ++++++++++ 4 files changed, 322 insertions(+), 15 deletions(-) diff --git a/recipe/emailpassword/api/implementation.go b/recipe/emailpassword/api/implementation.go index 9ab51cc6..470d3ad7 100644 --- a/recipe/emailpassword/api/implementation.go +++ b/recipe/emailpassword/api/implementation.go @@ -40,9 +40,11 @@ func MakeAPIImplementation() epmodels.APIInterface { var email string for _, formField := range formFields { if formField.ID == "email" { - valueAsString, parseErr := withValueAsString(formField.Value, "Email value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "email value needs to be a string") if parseErr != nil { - return epmodels.GeneratePasswordResetTokenPOSTResponse{}, parseErr + return epmodels.GeneratePasswordResetTokenPOSTResponse{ + GeneralError: &supertokens.GeneralErrorResponse{Message: parseErr.Error()}, + }, nil } email = valueAsString } @@ -106,9 +108,11 @@ func MakeAPIImplementation() epmodels.APIInterface { var newPassword string for _, formField := range formFields { if formField.ID == "password" { - valueAsString, parseErr := withValueAsString(formField.Value, "Password value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "password value needs to be a string") if parseErr != nil { - return epmodels.ResetPasswordPOSTResponse{}, parseErr + return epmodels.ResetPasswordPOSTResponse{ + GeneralError: &supertokens.GeneralErrorResponse{Message: parseErr.Error()}, + }, nil } newPassword = valueAsString } @@ -135,15 +139,19 @@ func MakeAPIImplementation() epmodels.APIInterface { var password string for _, formField := range formFields { if formField.ID == "email" { - valueAsString, parseErr := withValueAsString(formField.Value, "Email value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "email value needs to be a string") if parseErr != nil { - return epmodels.SignInPOSTResponse{}, parseErr + return epmodels.SignInPOSTResponse{ + WrongCredentialsError: &struct{}{}, + }, nil } email = valueAsString } else if formField.ID == "password" { - valueAsString, parseErr := withValueAsString(formField.Value, "Password value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "password value needs to be a string") if parseErr != nil { - return epmodels.SignInPOSTResponse{}, parseErr + return epmodels.SignInPOSTResponse{ + WrongCredentialsError: &struct{}{}, + }, nil } password = valueAsString } @@ -181,15 +189,19 @@ func MakeAPIImplementation() epmodels.APIInterface { var password string for _, formField := range formFields { if formField.ID == "email" { - valueAsString, parseErr := withValueAsString(formField.Value, "Email value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "email value needs to be a string") if parseErr != nil { - return epmodels.SignUpPOSTResponse{}, parseErr + return epmodels.SignUpPOSTResponse{ + GeneralError: &supertokens.GeneralErrorResponse{Message: parseErr.Error()}, + }, nil } email = valueAsString } else if formField.ID == "password" { - valueAsString, parseErr := withValueAsString(formField.Value, "Password value needs to be a string") + valueAsString, parseErr := withValueAsString(formField.Value, "password value needs to be a string") if parseErr != nil { - return epmodels.SignUpPOSTResponse{}, parseErr + return epmodels.SignUpPOSTResponse{ + GeneralError: &supertokens.GeneralErrorResponse{Message: parseErr.Error()}, + }, nil } password = valueAsString } diff --git a/recipe/emailpassword/api/utils.go b/recipe/emailpassword/api/utils.go index 577ef715..363f713f 100644 --- a/recipe/emailpassword/api/utils.go +++ b/recipe/emailpassword/api/utils.go @@ -76,13 +76,14 @@ func validateFormFieldsOrThrowError(configFormFields []epmodels.NormalisedFormFi return nil, err } - if formField.ID == "email" { - valueAsString, parseErr := withValueAsString(formField.Value, "Email value needs to be a string") + if formField.ID == "email" || formField.ID == "password" { + valueAsString, parseErr := withValueAsString(formField.Value, fmt.Sprintf("%s value must be a string", formField.ID)) if parseErr != nil { return nil, supertokens.BadInputError{ - Msg: "Email value must be a string", + Msg: parseErr.Error(), } } + formFields = append(formFields, epmodels.TypeFormField{ ID: formField.ID, Value: strings.TrimSpace(valueAsString), diff --git a/recipe/emailpassword/authFlow_test.go b/recipe/emailpassword/authFlow_test.go index 375beae0..dee3699e 100644 --- a/recipe/emailpassword/authFlow_test.go +++ b/recipe/emailpassword/authFlow_test.go @@ -38,6 +38,208 @@ import ( "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestInvalidTypeForPassword(t *testing.T) { + configValue := supertokens.TypeInput{ + Supertokens: &supertokens.ConnectionInfo{ + ConnectionURI: "http://localhost:8080", + }, + AppInfo: supertokens.AppInfo{ + APIDomain: "api.supertokens.io", + AppName: "SuperTokens", + WebsiteDomain: "supertokens.io", + }, + RecipeList: []supertokens.Recipe{ + Init(&epmodels.TypeInput{ + SignUpFeature: &epmodels.TypeInputSignUp{ + FormFields: []epmodels.TypeInputFormField{}, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + formFields := map[string][]map[string]interface{}{ + "formFields": { + { + "id": "password", + "value": 123, + }, + { + "id": "email", + "value": "random@gmail.com", + }, + }, + } + + postBody, err := json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + resp, err := http.Post(testServer.URL+"/auth/signup", "application/json", bytes.NewBuffer(postBody)) + + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, 400, resp.StatusCode) + + dataInBytes, err := io.ReadAll(resp.Body) + if err != nil { + t.Error(err.Error()) + } + resp.Body.Close() + + var data map[string]interface{} + err = json.Unmarshal(dataInBytes, &data) + if err != nil { + t.Error(err.Error()) + } + + assert.NotNil(t, data["message"].(string)) + assert.Equal(t, "password value must be a string", data["message"].(string)) + + // Test the signin flow + respSignIn, err := http.Post(testServer.URL+"/auth/signin", "application/json", bytes.NewBuffer(postBody)) + + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, 400, respSignIn.StatusCode) + + dataInBytesSignIn, err := io.ReadAll(respSignIn.Body) + if err != nil { + t.Error(err.Error()) + } + respSignIn.Body.Close() + + var dataSignIn map[string]interface{} + err = json.Unmarshal(dataInBytesSignIn, &dataSignIn) + if err != nil { + t.Error(err.Error()) + } + + assert.NotNil(t, dataSignIn["message"].(string)) + assert.Equal(t, "password value must be a string", dataSignIn["message"].(string)) +} + +func TestInvalidTypeForEmail(t *testing.T) { + configValue := supertokens.TypeInput{ + Supertokens: &supertokens.ConnectionInfo{ + ConnectionURI: "http://localhost:8080", + }, + AppInfo: supertokens.AppInfo{ + APIDomain: "api.supertokens.io", + AppName: "SuperTokens", + WebsiteDomain: "supertokens.io", + }, + RecipeList: []supertokens.Recipe{ + Init(&epmodels.TypeInput{ + SignUpFeature: &epmodels.TypeInputSignUp{ + FormFields: []epmodels.TypeInputFormField{}, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + formFields := map[string][]map[string]interface{}{ + "formFields": { + { + "id": "password", + "value": "testpw1234", + }, + { + "id": "email", + "value": 1234, + }, + }, + } + + postBody, err := json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + resp, err := http.Post(testServer.URL+"/auth/signup", "application/json", bytes.NewBuffer(postBody)) + + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, 400, resp.StatusCode) + + dataInBytes, err := io.ReadAll(resp.Body) + if err != nil { + t.Error(err.Error()) + } + resp.Body.Close() + + var data map[string]interface{} + err = json.Unmarshal(dataInBytes, &data) + if err != nil { + t.Error(err.Error()) + } + + assert.NotNil(t, data["message"].(string)) + assert.Equal(t, "email value must be a string", data["message"].(string)) + + // Test the signin flow + respSignIn, err := http.Post(testServer.URL+"/auth/signin", "application/json", bytes.NewBuffer(postBody)) + + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, 400, respSignIn.StatusCode) + + dataInBytesSignIn, err := io.ReadAll(respSignIn.Body) + if err != nil { + t.Error(err.Error()) + } + respSignIn.Body.Close() + + var dataSignIn map[string]interface{} + err = json.Unmarshal(dataInBytesSignIn, &dataSignIn) + if err != nil { + t.Error(err.Error()) + } + + assert.NotNil(t, dataSignIn["message"].(string)) + assert.Equal(t, "email value must be a string", dataSignIn["message"].(string)) +} + func TestGoodCaseInputWithOptionalAndBoolean(t *testing.T) { optionalVal := true configValue := supertokens.TypeInput{ diff --git a/recipe/emailpassword/passwordReset_test.go b/recipe/emailpassword/passwordReset_test.go index abec9ce8..d9f5334d 100644 --- a/recipe/emailpassword/passwordReset_test.go +++ b/recipe/emailpassword/passwordReset_test.go @@ -232,6 +232,98 @@ func TestPasswordValidation(t *testing.T) { assert.Equal(t, "RESET_PASSWORD_INVALID_TOKEN_ERROR", data3["status"]) } +func TestInvalidTypeForPasswordAndEmail(t *testing.T) { + configValue := supertokens.TypeInput{ + Supertokens: &supertokens.ConnectionInfo{ + ConnectionURI: "http://localhost:8080", + }, + AppInfo: supertokens.AppInfo{ + APIDomain: "api.supertokens.io", + AppName: "SuperTokens", + WebsiteDomain: "supertokens.io", + }, + RecipeList: []supertokens.Recipe{ + Init(nil), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + formFields := map[string][]map[string]interface{}{ + "formFields": { + { + "id": "password", + "value": 1234, + }, + }, + } + token := map[string]interface{}{ + "token": "RandomToken", + } + var data map[string]interface{} + + a, _ := json.Marshal(formFields) + json.Unmarshal(a, &data) + b, _ := json.Marshal(token) + json.Unmarshal(b, &data) + + jData, _ := json.Marshal(data) + + resp, err := http.Post(testServer.URL+"/auth/user/password/reset", "application/json", bytes.NewBuffer(jData)) + + if err != nil { + t.Error(err.Error()) + } + + assert.NoError(t, err) + + dataInBytes, _ := io.ReadAll(resp.Body) + resp.Body.Close() + + var data1 map[string]interface{} + json.Unmarshal(dataInBytes, &data1) + + assert.Equal(t, 400, resp.StatusCode) + assert.Equal(t, "password value must be a string", data1["message"]) + + tokenResetFormFields := map[string][]map[string]interface{}{ + "formFields": { + { + "id": "email", + "value": 123456, + }, + }, + } + + postBody, err := json.Marshal(tokenResetFormFields) + if err != nil { + t.Error(err.Error()) + } + + resetResponse, resetErr := http.Post(testServer.URL+"/auth/user/password/reset/token", "application/json", bytes.NewBuffer(postBody)) + respInBytes, _ := io.ReadAll(resetResponse.Body) + resetResponse.Body.Close() + var resetResponseData map[string]interface{} + json.Unmarshal(respInBytes, &resetResponseData) + + if resetErr != nil { + t.Error(resetErr.Error()) + } + + assert.NoError(t, resetErr) + assert.Equal(t, 400, resetResponse.StatusCode) + assert.Equal(t, "email value must be a string", resetResponseData["message"]) +} + func TestTokenMissingFromInput(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{