From 8f65e8e0c7fd0f566df61114dbb7b8158c4e1ff8 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Tue, 9 Apr 2024 11:10:20 +0530 Subject: [PATCH 01/19] removes a bunch of unnecessary tests --- .../emailExistsAndVerificationCheck_test.go | 189 ++++++++----- .../loginmethods_test.go | 2 +- .../authorisationUrlFeature_test.go | 164 ------------ recipe/thirdpartyemailpassword/config_test.go | 142 ---------- .../emailExist_test.go | 222 ---------------- .../emailVerify_test.go | 250 ------------------ 6 files changed, 122 insertions(+), 847 deletions(-) rename recipe/{thirdpartyemailpassword => emailpassword}/loginmethods_test.go (97%) delete mode 100644 recipe/thirdpartyemailpassword/authorisationUrlFeature_test.go delete mode 100644 recipe/thirdpartyemailpassword/config_test.go delete mode 100644 recipe/thirdpartyemailpassword/emailExist_test.go delete mode 100644 recipe/thirdpartyemailpassword/emailVerify_test.go diff --git a/recipe/emailpassword/emailExistsAndVerificationCheck_test.go b/recipe/emailpassword/emailExistsAndVerificationCheck_test.go index aa206463..346f29e1 100644 --- a/recipe/emailpassword/emailExistsAndVerificationCheck_test.go +++ b/recipe/emailpassword/emailExistsAndVerificationCheck_test.go @@ -430,76 +430,66 @@ func TestEmailDoesExistsWithBadInput(t *testing.T) { res, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, 400, res.StatusCode) + result := *unittesting.HttpResponseToConsumableInformation(res.Body) + assert.Equal(t, "Please provide the email as a GET param", result["message"]) } -//email_verify tests -// func TestGenerateTokenAPIWithValidInputAndEmailNotVerified(t *testing.T) { -// customAntiCsrfVal := "VIA_TOKEN" -// 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), -// session.Init(&sessmodels.TypeInput{ -// AntiCsrf: &customAntiCsrfVal, -// }), -// }, -// } - -// 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() - -// resp, err := unittesting.SignupRequest("test@gmail.com", "testPass123", testServer.URL) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.NoError(t, err) -// assert.Equal(t, 200, resp.StatusCode) -// data, _ := io.ReadAll(resp.Body) -// resp.Body.Close() -// var response map[string]interface{} -// _ = json.Unmarshal(data, &response) -// assert.Equal(t, "OK", response["status"]) - -// userId := response["user"].(map[string]interface{})["id"] -// cookieData := unittesting.ExtractInfoFromResponse(resp) - -// verifyToken, err := CreateEmailVerificationToken(userId.(string)) -// if err != nil { -// t.Error(err.Error()) -// } -// VerifyEmailUsingToken(verifyToken.OK.Token) - -// resp1, err := unittesting.EmailVerifyTokenRequest(testServer.URL, userId.(string), cookieData["sAccessToken"], cookieData["antiCsrf"]) - -// if err != nil { -// t.Error(err.Error()) -// } - -// assert.NoError(t, err) -// assert.Equal(t, 200, resp1.StatusCode) -// data1, _ := io.ReadAll(resp1.Body) -// resp1.Body.Close() -// var response1 map[string]interface{} -// _ = json.Unmarshal(data1, &response1) - -// assert.Equal(t, "EMAIL_ALREADY_VERIFIED_ERROR", response1["status"]) - -// } +func TestGenerateTokenAPIWithValidInputAndEmailNotVerified(t *testing.T) { + customCSRFval := "VIA_TOKEN" + 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{ + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + }), + Init(nil), + session.Init(&sessmodels.TypeInput{ + AntiCsrf: &customCSRFval, + 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() + + resp, err := unittesting.SignupRequest("random@gmail.com", "validPass123", testServer.URL) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + cookieData := unittesting.ExtractInfoFromResponse(resp) + + result := *unittesting.HttpResponseToConsumableInformation(resp.Body) + assert.Equal(t, "OK", result["status"]) + user := result["user"].(map[string]interface{}) + + rep1, err := unittesting.EmailVerifyTokenRequest(testServer.URL, user["id"].(string), cookieData["sAccessToken"], cookieData["antiCsrf"]) + if err != nil { + t.Error(err.Error()) + } + result1 := *unittesting.HttpResponseToConsumableInformation(rep1.Body) + assert.Equal(t, "OK", result1["status"]) +} func TestGenerateTokenAPIWithValidInputNoSessionAndCheckOutput(t *testing.T) { customAntiCsrfVal := "VIA_TOKEN" @@ -558,6 +548,69 @@ func TestGenerateTokenAPIWithValidInputNoSessionAndCheckOutput(t *testing.T) { assert.Equal(t, "unauthorised", response["message"]) } +func TestGenerateTokenAPIwithValidInputEmailVerifiedAndTestError(t *testing.T) { + customCSRFval := "VIA_TOKEN" + 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{ + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + }), + Init(nil), + session.Init(&sessmodels.TypeInput{ + AntiCsrf: &customCSRFval, + 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() + + resp, err := unittesting.SignupRequest("random@gmail.com", "validPass123", testServer.URL) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + cookieData := unittesting.ExtractInfoFromResponse(resp) + + result := *unittesting.HttpResponseToConsumableInformation(resp.Body) + assert.Equal(t, "OK", result["status"]) + user := result["user"].(map[string]interface{}) + + verifyToken, err := emailverification.CreateEmailVerificationToken("public", user["id"].(string), nil) + if err != nil { + t.Error(err.Error()) + } + emailverification.VerifyEmailUsingToken("public", verifyToken.OK.Token) + + rep1, err := unittesting.EmailVerifyTokenRequest(testServer.URL, user["id"].(string), cookieData["sAccessToken"], cookieData["antiCsrf"]) + if err != nil { + t.Error(err.Error()) + } + result1 := *unittesting.HttpResponseToConsumableInformation(rep1.Body) + assert.Equal(t, "EMAIL_ALREADY_VERIFIED_ERROR", result1["status"]) +} + func TestGenerateTokenAPIWithExpiredAccessToken(t *testing.T) { customAntiCsrfVal := "VIA_TOKEN" configValue := supertokens.TypeInput{ diff --git a/recipe/thirdpartyemailpassword/loginmethods_test.go b/recipe/emailpassword/loginmethods_test.go similarity index 97% rename from recipe/thirdpartyemailpassword/loginmethods_test.go rename to recipe/emailpassword/loginmethods_test.go index ba09d6b6..846e5021 100644 --- a/recipe/thirdpartyemailpassword/loginmethods_test.go +++ b/recipe/emailpassword/loginmethods_test.go @@ -1,4 +1,4 @@ -package thirdpartyemailpassword +package emailpassword import ( "encoding/json" diff --git a/recipe/thirdpartyemailpassword/authorisationUrlFeature_test.go b/recipe/thirdpartyemailpassword/authorisationUrlFeature_test.go deleted file mode 100644 index 84487fd0..00000000 --- a/recipe/thirdpartyemailpassword/authorisationUrlFeature_test.go +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestMinimumConfigForThirdPartyModule(t *testing.T) { - customAntiCsrfVal := "VIA_TOKEN" - 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( - &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProvider1, - }, - }, - ), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfVal, - 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() - - resp, err := http.Get(testServer.URL + "/auth/authorisationurl?thirdPartyId=custom") - if err != nil { - t.Error(err.Error()) - } - - 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.Equal(t, "OK", data["status"]) - - fetchedUrl, err := url.Parse(data["urlWithQueryParams"].(string)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, "test.com", fetchedUrl.Host) - assert.Equal(t, "/oauth/auth", fetchedUrl.Path) -} - -func TestThirdPartyProviderDoesnotExsit(t *testing.T) { - customAntiCsrfVal := "VIA_TOKEN" - 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( - &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProvider1, - }, - }, - ), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfVal, - 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() - - resp, err := http.Get(testServer.URL + "/auth/authorisationurl?thirdPartyId=google") - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusBadRequest, 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.Equal(t, "the provider google could not be found in the configuration", data["message"].(string)) -} diff --git a/recipe/thirdpartyemailpassword/config_test.go b/recipe/thirdpartyemailpassword/config_test.go deleted file mode 100644 index 43d5e844..00000000 --- a/recipe/thirdpartyemailpassword/config_test.go +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestDefaultConfigForThirdPartyEmailPasswordRecipe(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( - &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{}, - }, - ), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - - if err != nil { - t.Error(err.Error()) - } - - thirdpartyemailpassword, err := GetRecipeInstanceOrThrowError() - if err != nil { - t.Error(err.Error()) - } - - assert.NotNil(t, thirdpartyemailpassword.thirdPartyRecipe) // thirdPartyRecipe must be created always - - emailpassword := thirdpartyemailpassword.emailPasswordRecipe - signUpFeature := emailpassword.Config.SignUpFeature - assert.Equal(t, 2, len(signUpFeature.FormFields)) - for _, formField := range signUpFeature.FormFields { - assert.False(t, formField.Optional) - assert.NotNil(t, formField.Validate) - } - - signInFeature := emailpassword.Config.SignInFeature - assert.Equal(t, 2, len(signInFeature.FormFields)) - for _, formField := range signInFeature.FormFields { - assert.False(t, formField.Optional) - assert.NotNil(t, formField.Validate) - } - - resetPasswordUsingTokenFeature := emailpassword.Config.ResetPasswordUsingTokenFeature - assert.Equal(t, 1, len(resetPasswordUsingTokenFeature.FormFieldsForGenerateTokenForm)) - assert.Equal(t, "email", resetPasswordUsingTokenFeature.FormFieldsForGenerateTokenForm[0].ID) - assert.Equal(t, 1, len(resetPasswordUsingTokenFeature.FormFieldsForPasswordResetForm)) - assert.Equal(t, "password", resetPasswordUsingTokenFeature.FormFieldsForPasswordResetForm[0].ID) -} - -func TestDefaultConfigForThirdPartyEmailPasswordRecipeWithProvider(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( - &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProvider2, - }, - }, - ), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - - if err != nil { - t.Error(err.Error()) - } - - thirdpartyemailpassword, err := GetRecipeInstanceOrThrowError() - if err != nil { - t.Error(err.Error()) - } - - assert.NotNil(t, thirdpartyemailpassword.thirdPartyRecipe) - - emailpassword := thirdpartyemailpassword.emailPasswordRecipe - signUpFeature := emailpassword.Config.SignUpFeature - assert.Equal(t, 2, len(signUpFeature.FormFields)) - for _, formField := range signUpFeature.FormFields { - assert.False(t, formField.Optional) - assert.NotNil(t, formField.Validate) - } - - signInFeature := emailpassword.Config.SignInFeature - assert.Equal(t, 2, len(signInFeature.FormFields)) - for _, formField := range signInFeature.FormFields { - assert.False(t, formField.Optional) - assert.NotNil(t, formField.Validate) - } - - resetPasswordUsingTokenFeature := emailpassword.Config.ResetPasswordUsingTokenFeature - assert.Equal(t, 1, len(resetPasswordUsingTokenFeature.FormFieldsForGenerateTokenForm)) - assert.Equal(t, "email", resetPasswordUsingTokenFeature.FormFieldsForGenerateTokenForm[0].ID) - assert.Equal(t, 1, len(resetPasswordUsingTokenFeature.FormFieldsForPasswordResetForm)) - assert.Equal(t, "password", resetPasswordUsingTokenFeature.FormFieldsForPasswordResetForm[0].ID) -} diff --git a/recipe/thirdpartyemailpassword/emailExist_test.go b/recipe/thirdpartyemailpassword/emailExist_test.go deleted file mode 100644 index 2e42a3ef..00000000 --- a/recipe/thirdpartyemailpassword/emailExist_test.go +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestIfDisableAPIdefaultEmailExistDoesNotWork(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(&tpepmodels.TypeInput{ - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.EmailPasswordEmailExistsGET = nil - return originalImplementation - }, - }, - }), - }, - } - - 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() - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - q := req.URL.Query() - q.Add("email", "random@gmail.com") - req.URL.RawQuery = q.Encode() - assert.NoError(t, err) - res, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - assert.Equal(t, http.StatusNotFound, res.StatusCode) -} - -func TestGoodInputEmailExist(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), - 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() - - resp, err := unittesting.SignupRequest("random@gmail.com", "validPass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - q := req.URL.Query() - q.Add("email", "random@gmail.com") - req.URL.RawQuery = q.Encode() - if err != nil { - t.Error(err.Error()) - } - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - result1 := *unittesting.HttpResponseToConsumableInformation(res.Body) - assert.Equal(t, http.StatusOK, res.StatusCode) - assert.Equal(t, "OK", result1["status"]) - assert.Equal(t, true, result1["exists"]) -} - -func TestGoodInputEmailDoesNotExist(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), - 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() - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - q := req.URL.Query() - q.Add("email", "random@gmail.com") - req.URL.RawQuery = q.Encode() - if err != nil { - t.Error(err.Error()) - } - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - result := *unittesting.HttpResponseToConsumableInformation(res.Body) - assert.Equal(t, http.StatusOK, res.StatusCode) - assert.Equal(t, "OK", result["status"]) - assert.Equal(t, false, result["exists"]) -} - -func TestBadInputDoNotPassEmail(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), - 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() - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - if err != nil { - t.Error(err.Error()) - } - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - result := *unittesting.HttpResponseToConsumableInformation(res.Body) - assert.Equal(t, http.StatusBadRequest, res.StatusCode) - assert.Equal(t, "Please provide the email as a GET param", result["message"]) -} diff --git a/recipe/thirdpartyemailpassword/emailVerify_test.go b/recipe/thirdpartyemailpassword/emailVerify_test.go deleted file mode 100644 index d2c5cc7d..00000000 --- a/recipe/thirdpartyemailpassword/emailVerify_test.go +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestTheGenerateTokenAPIwithValidInputEmailNotVerified(t *testing.T) { - customCSRFval := "VIA_TOKEN" - 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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - Init(nil), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customCSRFval, - 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() - - resp, err := unittesting.SignupRequest("random@gmail.com", "validPass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - user := result["user"].(map[string]interface{}) - - rep1, err := unittesting.EmailVerifyTokenRequest(testServer.URL, user["id"].(string), cookieData["sAccessToken"], cookieData["antiCsrf"]) - if err != nil { - t.Error(err.Error()) - } - result1 := *unittesting.HttpResponseToConsumableInformation(rep1.Body) - assert.Equal(t, "OK", result1["status"]) -} - -func TestGenerateTokenAPIwithValidInputEmailVerifiedAndTestError(t *testing.T) { - customCSRFval := "VIA_TOKEN" - 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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - Init(nil), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customCSRFval, - 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() - - resp, err := unittesting.SignupRequest("random@gmail.com", "validPass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - user := result["user"].(map[string]interface{}) - - verifyToken, err := emailverification.CreateEmailVerificationToken("public", user["id"].(string), nil) - if err != nil { - t.Error(err.Error()) - } - emailverification.VerifyEmailUsingToken("public", verifyToken.OK.Token) - - rep1, err := unittesting.EmailVerifyTokenRequest(testServer.URL, user["id"].(string), cookieData["sAccessToken"], cookieData["antiCsrf"]) - if err != nil { - t.Error(err.Error()) - } - result1 := *unittesting.HttpResponseToConsumableInformation(rep1.Body) - assert.Equal(t, "EMAIL_ALREADY_VERIFIED_ERROR", result1["status"]) -} - -func TestGenerateTokenAPIWithValidInputNoSessionAndCheckOutput(t *testing.T) { - customCSRFval := "VIA_TOKEN" - 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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - Init(nil), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customCSRFval, - 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() - - resp, err := http.Post(testServer.URL+"/auth/user/email/verify/token", "application/json", nil) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "unauthorised", result["message"]) -} - -func TestEmailVerifyAPIwithInvalidTokenCheckError(t *testing.T) { - customCSRFval := "VIA_TOKEN" - 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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - Init(nil), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customCSRFval, - 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]string{ - "method": "token", - "token": "randomToken", - } - - postBody, err := json.Marshal(formFields) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/user/email/verify", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR", result["status"]) -} From edcc793a338a36ee68e1dbe0f5ba9e04018e362b Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Tue, 9 Apr 2024 14:40:00 +0530 Subject: [PATCH 02/19] moves tests around and removes tpep folder --- frontendDriverInterfaceSupported.json | 3 +- .../api/userdetails/userPasswordPut.go | 59 +- recipe/dashboard/api/userdetails/userPut.go | 41 - recipe/dashboard/api/utils.go | 49 - recipe/dashboard/testingUtils.go | 2 - recipe/dashboard/userGet_test.go | 19 +- recipe/dashboard/userPasswordPut_test.go | 10 +- recipe/dashboard/userPut_test.go | 10 +- recipe/emailpassword/authFlow_test.go | 54 + .../signinFeature_test.go} | 179 +--- .../signoutFeature_test.go | 10 +- .../userIdMapping_create_test.go | 75 ++ recipe/thirdparty/email_test.go | 181 ++++ recipe/thirdparty/signinupFeature_test.go | 103 ++ recipe/thirdparty/testingUtils.go | 2 +- .../api/emailPasswordAPIImplementation.go | 103 -- .../api/implementation.go | 185 ---- .../api/thirdPartyAPIImplementation.go | 78 -- .../backwardCompatibilityService/main.go | 46 - .../emaildelivery/smtpService/main.go | 42 - recipe/thirdpartyemailpassword/main.go | 240 ----- recipe/thirdpartyemailpassword/recipe.go | 220 ---- .../emailPasswordRecipeImplementation.go | 122 --- .../recipeimplementation/main.go | 328 ------ .../thirdPartyRecipeImplementation.go | 149 --- .../signinFeature_test.go | 458 --------- .../thirdpartyemailpassword/testingUtils.go | 160 --- .../tpep_email_test.go | 968 ------------------ .../tpep_userIdMapping_test.go | 166 --- .../tpepmodels/apiInterface.go | 80 -- .../tpepmodels/models.go | 62 -- .../tpepmodels/recipeInterface.go | 68 -- recipe/thirdpartyemailpassword/utils.go | 79 -- test/auth-react-server/main.go | 259 +++-- 34 files changed, 610 insertions(+), 4000 deletions(-) rename recipe/{thirdpartyemailpassword/signupFeature_test.go => emailpassword/signinFeature_test.go} (50%) rename recipe/{thirdpartyemailpassword => emailpassword}/signoutFeature_test.go (94%) create mode 100644 recipe/thirdparty/email_test.go delete mode 100644 recipe/thirdpartyemailpassword/api/emailPasswordAPIImplementation.go delete mode 100644 recipe/thirdpartyemailpassword/api/implementation.go delete mode 100644 recipe/thirdpartyemailpassword/api/thirdPartyAPIImplementation.go delete mode 100644 recipe/thirdpartyemailpassword/emaildelivery/backwardCompatibilityService/main.go delete mode 100644 recipe/thirdpartyemailpassword/emaildelivery/smtpService/main.go delete mode 100644 recipe/thirdpartyemailpassword/main.go delete mode 100644 recipe/thirdpartyemailpassword/recipe.go delete mode 100644 recipe/thirdpartyemailpassword/recipeimplementation/emailPasswordRecipeImplementation.go delete mode 100644 recipe/thirdpartyemailpassword/recipeimplementation/main.go delete mode 100644 recipe/thirdpartyemailpassword/recipeimplementation/thirdPartyRecipeImplementation.go delete mode 100644 recipe/thirdpartyemailpassword/signinFeature_test.go delete mode 100644 recipe/thirdpartyemailpassword/testingUtils.go delete mode 100644 recipe/thirdpartyemailpassword/tpep_email_test.go delete mode 100644 recipe/thirdpartyemailpassword/tpep_userIdMapping_test.go delete mode 100644 recipe/thirdpartyemailpassword/tpepmodels/apiInterface.go delete mode 100644 recipe/thirdpartyemailpassword/tpepmodels/models.go delete mode 100644 recipe/thirdpartyemailpassword/tpepmodels/recipeInterface.go delete mode 100644 recipe/thirdpartyemailpassword/utils.go diff --git a/frontendDriverInterfaceSupported.json b/frontendDriverInterfaceSupported.json index 0d1267d8..8ca4e370 100644 --- a/frontendDriverInterfaceSupported.json +++ b/frontendDriverInterfaceSupported.json @@ -1,6 +1,7 @@ { "_comment": "contains a list of frontend-driver interfaces branch names that this core supports", "versions": [ - "1.17" + "1.17", + "2.0" ] } \ No newline at end of file diff --git a/recipe/dashboard/api/userdetails/userPasswordPut.go b/recipe/dashboard/api/userdetails/userPasswordPut.go index 672e195b..bff11fdf 100644 --- a/recipe/dashboard/api/userdetails/userPasswordPut.go +++ b/recipe/dashboard/api/userdetails/userPasswordPut.go @@ -22,7 +22,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -69,66 +68,14 @@ func UserPasswordPut(apiInterface dashboardmodels.APIInterface, tenantId string, recipeToUse = "emailpassword" } - if recipeToUse == "none" { - tpepInstance := thirdpartyemailpassword.GetRecipeInstance() - - if tpepInstance != nil { - recipeToUse = "thirdpartyemailpassword" - } - } - if recipeToUse == "none" { // This means that neither emailpassword or thirdpartyemailpassword is initialised return userPasswordPutResponse{}, errors.New("Should never come here") } - if recipeToUse == "emailpassword" { - var passwordField epmodels.NormalisedFormField - - for _, value := range emailPasswordInstance.Config.SignUpFeature.FormFields { - if value.ID == "password" { - passwordField = value - } - } - - validationError := passwordField.Validate(*readBody.NewPassword, tenantId) - - if validationError != nil { - return userPasswordPutResponse{ - Status: "INVALID_PASSWORD_ERROR", - Error: *validationError, - }, nil - } - - passwordResetToken, resetTokenErr := emailpassword.CreateResetPasswordToken(tenantId, *readBody.UserId, userContext) - - if resetTokenErr != nil { - return userPasswordPutResponse{}, resetTokenErr - } - - if passwordResetToken.UnknownUserIdError != nil { - // Techincally it can but its an edge case so we assume that it wont - return userPasswordPutResponse{}, errors.New("Should never come here") - } - - passwordResetResponse, passwordResetErr := emailpassword.ResetPasswordUsingToken(tenantId, passwordResetToken.OK.Token, *readBody.NewPassword, userContext) - - if passwordResetErr != nil { - return userPasswordPutResponse{}, passwordResetErr - } - - if passwordResetResponse.ResetPasswordInvalidTokenError != nil { - return userPasswordPutResponse{}, errors.New("Should never come here") - } - - return userPasswordPutResponse{ - Status: "OK", - }, nil - } - var passwordField epmodels.NormalisedFormField - for _, value := range thirdpartyemailpassword.GetRecipeInstance().GetEmailPasswordRecipe().Config.SignUpFeature.FormFields { + for _, value := range emailPasswordInstance.Config.SignUpFeature.FormFields { if value.ID == "password" { passwordField = value } @@ -143,7 +90,7 @@ func UserPasswordPut(apiInterface dashboardmodels.APIInterface, tenantId string, }, nil } - passwordResetToken, resetTokenErr := thirdpartyemailpassword.CreateResetPasswordToken(tenantId, *readBody.UserId, userContext) + passwordResetToken, resetTokenErr := emailpassword.CreateResetPasswordToken(tenantId, *readBody.UserId, userContext) if resetTokenErr != nil { return userPasswordPutResponse{}, resetTokenErr @@ -154,7 +101,7 @@ func UserPasswordPut(apiInterface dashboardmodels.APIInterface, tenantId string, return userPasswordPutResponse{}, errors.New("Should never come here") } - passwordResetResponse, passwordResetErr := thirdpartyemailpassword.ResetPasswordUsingToken(tenantId, passwordResetToken.OK.Token, *readBody.NewPassword, userContext) + passwordResetResponse, passwordResetErr := emailpassword.ResetPasswordUsingToken(tenantId, passwordResetToken.OK.Token, *readBody.NewPassword, userContext) if passwordResetErr != nil { return userPasswordPutResponse{}, passwordResetErr diff --git a/recipe/dashboard/api/userdetails/userPut.go b/recipe/dashboard/api/userdetails/userPut.go index c778f05d..4320f06c 100644 --- a/recipe/dashboard/api/userdetails/userPut.go +++ b/recipe/dashboard/api/userdetails/userPut.go @@ -25,7 +25,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/recipe/usermetadata" "github.com/supertokens/supertokens-golang/supertokens" @@ -95,46 +94,6 @@ func updateEmailForRecipeId(recipeId string, userId string, email string, tenant }, nil } - if recipeId == "thirdpartyemailpassword" { - var emailField epmodels.NormalisedFormField - - for _, value := range thirdpartyemailpassword.GetRecipeInstance().GetEmailPasswordRecipe().Config.SignUpFeature.FormFields { - if value.ID == "email" { - emailField = value - } - } - - validationError := emailField.Validate(email, tenantId) - - if validationError != nil { - return updateEmailResponse{ - Status: "INVALID_EMAIL_ERROR", - Error: *validationError, - }, nil - } - - tenantId := "public" - updateResponse, err := thirdpartyemailpassword.UpdateEmailOrPassword(userId, &email, nil, nil, &tenantId, userContext) - - if err != nil { - return updateEmailResponse{}, err - } - - if updateResponse.EmailAlreadyExistsError != nil { - return updateEmailResponse{ - Status: "EMAIL_ALREADY_EXISTS_ERROR", - }, nil - } - - if updateResponse.UnknownUserIdError != nil { - return updateEmailResponse{}, errors.New("Should never come here") - } - - return updateEmailResponse{ - Status: "OK", - }, nil - } - if recipeId == "passwordless" { isValidEmail := true validationError := "" diff --git a/recipe/dashboard/api/utils.go b/recipe/dashboard/api/utils.go index 5134d1f3..7179f08c 100644 --- a/recipe/dashboard/api/utils.go +++ b/recipe/dashboard/api/utils.go @@ -7,7 +7,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/passwordless" "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -45,21 +44,6 @@ func GetUserForRecipeId(userId string, recipeId string, userContext supertokens. recipeToReturn = emailpassword.RECIPE_ID } - - if reflect.DeepEqual(userToReturn, dashboardmodels.UserType{}) { - tpepResponse, tpepError := thirdpartyemailpassword.GetUserById(userId, userContext) - - if tpepError == nil && tpepResponse != nil { - userToReturn.Id = tpepResponse.ID - userToReturn.TimeJoined = tpepResponse.TimeJoined - userToReturn.FirstName = "" - userToReturn.LastName = "" - userToReturn.Email = tpepResponse.Email - userToReturn.TenantIds = tpepResponse.TenantIds - - recipeToReturn = thirdpartyemailpassword.RECIPE_ID - } - } } else if recipeId == thirdparty.RECIPE_ID { response, error := thirdparty.GetUserByID(userId, userContext) @@ -76,23 +60,6 @@ func GetUserForRecipeId(userId string, recipeId string, userContext supertokens. userToReturn.TenantIds = response.TenantIds } - if reflect.DeepEqual(userToReturn, dashboardmodels.UserType{}) { - tpepResponse, tpepError := thirdpartyemailpassword.GetUserById(userId, userContext) - - if tpepError == nil && tpepResponse != nil { - userToReturn.Id = tpepResponse.ID - userToReturn.TimeJoined = tpepResponse.TimeJoined - userToReturn.FirstName = "" - userToReturn.LastName = "" - userToReturn.Email = tpepResponse.Email - userToReturn.ThirdParty = &dashboardmodels.ThirdParty{ - Id: tpepResponse.ThirdParty.ID, - UserId: tpepResponse.ThirdParty.UserID, - } - userToReturn.TenantIds = tpepResponse.TenantIds - } - } - if reflect.DeepEqual(userToReturn, dashboardmodels.UserType{}) { tpplessResponse, tpplessError := thirdpartypasswordless.GetUserById(userId, userContext) @@ -171,14 +138,6 @@ func IsRecipeInitialised(recipeId string) bool { if err == nil { isRecipeInitialised = true } - - if !isRecipeInitialised { - _, err := thirdpartyemailpassword.GetRecipeInstanceOrThrowError() - - if err == nil { - isRecipeInitialised = true - } - } } else if recipeId == passwordless.RECIPE_ID { _, err := passwordless.GetRecipeInstanceOrThrowError() @@ -200,14 +159,6 @@ func IsRecipeInitialised(recipeId string) bool { isRecipeInitialised = true } - if !isRecipeInitialised { - _, err := thirdpartyemailpassword.GetRecipeInstanceOrThrowError() - - if err == nil { - isRecipeInitialised = true - } - } - if !isRecipeInitialised { _, err := thirdpartypasswordless.GetRecipeInstanceOrThrowError() diff --git a/recipe/dashboard/testingUtils.go b/recipe/dashboard/testingUtils.go index 0763f1f9..43e80591 100644 --- a/recipe/dashboard/testingUtils.go +++ b/recipe/dashboard/testingUtils.go @@ -20,7 +20,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/multitenancy" "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" @@ -30,7 +29,6 @@ func resetAll() { supertokens.ResetForTest() ResetForTest() session.ResetForTest() - thirdpartyemailpassword.ResetForTest() multitenancy.ResetForTest() } diff --git a/recipe/dashboard/userGet_test.go b/recipe/dashboard/userGet_test.go index 8bdd34a2..7f6b8b5c 100644 --- a/recipe/dashboard/userGet_test.go +++ b/recipe/dashboard/userGet_test.go @@ -2,29 +2,28 @@ package dashboard import ( "encoding/json" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + "github.com/supertokens/supertokens-golang/recipe/dashboard/api" "github.com/supertokens/supertokens-golang/recipe/dashboard/api/userdetails" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) /* -- Initialise with thirdpartyemailpassword and provide no custom form fields -- Create an emailpassword user using the thirdpartyemailpassword recipe - Get user from the user get API - Check that user has public tenant */ @@ -42,7 +41,7 @@ func TestThatUserGetReturnsTenantIDsCorrectly(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - thirdpartyemailpassword.Init(nil), + emailpassword.Init(nil), Init(&dashboardmodels.TypeInput{ ApiKey: "testapikey", }), @@ -61,7 +60,7 @@ func TestThatUserGetReturnsTenantIDsCorrectly(t *testing.T) { testServer := httptest.NewServer(supertokens.Middleware(mux)) defer testServer.Close() - signupResponse, err := thirdpartyemailpassword.EmailPasswordSignUp("public", "testing@supertokens.com", "abcd1234") + signupResponse, err := emailpassword.SignUp("public", "testing@supertokens.com", "abcd1234") if err != nil { t.Error(err.Error()) } diff --git a/recipe/dashboard/userPasswordPut_test.go b/recipe/dashboard/userPasswordPut_test.go index a85421f9..30442361 100644 --- a/recipe/dashboard/userPasswordPut_test.go +++ b/recipe/dashboard/userPasswordPut_test.go @@ -8,14 +8,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) /* -- Initialise with thirdpartyemailpassword and provide no custom form fields -- Create an emailpassword user using the thirdpartyemailpassword recipe - Try to change the password of the user - Should result in no errors - Sign in with new password @@ -35,7 +33,7 @@ func TestThatUpdatingPasswordWithNoSignUpFeatureInTPEPWorks(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - thirdpartyemailpassword.Init(nil), + emailpassword.Init(nil), Init(&dashboardmodels.TypeInput{ ApiKey: "testapikey", }), @@ -54,7 +52,7 @@ func TestThatUpdatingPasswordWithNoSignUpFeatureInTPEPWorks(t *testing.T) { testServer := httptest.NewServer(supertokens.Middleware(mux)) defer testServer.Close() - signupResponse, err := thirdpartyemailpassword.EmailPasswordSignUp("public", "testing@supertokens.com", "abcd1234") + signupResponse, err := emailpassword.SignUp("public", "testing@supertokens.com", "abcd1234") if err != nil { t.Error(err.Error()) } @@ -78,7 +76,7 @@ func TestThatUpdatingPasswordWithNoSignUpFeatureInTPEPWorks(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode) - signInResponse, err := thirdpartyemailpassword.EmailPasswordSignIn("public", "testing@supertokens.com", "newabcd1234") + signInResponse, err := emailpassword.SignIn("public", "testing@supertokens.com", "newabcd1234") if err != nil { t.Error(err.Error()) } diff --git a/recipe/dashboard/userPut_test.go b/recipe/dashboard/userPut_test.go index de8afb9a..fc15ec8c 100644 --- a/recipe/dashboard/userPut_test.go +++ b/recipe/dashboard/userPut_test.go @@ -8,14 +8,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) /* -- Initialise with thirdpartyemailpassword and provide no custom form fields -- Create an emailpassword user using the thirdpartyemailpassword recipe - Try to change the password of the user - Should result in no errors - Sign in with new password @@ -35,7 +33,7 @@ func TestThatUpdatingEmailWithNoSignUpFeatureInTPEPWorks(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - thirdpartyemailpassword.Init(nil), + emailpassword.Init(nil), Init(&dashboardmodels.TypeInput{ ApiKey: "testapikey", }), @@ -54,7 +52,7 @@ func TestThatUpdatingEmailWithNoSignUpFeatureInTPEPWorks(t *testing.T) { testServer := httptest.NewServer(supertokens.Middleware(mux)) defer testServer.Close() - signupResponse, err := thirdpartyemailpassword.EmailPasswordSignUp("public", "testing@supertokens.com", "abcd1234") + signupResponse, err := emailpassword.SignUp("public", "testing@supertokens.com", "abcd1234") if err != nil { t.Error(err.Error()) } @@ -78,7 +76,7 @@ func TestThatUpdatingEmailWithNoSignUpFeatureInTPEPWorks(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode) - signInResponse, err := thirdpartyemailpassword.EmailPasswordSignIn("public", "testing2@supertokens.com", "abcd1234") + signInResponse, err := emailpassword.SignIn("public", "testing2@supertokens.com", "abcd1234") if err != nil { t.Error(err.Error()) diff --git a/recipe/emailpassword/authFlow_test.go b/recipe/emailpassword/authFlow_test.go index b2233c0a..720d973f 100644 --- a/recipe/emailpassword/authFlow_test.go +++ b/recipe/emailpassword/authFlow_test.go @@ -20,6 +20,7 @@ import ( "bytes" "encoding/json" "io" + "io/ioutil" "net/http" "net/http/httptest" "strconv" @@ -3016,3 +3017,56 @@ func TestInputEmailIsTrimmed(t *testing.T) { assert.Equal(t, "random@gmail.com", data["user"].(map[string]interface{})["email"]) } + +func TestSignUpAPIWorksWhenInputIsFine(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), + 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() + + resp, err := unittesting.SignupRequest("random@gmail.com", "validpass123", testServer.URL) + if err != nil { + t.Error(err.Error()) + } + assert.Equal(t, http.StatusOK, resp.StatusCode) + dataInBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Error(err.Error()) + } + resp.Body.Close() + + var result map[string]interface{} + + err = json.Unmarshal(dataInBytes, &result) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", result["status"]) + assert.Equal(t, "random@gmail.com", result["user"].(map[string]interface{})["email"]) +} diff --git a/recipe/thirdpartyemailpassword/signupFeature_test.go b/recipe/emailpassword/signinFeature_test.go similarity index 50% rename from recipe/thirdpartyemailpassword/signupFeature_test.go rename to recipe/emailpassword/signinFeature_test.go index be319ea4..cbc5a3cb 100644 --- a/recipe/thirdpartyemailpassword/signupFeature_test.go +++ b/recipe/emailpassword/signinFeature_test.go @@ -13,28 +13,24 @@ * under the License. */ -package thirdpartyemailpassword +package emailpassword import ( - "bytes" "encoding/json" "io" - "io/ioutil" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" + "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" ) -func TestDisablingDefaultAPIDoesNotWork(t *testing.T) { +func TestAfterDisablingTheDefaultSigninAPIdoesNotWork(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ ConnectionURI: "http://localhost:8080", @@ -45,23 +41,10 @@ func TestDisablingDefaultAPIDoesNotWork(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - Init(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.ThirdPartySignInUpPOST = nil + Init(&epmodels.TypeInput{ + Override: &epmodels.OverrideStruct{ + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { + *originalImplementation.SignInPOST = nil return originalImplementation }, }, @@ -80,29 +63,14 @@ func TestDisablingDefaultAPIDoesNotWork(t *testing.T) { testServer := httptest.NewServer(supertokens.Middleware(mux)) defer testServer.Close() - signinupPostData := map[string]interface{}{ - "thirdPartyId": "google", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(signinupPostData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + resp, err := unittesting.SignInRequest("random@gmail.com", "validpass123", testServer.URL) if err != nil { t.Error(err.Error()) } assert.Equal(t, http.StatusNotFound, resp.StatusCode) } -func TestThatIfDisableAPIDefaultSignupAPIDoesNotWork(t *testing.T) { +func TestSignInAPIWorksWhenInputIsFine(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ ConnectionURI: "http://localhost:8080", @@ -113,14 +81,7 @@ func TestThatIfDisableAPIDefaultSignupAPIDoesNotWork(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - Init(&tpepmodels.TypeInput{ - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.EmailPasswordSignUpPOST = nil - return originalImplementation - }, - }, - }), + Init(nil), session.Init(&sessmodels.TypeInput{ GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { return sessmodels.CookieTransferMethod @@ -128,7 +89,6 @@ func TestThatIfDisableAPIDefaultSignupAPIDoesNotWork(t *testing.T) { }), }, } - BeforeEach() unittesting.StartUpST("localhost", "8080") defer AfterEach() @@ -144,104 +104,43 @@ func TestThatIfDisableAPIDefaultSignupAPIDoesNotWork(t *testing.T) { if err != nil { t.Error(err.Error()) } - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - -func TestMinimumConfigForOneProvider(t *testing.T) { - customAntiCsrfVal := "VIA_TOKEN" - 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(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProvider2, - }, - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.EmailPasswordSignUpPOST = nil - return originalImplementation - }, - }, - }), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfVal, - 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) + assert.Equal(t, http.StatusOK, resp.StatusCode) + dataInBytes, err := io.ReadAll(resp.Body) if err != nil { t.Error(err.Error()) } - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() + var result map[string]interface{} + json.Unmarshal(dataInBytes, &result) + resp.Body.Close() - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) + assert.Equal(t, "OK", result["status"]) - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } + signupUserInfo := result["user"].(map[string]interface{}) - postBody, err := json.Marshal(postData) + resp1, err := unittesting.SignInRequest("random@gmail.com", "validpass123", testServer.URL) if err != nil { t.Error(err.Error()) } - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.Equal(t, http.StatusOK, resp1.StatusCode) + dataInBytes1, err := io.ReadAll(resp1.Body) if err != nil { t.Error(err.Error()) } - assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - resp.Body.Close() + var result1 map[string]interface{} + json.Unmarshal(dataInBytes1, &result1) + resp1.Body.Close() - var result map[string]interface{} - - err = json.Unmarshal(dataInBytes, &result) - if err != nil { - t.Error(err.Error()) - } + assert.Equal(t, "OK", result1["status"]) - user := result["user"].(map[string]interface{}) + signInUserInfo := result1["user"].(map[string]interface{}) - assert.Equal(t, "OK", result["status"]) - assert.Equal(t, true, result["createdNewUser"]) - assert.Equal(t, "email@test.com", user["email"]) - assert.Equal(t, "custom", user["thirdParty"].(map[string]interface{})["id"]) - assert.Equal(t, "user", user["thirdParty"].(map[string]interface{})["userId"]) + assert.Equal(t, signInUserInfo["id"], signupUserInfo["id"]) + assert.Equal(t, signInUserInfo["email"], signupUserInfo["email"]) } -func TestSignUpAPIWorksWhenInputIsFine(t *testing.T) { +func TestSigninAPIthrowsAnErrorWhenEmailDoesNotExist(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ ConnectionURI: "http://localhost:8080", @@ -260,7 +159,6 @@ func TestSignUpAPIWorksWhenInputIsFine(t *testing.T) { }), }, } - BeforeEach() unittesting.StartUpST("localhost", "8080") defer AfterEach() @@ -276,20 +174,31 @@ func TestSignUpAPIWorksWhenInputIsFine(t *testing.T) { if err != nil { t.Error(err.Error()) } + assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := ioutil.ReadAll(resp.Body) + dataInBytes, err := io.ReadAll(resp.Body) if err != nil { t.Error(err.Error()) } + var result map[string]interface{} + json.Unmarshal(dataInBytes, &result) resp.Body.Close() - var result map[string]interface{} + assert.Equal(t, "OK", result["status"]) - err = json.Unmarshal(dataInBytes, &result) + resp1, err := unittesting.SignInRequest("rand@gmail.com", "validpass123", testServer.URL) if err != nil { t.Error(err.Error()) } - assert.Equal(t, "OK", result["status"]) - assert.Equal(t, "random@gmail.com", result["user"].(map[string]interface{})["email"]) + assert.Equal(t, http.StatusOK, resp1.StatusCode) + dataInBytes1, err := io.ReadAll(resp1.Body) + if err != nil { + t.Error(err.Error()) + } + var result1 map[string]interface{} + json.Unmarshal(dataInBytes1, &result1) + resp1.Body.Close() + + assert.Equal(t, "WRONG_CREDENTIALS_ERROR", result1["status"]) } diff --git a/recipe/thirdpartyemailpassword/signoutFeature_test.go b/recipe/emailpassword/signoutFeature_test.go similarity index 94% rename from recipe/thirdpartyemailpassword/signoutFeature_test.go rename to recipe/emailpassword/signoutFeature_test.go index 288eb7de..85159c4e 100644 --- a/recipe/thirdpartyemailpassword/signoutFeature_test.go +++ b/recipe/emailpassword/signoutFeature_test.go @@ -13,7 +13,7 @@ * under the License. */ -package thirdpartyemailpassword +package emailpassword import ( "bytes" @@ -26,8 +26,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" "gopkg.in/h2non/gock.v1" @@ -45,11 +43,7 @@ func TestDefaultRouteShouldRevokeSession(t *testing.T) { WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - Init(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProvider2, - }, - }), + Init(nil), session.Init(&sessmodels.TypeInput{ AntiCsrf: &customAntiCsrfVal, GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { diff --git a/recipe/emailpassword/userIdMapping_create_test.go b/recipe/emailpassword/userIdMapping_create_test.go index f98d9461..13c4e5ac 100644 --- a/recipe/emailpassword/userIdMapping_create_test.go +++ b/recipe/emailpassword/userIdMapping_create_test.go @@ -213,3 +213,78 @@ func TestCreateUserIdMappingWithMetadataAndWithAndWithoutForce(t *testing.T) { assert.NotNil(t, createResp.OK) } } + +func TestEPCreateUserIdMappingGetUserById(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + initForUserIdMappingTest(t) + + querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") + assert.NoError(t, err) + + cdiVersion, err := querier.GetQuerierAPIVersion() + assert.NoError(t, err) + + if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { + return + } + + signUpResponse, err := SignUp("public", "test@example.com", "testpass123") + assert.NoError(t, err) + + assert.NotNil(t, signUpResponse.OK) + + externalUserId := "externalId" + externalUserIdInfo := "externalIdInfo" + createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) + assert.NoError(t, err) + assert.NotNil(t, createResp.OK) + + { // Using supertokens ID + userResp, err := GetUserByID(signUpResponse.OK.User.ID) + assert.NoError(t, err) + assert.Equal(t, externalUserId, userResp.ID) + } + + { // Using external ID + userResp, err := GetUserByID(externalUserId) + assert.NoError(t, err) + assert.Equal(t, externalUserId, userResp.ID) + } +} + +func TestEPCreateUserIdMappingGetUserByEmail(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + initForUserIdMappingTest(t) + + querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") + assert.NoError(t, err) + + cdiVersion, err := querier.GetQuerierAPIVersion() + assert.NoError(t, err) + + if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { + return + } + + signUpResponse, err := SignUp("public", "test@example.com", "testpass123") + assert.NoError(t, err) + + assert.NotNil(t, signUpResponse.OK) + + externalUserId := "externalId" + externalUserIdInfo := "externalIdInfo" + createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) + assert.NoError(t, err) + assert.NotNil(t, createResp.OK) + + userResp, err := GetUserByEmail("public", "test@example.com") + assert.NoError(t, err) + assert.NotNil(t, userResp) + assert.Equal(t, externalUserId, userResp.ID) +} diff --git a/recipe/thirdparty/email_test.go b/recipe/thirdparty/email_test.go new file mode 100644 index 00000000..4a895698 --- /dev/null +++ b/recipe/thirdparty/email_test.go @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package thirdparty + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" + "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" + "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/supertokens" + "github.com/supertokens/supertokens-golang/test/unittesting" +) + +func TestDefaultBackwardCompatibilityPasswordResetForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + testServer := supertokensInitForTest( + t, + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(nil), + emailpassword.Init(nil), + ) + defer testServer.Close() + + ManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") + resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.False(t, emailpassword.PasswordResetEmailSentForTest) + assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) + assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) +} + +func TestCustomOverrideResetPasswordForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + customCalled := false + email := "" + passwordResetLink := "" + + epConfig := &epmodels.TypeInput{ + EmailDelivery: &emaildelivery.TypeInput{ + Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { + *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.PasswordReset != nil { + customCalled = true + email = input.PasswordReset.User.Email + passwordResetLink = input.PasswordReset.PasswordResetLink + } + return nil + } + return originalImplementation + }, + }, + } + testServer := supertokensInitForTest( + t, + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(nil), + emailpassword.Init(epConfig), + ) + defer testServer.Close() + + ManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") + resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Default handler not called + assert.False(t, emailpassword.PasswordResetEmailSentForTest) + assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) + assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) + + // Custom handler not called + assert.Empty(t, email) + assert.Empty(t, passwordResetLink) + assert.False(t, customCalled) +} + +func TestSMTPOverridePasswordResetForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + getContentCalled := false + sendRawEmailCalled := false + email := "" + passwordResetLink := "" + + smtpService := emailpassword.MakeSMTPService(emaildelivery.SMTPServiceConfig{ + Settings: emaildelivery.SMTPSettings{ + Host: "", + From: emaildelivery.SMTPFrom{ + Name: "Test User", + Email: "", + }, + Port: 123, + Password: "", + }, + Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { + (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { + if input.PasswordReset != nil { + email = input.PasswordReset.User.Email + passwordResetLink = input.PasswordReset.PasswordResetLink + getContentCalled = true + } + return emaildelivery.EmailContent{}, nil + } + + (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { + sendRawEmailCalled = true + return nil + } + + return originalImplementation + }, + }) + epConfig := &epmodels.TypeInput{ + EmailDelivery: &emaildelivery.TypeInput{ + Service: smtpService, + }, + } + testServer := supertokensInitForTest( + t, + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(nil), + emailpassword.Init(epConfig), + ) + defer testServer.Close() + + ManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") + resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Default handler not called + assert.False(t, emailpassword.PasswordResetEmailSentForTest) + assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) + assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) + + // Custom handler not called + assert.Empty(t, email) + assert.Empty(t, passwordResetLink) + assert.False(t, getContentCalled) + assert.False(t, sendRawEmailCalled) +} diff --git a/recipe/thirdparty/signinupFeature_test.go b/recipe/thirdparty/signinupFeature_test.go index 589ec9bc..88c99dce 100644 --- a/recipe/thirdparty/signinupFeature_test.go +++ b/recipe/thirdparty/signinupFeature_test.go @@ -969,3 +969,106 @@ func TestGetUserByThirdPartyInfoWhenUserDoesNotExist(t *testing.T) { assert.Equal(t, userInfoAfterSignup.ID, user["id"].(string)) assert.Equal(t, userInfoAfterSignup.Email, user["email"].(string)) } + +func TestHandlePostSignUpInGetsSetCorrectly(t *testing.T) { + userId := "" + loginType := "" + customAntiCsrfVal := "VIA_TOKEN" + 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(&tpmodels.TypeInput{ + Override: &tpmodels.OverrideStruct{ + APIs: func(originalImplementation tpmodels.APIInterface) tpmodels.APIInterface { + originalSignInUpPost := *originalImplementation.SignInUpPOST + *originalImplementation.SignInUpPOST = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.SignInUpPOSTResponse, error) { + resp, err := originalSignInUpPost(provider, input, tenantId, options, userContext) + if err != nil { + t.Error(err.Error()) + } + userId = resp.OK.User.ID + loginType = "thirdparty" + return resp, err + } + return originalImplementation + }, + }, + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + customProvider2, + }, + }, + }), + session.Init(&sessmodels.TypeInput{ + AntiCsrf: &customAntiCsrfVal, + 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() + + defer gock.OffAll() + gock.New("https://test.com/"). + Post("oauth/token"). + Reply(200). + JSON(map[string]string{"access_token": "abcdefghj", "email": "test@example.com"}) + + postData := map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err := json.Marshal(postData) + if err != nil { + t.Error(err.Error()) + } + + gock.New(testServer.URL).EnableNetworking().Persist() + gock.New("http://localhost:8080/").EnableNetworking().Persist() + + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + if err != nil { + t.Error(err.Error()) + } + assert.Equal(t, http.StatusOK, resp.StatusCode) + dataInBytes, err := io.ReadAll(resp.Body) + if err != nil { + t.Error(err.Error()) + } + resp.Body.Close() + + var result map[string]interface{} + + err = json.Unmarshal(dataInBytes, &result) + if err != nil { + t.Error(err.Error()) + } + + user := result["user"].(map[string]interface{}) + + assert.Equal(t, userId, user["id"]) + assert.Equal(t, "thirdparty", loginType) +} diff --git a/recipe/thirdparty/testingUtils.go b/recipe/thirdparty/testingUtils.go index f3bf239d..00cc485d 100644 --- a/recipe/thirdparty/testingUtils.go +++ b/recipe/thirdparty/testingUtils.go @@ -179,7 +179,7 @@ var customProvider2 = tpmodels.ProviderInput{ Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { return tpmodels.TypeUserInfo{ - ThirdPartyUserId: oAuthTokens["id"].(string), + ThirdPartyUserId: oAuthTokens["access_token"].(string), Email: &tpmodels.EmailStruct{ ID: oAuthTokens["email"].(string), IsVerified: true, diff --git a/recipe/thirdpartyemailpassword/api/emailPasswordAPIImplementation.go b/recipe/thirdpartyemailpassword/api/emailPasswordAPIImplementation.go deleted file mode 100644 index eb8a1531..00000000 --- a/recipe/thirdpartyemailpassword/api/emailPasswordAPIImplementation.go +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func GetEmailPasswordIterfaceImpl(apiImplmentation tpepmodels.APIInterface) epmodels.APIInterface { - - result := epmodels.APIInterface{ - EmailExistsGET: apiImplmentation.EmailPasswordEmailExistsGET, - GeneratePasswordResetTokenPOST: apiImplmentation.GeneratePasswordResetTokenPOST, - PasswordResetPOST: apiImplmentation.PasswordResetPOST, - SignInPOST: nil, - SignUpPOST: nil, - } - - if apiImplmentation.EmailPasswordSignInPOST != nil && (*apiImplmentation.EmailPasswordSignInPOST) != nil { - signInPOST := func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignInPOSTResponse, error) { - result, err := (*apiImplmentation.EmailPasswordSignInPOST)(formFields, tenantId, options, userContext) - if err != nil { - return epmodels.SignInPOSTResponse{}, err - } - if result.OK != nil { - return epmodels.SignInPOSTResponse{ - OK: &struct { - User epmodels.User - Session sessmodels.SessionContainer - }{ - - User: epmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - }, - Session: result.OK.Session, - }, - }, nil - } else if result.WrongCredentialsError != nil { - return epmodels.SignInPOSTResponse{ - WrongCredentialsError: &struct{}{}, - }, nil - } else { - return epmodels.SignInPOSTResponse{ - GeneralError: result.GeneralError, - }, nil - } - } - result.SignInPOST = &signInPOST - } - - if apiImplmentation.EmailPasswordSignUpPOST != nil && (*apiImplmentation.EmailPasswordSignUpPOST) != nil { - signUpPOST := func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignUpPOSTResponse, error) { - result, err := (*apiImplmentation.EmailPasswordSignUpPOST)(formFields, tenantId, options, userContext) - if err != nil { - return epmodels.SignUpPOSTResponse{}, err - } - if result.OK != nil { - return epmodels.SignUpPOSTResponse{ - OK: &struct { - User epmodels.User - Session sessmodels.SessionContainer - }{ - User: epmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - }, - Session: result.OK.Session, - }, - }, nil - } else if result.EmailAlreadyExistsError != nil { - return epmodels.SignUpPOSTResponse{ - EmailAlreadyExistsError: &struct{}{}, - }, nil - } else { - return epmodels.SignUpPOSTResponse{ - GeneralError: result.GeneralError, - }, nil - } - } - result.SignUpPOST = &signUpPOST - } - - return result -} diff --git a/recipe/thirdpartyemailpassword/api/implementation.go b/recipe/thirdpartyemailpassword/api/implementation.go deleted file mode 100644 index b1b24bb2..00000000 --- a/recipe/thirdpartyemailpassword/api/implementation.go +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - epapi "github.com/supertokens/supertokens-golang/recipe/emailpassword/api" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - tpapi "github.com/supertokens/supertokens-golang/recipe/thirdparty/api" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeAPIImplementation() tpepmodels.APIInterface { - emailPasswordImplementation := epapi.MakeAPIImplementation() - thirdPartyImplementation := tpapi.MakeAPIImplementation() - - ogEmailExistsGET := *emailPasswordImplementation.EmailExistsGET - emailExistsGET := func(email string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) { - return ogEmailExistsGET(email, tenantId, options, userContext) - - } - - ogGeneratePasswordResetTokenPOST := *emailPasswordImplementation.GeneratePasswordResetTokenPOST - generatePasswordResetTokenPOST := func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.GeneratePasswordResetTokenPOSTResponse, error) { - return ogGeneratePasswordResetTokenPOST(formFields, tenantId, options, userContext) - } - - ogPasswordResetPOST := *emailPasswordImplementation.PasswordResetPOST - passwordResetPOST := func(formFields []epmodels.TypeFormField, token string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.ResetPasswordPOSTResponse, error) { - return ogPasswordResetPOST(formFields, token, tenantId, options, userContext) - } - - ogSignInPOST := *emailPasswordImplementation.SignInPOST - emailPasswordSignInPOST := func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignInPOSTResponse, error) { - response, err := ogSignInPOST(formFields, tenantId, options, userContext) - if err != nil { - return tpepmodels.SignInPOSTResponse{}, err - } - if response.OK != nil { - return tpepmodels.SignInPOSTResponse{ - OK: &struct { - User tpepmodels.User - Session sessmodels.SessionContainer - }{ - User: tpepmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - ThirdParty: nil, - }, - Session: response.OK.Session, - }, - }, nil - } else if response.WrongCredentialsError != nil { - return tpepmodels.SignInPOSTResponse{ - WrongCredentialsError: &struct{}{}, - }, nil - } else { - return tpepmodels.SignInPOSTResponse{ - GeneralError: response.GeneralError, - }, nil - } - } - - ogSignUpPOST := *emailPasswordImplementation.SignUpPOST - emailPasswordSignUpPOST := func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignUpPOSTResponse, error) { - response, err := ogSignUpPOST(formFields, tenantId, options, userContext) - if err != nil { - return tpepmodels.SignUpPOSTResponse{}, err - } - if response.OK != nil { - return tpepmodels.SignUpPOSTResponse{ - OK: &struct { - User tpepmodels.User - Session sessmodels.SessionContainer - }{ - User: tpepmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - ThirdParty: nil, - }, - Session: response.OK.Session, - }, - }, nil - } else if response.EmailAlreadyExistsError != nil { - return tpepmodels.SignUpPOSTResponse{ - EmailAlreadyExistsError: &struct{}{}, - }, nil - } else { - return tpepmodels.SignUpPOSTResponse{ - GeneralError: response.GeneralError, - }, nil - } - } - - ogSignInUpPOST := *thirdPartyImplementation.SignInUpPOST - thirdPartySignInUpPOST := func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.ThirdPartySignInUpPOSTResponse, error) { - response, err := ogSignInUpPOST(provider, input, tenantId, options, userContext) - if err != nil { - return tpepmodels.ThirdPartySignInUpPOSTResponse{}, err - } - if response.GeneralError != nil { - return tpepmodels.ThirdPartySignInUpPOSTResponse{ - GeneralError: response.GeneralError, - }, nil - } else if response.NoEmailGivenByProviderError != nil { - return tpepmodels.ThirdPartySignInUpPOSTResponse{ - NoEmailGivenByProviderError: &struct{}{}, - }, nil - } else { - return tpepmodels.ThirdPartySignInUpPOSTResponse{ - OK: &struct { - CreatedNewUser bool - User tpepmodels.User - Session *sessmodels.TypeSessionContainer - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: response.OK.CreatedNewUser, - User: tpepmodels.User{ - ID: response.OK.User.ID, - TimeJoined: response.OK.User.TimeJoined, - Email: response.OK.User.Email, - ThirdParty: &response.OK.User.ThirdParty, - }, - Session: response.OK.Session, - OAuthTokens: response.OK.OAuthTokens, - RawUserInfoFromProvider: response.OK.RawUserInfoFromProvider, - }, - }, nil - } - } - - ogAuthorisationUrlGET := *thirdPartyImplementation.AuthorisationUrlGET - authorisationUrlGET := func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - } - - ogAppleRedirectHandlerPOST := *thirdPartyImplementation.AppleRedirectHandlerPOST - appleRedirectHandlerPOST := func(formPostInfoFromProvider map[string]interface{}, options tpmodels.APIOptions, userContext supertokens.UserContext) error { - return ogAppleRedirectHandlerPOST(formPostInfoFromProvider, options, userContext) - } - - result := tpepmodels.APIInterface{ - AuthorisationUrlGET: &authorisationUrlGET, - ThirdPartySignInUpPOST: &thirdPartySignInUpPOST, - AppleRedirectHandlerPOST: &appleRedirectHandlerPOST, - - EmailPasswordEmailExistsGET: &emailExistsGET, - GeneratePasswordResetTokenPOST: &generatePasswordResetTokenPOST, - PasswordResetPOST: &passwordResetPOST, - EmailPasswordSignInPOST: &emailPasswordSignInPOST, - EmailPasswordSignUpPOST: &emailPasswordSignUpPOST, - } - - modifiedEP := GetEmailPasswordIterfaceImpl(result) - (*emailPasswordImplementation.EmailExistsGET) = *modifiedEP.EmailExistsGET - (*emailPasswordImplementation.GeneratePasswordResetTokenPOST) = *modifiedEP.GeneratePasswordResetTokenPOST - (*emailPasswordImplementation.PasswordResetPOST) = *modifiedEP.PasswordResetPOST - (*emailPasswordImplementation.SignInPOST) = *modifiedEP.SignInPOST - (*emailPasswordImplementation.SignUpPOST) = *modifiedEP.SignUpPOST - - modifiedTP := GetThirdPartyIterfaceImpl(result) - (*thirdPartyImplementation.AuthorisationUrlGET) = *modifiedTP.AuthorisationUrlGET - (*thirdPartyImplementation.SignInUpPOST) = *modifiedTP.SignInUpPOST - (*thirdPartyImplementation.AppleRedirectHandlerPOST) = *modifiedTP.AppleRedirectHandlerPOST - - return result -} diff --git a/recipe/thirdpartyemailpassword/api/thirdPartyAPIImplementation.go b/recipe/thirdpartyemailpassword/api/thirdPartyAPIImplementation.go deleted file mode 100644 index a3dbdc5b..00000000 --- a/recipe/thirdpartyemailpassword/api/thirdPartyAPIImplementation.go +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func GetThirdPartyIterfaceImpl(apiImplmentation tpepmodels.APIInterface) tpmodels.APIInterface { - if apiImplmentation.ThirdPartySignInUpPOST == nil || (*apiImplmentation.ThirdPartySignInUpPOST) == nil { - return tpmodels.APIInterface{ - AuthorisationUrlGET: apiImplmentation.AuthorisationUrlGET, - AppleRedirectHandlerPOST: apiImplmentation.AppleRedirectHandlerPOST, - SignInUpPOST: nil, - } - } - - signInUpPOST := func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.SignInUpPOSTResponse, error) { - result, err := (*apiImplmentation.ThirdPartySignInUpPOST)(provider, input, tenantId, options, userContext) - if err != nil { - return tpmodels.SignInUpPOSTResponse{}, err - } - - if result.OK != nil { - return tpmodels.SignInUpPOSTResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - Session *sessmodels.TypeSessionContainer - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TenantIds: result.OK.User.TenantIds, - TimeJoined: result.OK.User.TimeJoined, - ThirdParty: *result.OK.User.ThirdParty, - }, - Session: result.OK.Session, - OAuthTokens: result.OK.OAuthTokens, - RawUserInfoFromProvider: result.OK.RawUserInfoFromProvider, - }, - }, nil - } else if result.NoEmailGivenByProviderError != nil { - return tpmodels.SignInUpPOSTResponse{ - NoEmailGivenByProviderError: &struct{}{}, - }, nil - } else { - return tpmodels.SignInUpPOSTResponse{ - GeneralError: result.GeneralError, - }, nil - } - } - - return tpmodels.APIInterface{ - AuthorisationUrlGET: apiImplmentation.AuthorisationUrlGET, - AppleRedirectHandlerPOST: apiImplmentation.AppleRedirectHandlerPOST, - SignInUpPOST: &signInUpPOST, - } -} diff --git a/recipe/thirdpartyemailpassword/emaildelivery/backwardCompatibilityService/main.go b/recipe/thirdpartyemailpassword/emaildelivery/backwardCompatibilityService/main.go deleted file mode 100644 index 4d79995a..00000000 --- a/recipe/thirdpartyemailpassword/emaildelivery/backwardCompatibilityService/main.go +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package backwardCompatibilityService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - emailPasswordBackwardsCompatibilityService "github.com/supertokens/supertokens-golang/recipe/emailpassword/emaildelivery/backwardCompatibilityService" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeBackwardCompatibilityService(recipeInterfaceImpl tpepmodels.RecipeInterface, emailPasswordRecipeInterfaceImpl epmodels.RecipeInterface, appInfo supertokens.NormalisedAppinfo, sendResetPasswordEmail func(user epmodels.User, passwordResetURLWithToken string, userContext supertokens.UserContext)) emaildelivery.EmailDeliveryInterface { - // We are using evmodels.User as opposed to tpmodels.User because TypeInput of thirdparty accepts evmodels.TypeInput for EmailVerificationFeature - // Similarly with epmodels.User as well - emailPasswordService := emailPasswordBackwardsCompatibilityService.MakeBackwardCompatibilityService(emailPasswordRecipeInterfaceImpl, appInfo, sendResetPasswordEmail) - - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordReset != nil { - return (*emailPasswordService.SendEmail)(input, userContext) - - } else { - return errors.New("should never come here") - } - } - - return emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - } -} diff --git a/recipe/thirdpartyemailpassword/emaildelivery/smtpService/main.go b/recipe/thirdpartyemailpassword/emaildelivery/smtpService/main.go deleted file mode 100644 index d852f922..00000000 --- a/recipe/thirdpartyemailpassword/emaildelivery/smtpService/main.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package smtpService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - epsmtpService "github.com/supertokens/supertokens-golang/recipe/emailpassword/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeSMTPService(config emaildelivery.SMTPServiceConfig) *emaildelivery.EmailDeliveryInterface { - emailPasswordServiceImpl := epsmtpService.MakeSMTPService(config) - - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordReset != nil { - return (*emailPasswordServiceImpl.SendEmail)(input, userContext) - - } else { - return errors.New("should never come here") - } - } - - return &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - } -} diff --git a/recipe/thirdpartyemailpassword/main.go b/recipe/thirdpartyemailpassword/main.go deleted file mode 100644 index c297bf89..00000000 --- a/recipe/thirdpartyemailpassword/main.go +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/api" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func Init(config *tpepmodels.TypeInput) supertokens.Recipe { - return recipeInit(config) -} - -func ThirdPartyManuallyCreateOrUpdateUser(tenantId string, thirdPartyID string, thirdPartyUserID string, email string, userContext ...supertokens.UserContext) (tpepmodels.ManuallyCreateOrUpdateUserResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tpepmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ThirdPartyManuallyCreateOrUpdateUser)(thirdPartyID, thirdPartyUserID, email, tenantId, userContext[0]) -} - -func ThirdPartyGetProvider(tenantId string, thirdPartyID string, clientType *string, userContext ...supertokens.UserContext) (*tpmodels.TypeProvider, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ThirdPartyGetProvider)(thirdPartyID, clientType, tenantId, userContext[0]) -} - -func GetUserByThirdPartyInfo(tenantId string, thirdPartyID string, thirdPartyUserID string, userContext ...supertokens.UserContext) (*tpepmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByThirdPartyInfo)(thirdPartyID, thirdPartyUserID, tenantId, userContext[0]) -} - -func EmailPasswordSignUp(tenantId string, email, password string, userContext ...supertokens.UserContext) (tpepmodels.SignUpResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tpepmodels.SignUpResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.EmailPasswordSignUp)(email, password, tenantId, userContext[0]) -} - -func EmailPasswordSignIn(tenantId string, email, password string, userContext ...supertokens.UserContext) (tpepmodels.SignInResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tpepmodels.SignInResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.EmailPasswordSignIn)(email, password, tenantId, userContext[0]) -} - -func GetUserById(userID string, userContext ...supertokens.UserContext) (*tpepmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByID)(userID, userContext[0]) -} - -func GetUsersByEmail(tenantId string, email string, userContext ...supertokens.UserContext) ([]tpepmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUsersByEmail)(email, tenantId, userContext[0]) -} - -func CreateResetPasswordToken(tenantId string, userID string, userContext ...supertokens.UserContext) (epmodels.CreateResetPasswordTokenResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return epmodels.CreateResetPasswordTokenResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.CreateResetPasswordToken)(userID, tenantId, userContext[0]) -} - -func ResetPasswordUsingToken(tenantId string, token, newPassword string, userContext ...supertokens.UserContext) (epmodels.ResetPasswordUsingTokenResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return epmodels.ResetPasswordUsingTokenResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ResetPasswordUsingToken)(token, newPassword, tenantId, userContext[0]) -} - -func UpdateEmailOrPassword(userId string, email *string, password *string, applyPasswordPolicy *bool, tenantIdForPasswordPolicy *string, userContext ...supertokens.UserContext) (epmodels.UpdateEmailOrPasswordResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return epmodels.UpdateEmailOrPasswordResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - if tenantIdForPasswordPolicy == nil { - tenantId := supertokens.DefaultTenantId - tenantIdForPasswordPolicy = &tenantId - } - return (*instance.RecipeImpl.UpdateEmailOrPassword)(userId, email, password, applyPasswordPolicy, *tenantIdForPasswordPolicy, userContext[0]) -} - -func SendEmail(input emaildelivery.EmailType, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.EmailDelivery.IngredientInterfaceImpl.SendEmail)(input, userContext[0]) -} - -func CreateResetPasswordLink(tenantId string, userID string, userContext ...supertokens.UserContext) (epmodels.CreateResetPasswordLinkResponse, error) { - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - tokenResponse, err := CreateResetPasswordToken(tenantId, userID, userContext...) - if err != nil { - return epmodels.CreateResetPasswordLinkResponse{}, err - } - if tokenResponse.UnknownUserIdError != nil { - return epmodels.CreateResetPasswordLinkResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } - - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return epmodels.CreateResetPasswordLinkResponse{}, err - } - - link, err := api.GetPasswordResetLink( - instance.RecipeModule.GetAppInfo(), - instance.RecipeModule.GetRecipeID(), - tokenResponse.OK.Token, - tenantId, - supertokens.GetRequestFromUserContext(userContext[0]), - userContext[0], - ) - - if err != nil { - return epmodels.CreateResetPasswordLinkResponse{}, err - } - - return epmodels.CreateResetPasswordLinkResponse{ - OK: &struct{ Link string }{ - Link: link, - }, - }, nil -} - -func SendResetPasswordEmail(tenantId string, userID string, userContext ...supertokens.UserContext) (epmodels.SendResetPasswordEmailResponse, error) { - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - linkResponse, err := CreateResetPasswordLink(tenantId, userID, userContext...) - if err != nil { - return epmodels.SendResetPasswordEmailResponse{}, err - } - if linkResponse.UnknownUserIdError != nil { - return epmodels.SendResetPasswordEmailResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } - - userInfo, err := GetUserById(userID, userContext...) - if err != nil { - return epmodels.SendResetPasswordEmailResponse{}, err - } - if userInfo == nil { - return epmodels.SendResetPasswordEmailResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } - err = SendEmail(emaildelivery.EmailType{ - PasswordReset: &emaildelivery.PasswordResetType{ - User: emaildelivery.User{ - ID: userInfo.ID, - Email: userInfo.Email, - }, - PasswordResetLink: linkResponse.OK.Link, - TenantId: tenantId, - }, - }, userContext...) - if err != nil { - return epmodels.SendResetPasswordEmailResponse{}, err - } - - return epmodels.SendResetPasswordEmailResponse{ - OK: &struct{}{}, - }, nil -} - -func MakeSMTPService(config emaildelivery.SMTPServiceConfig) *emaildelivery.EmailDeliveryInterface { - return smtpService.MakeSMTPService(config) -} diff --git a/recipe/thirdpartyemailpassword/recipe.go b/recipe/thirdpartyemailpassword/recipe.go deleted file mode 100644 index 382f385b..00000000 --- a/recipe/thirdpartyemailpassword/recipe.go +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "errors" - "net/http" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailpassword" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/api" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/recipeimplementation" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -const RECIPE_ID = "thirdpartyemailpassword" - -type Recipe struct { - RecipeModule supertokens.RecipeModule - Config tpepmodels.TypeNormalisedInput - emailPasswordRecipe *emailpassword.Recipe - thirdPartyRecipe *thirdparty.Recipe - RecipeImpl tpepmodels.RecipeInterface - APIImpl tpepmodels.APIInterface - EmailDelivery emaildelivery.Ingredient - GetEmailPasswordRecipe func() *emailpassword.Recipe -} - -var singletonInstance *Recipe - -func MakeRecipe(recipeId string, appInfo supertokens.NormalisedAppinfo, config *tpepmodels.TypeInput, emailVerificationInstance *emailverification.Recipe, thirdPartyInstance *thirdparty.Recipe, emailPasswordInstance *emailpassword.Recipe, emailDeliveryIngredient *emaildelivery.Ingredient, onSuperTokensAPIError func(err error, req *http.Request, res http.ResponseWriter)) (Recipe, error) { - r := &Recipe{} - r.RecipeModule = supertokens.MakeRecipeModule(recipeId, appInfo, r.handleAPIRequest, r.getAllCORSHeaders, r.getAPIsHandled, nil, r.handleError, onSuperTokensAPIError) - - verifiedConfig, err := validateAndNormaliseUserInput(r, appInfo, config) - if err != nil { - return Recipe{}, err - } - r.Config = verifiedConfig - { - emailpasswordquerierInstance, err := supertokens.GetNewQuerierInstanceOrThrowError(emailpassword.RECIPE_ID) - if err != nil { - return Recipe{}, err - } - thirdpartyquerierInstance, err := supertokens.GetNewQuerierInstanceOrThrowError(thirdparty.RECIPE_ID) - if err != nil { - return Recipe{}, err - } - var getEmailPasswordConfig = func() epmodels.TypeNormalisedInput { - return r.emailPasswordRecipe.Config - } - r.RecipeImpl = verifiedConfig.Override.Functions(recipeimplementation.MakeRecipeImplementation(*emailpasswordquerierInstance, thirdpartyquerierInstance, getEmailPasswordConfig, verifiedConfig.Providers)) - } - r.APIImpl = verifiedConfig.Override.APIs(api.MakeAPIImplementation()) - - var emailPasswordRecipe emailpassword.Recipe - emailPasswordRecipeImpl := recipeimplementation.MakeEmailPasswordRecipeImplementation(r.RecipeImpl) - if emailDeliveryIngredient != nil { - r.EmailDelivery = *emailDeliveryIngredient - } else { - r.EmailDelivery = emaildelivery.MakeIngredient(verifiedConfig.GetEmailDeliveryConfig(r.RecipeImpl, emailPasswordRecipeImpl)) - } - - if emailPasswordInstance == nil { - emailPasswordConfig := &epmodels.TypeInput{ - SignUpFeature: verifiedConfig.SignUpFeature, - Override: &epmodels.OverrideStruct{ - Functions: func(_ epmodels.RecipeInterface) epmodels.RecipeInterface { - return emailPasswordRecipeImpl - }, - APIs: func(_ epmodels.APIInterface) epmodels.APIInterface { - return api.GetEmailPasswordIterfaceImpl(r.APIImpl) - }, - }, - } - emailPasswordRecipe, err = emailpassword.MakeRecipe(recipeId, appInfo, emailPasswordConfig, &r.EmailDelivery, onSuperTokensAPIError) - if err != nil { - return Recipe{}, err - } - r.emailPasswordRecipe = &emailPasswordRecipe - } else { - r.emailPasswordRecipe = emailPasswordInstance - } - - if thirdPartyInstance == nil { - thirdPartyConfig := &tpmodels.TypeInput{ - SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ - Providers: verifiedConfig.Providers, - }, - Override: &tpmodels.OverrideStruct{ - Functions: func(_ tpmodels.RecipeInterface) tpmodels.RecipeInterface { - return recipeimplementation.MakeThirdPartyRecipeImplementation(r.RecipeImpl) - }, - APIs: func(_ tpmodels.APIInterface) tpmodels.APIInterface { - return api.GetThirdPartyIterfaceImpl(r.APIImpl) - }, - }, - } - thirdPartyRecipeinstance, err := thirdparty.MakeRecipe(recipeId, appInfo, thirdPartyConfig, &r.EmailDelivery, onSuperTokensAPIError) - if err != nil { - return Recipe{}, err - } - r.thirdPartyRecipe = &thirdPartyRecipeinstance - } else { - r.thirdPartyRecipe = thirdPartyInstance - } - - r.GetEmailPasswordRecipe = func() *emailpassword.Recipe { - return r.emailPasswordRecipe - } - - return *r, nil -} - -func recipeInit(config *tpepmodels.TypeInput) supertokens.Recipe { - return func(appInfo supertokens.NormalisedAppinfo, onSuperTokensAPIError func(err error, req *http.Request, res http.ResponseWriter)) (*supertokens.RecipeModule, error) { - if singletonInstance == nil { - recipe, err := MakeRecipe(RECIPE_ID, appInfo, config, nil, nil, nil, nil, onSuperTokensAPIError) - if err != nil { - return nil, err - } - singletonInstance = &recipe - return &singletonInstance.RecipeModule, nil - } - return nil, errors.New("ThirdPartyEmailPassword recipe has already been initialised. Please check your code for bugs.") - } -} - -func GetRecipeInstanceOrThrowError() (*Recipe, error) { - if singletonInstance != nil { - return singletonInstance, nil - } - return nil, errors.New("Initialisation not done. Did you forget to call the init function?") -} - -func GetRecipeInstance() *Recipe { - return singletonInstance -} - -// implement RecipeModule - -func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { - emailpasswordAPIhandled, err := r.emailPasswordRecipe.RecipeModule.GetAPIsHandled() - if err != nil { - return nil, err - } - apisHandled := append(emailpasswordAPIhandled) - if r.thirdPartyRecipe != nil { - thirdpartyAPIhandled, err := r.thirdPartyRecipe.RecipeModule.GetAPIsHandled() - if err != nil { - return nil, err - } - apisHandled = append(apisHandled, thirdpartyAPIhandled...) - } - return apisHandled, nil -} - -func (r *Recipe) handleAPIRequest(id string, tenantId string, req *http.Request, res http.ResponseWriter, theirHandler http.HandlerFunc, path supertokens.NormalisedURLPath, method string, userContext supertokens.UserContext) error { - ok, _, err := r.emailPasswordRecipe.RecipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) - if err != nil { - return err - } - if ok != nil { - return r.emailPasswordRecipe.RecipeModule.HandleAPIRequest(id, tenantId, req, res, theirHandler, path, method, userContext) - } - if r.thirdPartyRecipe != nil { - ok, _, err := r.thirdPartyRecipe.RecipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) - if err != nil { - return err - } - if ok != nil { - return r.thirdPartyRecipe.RecipeModule.HandleAPIRequest(id, tenantId, req, res, theirHandler, path, method, userContext) - } - } - return errors.New("should not come here") -} - -func (r *Recipe) getAllCORSHeaders() []string { - corsHeaders := r.emailPasswordRecipe.RecipeModule.GetAllCORSHeaders() - if r.thirdPartyRecipe != nil { - corsHeaders = append(corsHeaders, r.thirdPartyRecipe.RecipeModule.GetAllCORSHeaders()...) - } - return corsHeaders -} - -func (r *Recipe) handleError(err error, req *http.Request, res http.ResponseWriter, userContext supertokens.UserContext) (bool, error) { - handleError, err := r.emailPasswordRecipe.RecipeModule.HandleError(err, req, res, userContext) - if err != nil || handleError { - return handleError, err - } - if r.thirdPartyRecipe != nil { - handleError, err = r.thirdPartyRecipe.RecipeModule.HandleError(err, req, res, userContext) - if err != nil || handleError { - return handleError, err - } - } - return false, nil -} - -func ResetForTest() { - singletonInstance = nil -} diff --git a/recipe/thirdpartyemailpassword/recipeimplementation/emailPasswordRecipeImplementation.go b/recipe/thirdpartyemailpassword/recipeimplementation/emailPasswordRecipeImplementation.go deleted file mode 100644 index 86919fd1..00000000 --- a/recipe/thirdpartyemailpassword/recipeimplementation/emailPasswordRecipeImplementation.go +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeEmailPasswordRecipeImplementation(recipeImplementation tpepmodels.RecipeInterface) epmodels.RecipeInterface { - - signUp := func(email, password string, tenantId string, userContext supertokens.UserContext) (epmodels.SignUpResponse, error) { - response, err := (*recipeImplementation.EmailPasswordSignUp)(email, password, tenantId, userContext) - if err != nil { - return epmodels.SignUpResponse{}, err - } - if response.EmailAlreadyExistsError != nil { - return epmodels.SignUpResponse{ - EmailAlreadyExistsError: &struct{}{}, - }, nil - } - return epmodels.SignUpResponse{ - OK: &struct{ User epmodels.User }{ - User: epmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - }, - }, - }, nil - } - - signIn := func(email, password string, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) { - response, err := (*recipeImplementation.EmailPasswordSignIn)(email, password, tenantId, userContext) - if err != nil { - return epmodels.SignInResponse{}, err - } - if response.WrongCredentialsError != nil { - return epmodels.SignInResponse{ - WrongCredentialsError: &struct{}{}, - }, nil - } - return epmodels.SignInResponse{ - OK: &struct{ User epmodels.User }{ - User: epmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - }, - }, - }, nil - } - - getUserByID := func(userId string, userContext supertokens.UserContext) (*epmodels.User, error) { - user, err := (*recipeImplementation.GetUserByID)(userId, userContext) - if err != nil { - return nil, err - } - if user == nil || user.ThirdParty != nil { - return nil, nil - } - return &epmodels.User{ - ID: user.ID, - Email: user.Email, - TimeJoined: user.TimeJoined, - }, nil - } - - getUserByEmail := func(email string, tenantId string, userContext supertokens.UserContext) (*epmodels.User, error) { - users, err := (*recipeImplementation.GetUsersByEmail)(email, tenantId, userContext) - if err != nil { - return nil, err - } - - for _, user := range users { - if user.ThirdParty == nil { - return &epmodels.User{ - ID: user.ID, - Email: user.Email, - TimeJoined: user.TimeJoined, - }, nil - } - } - return nil, nil - } - - createResetPasswordToken := func(userID string, tenantId string, userContext supertokens.UserContext) (epmodels.CreateResetPasswordTokenResponse, error) { - return (*recipeImplementation.CreateResetPasswordToken)(userID, tenantId, userContext) - } - - resetPasswordUsingToken := func(token, newPassword string, tenantId string, userContext supertokens.UserContext) (epmodels.ResetPasswordUsingTokenResponse, error) { - return (*recipeImplementation.ResetPasswordUsingToken)(token, newPassword, tenantId, userContext) - } - - updateEmailOrPassword := func(userId string, email, password *string, applyPasswordPolicy *bool, tenantIdForPasswordPolicy string, userContext supertokens.UserContext) (epmodels.UpdateEmailOrPasswordResponse, error) { - return (*recipeImplementation.UpdateEmailOrPassword)(userId, email, password, applyPasswordPolicy, tenantIdForPasswordPolicy, userContext) - } - - return epmodels.RecipeInterface{ - SignUp: &signUp, - SignIn: &signIn, - GetUserByID: &getUserByID, - GetUserByEmail: &getUserByEmail, - CreateResetPasswordToken: &createResetPasswordToken, - ResetPasswordUsingToken: &resetPasswordUsingToken, - UpdateEmailOrPassword: &updateEmailOrPassword, - } -} diff --git a/recipe/thirdpartyemailpassword/recipeimplementation/main.go b/recipe/thirdpartyemailpassword/recipeimplementation/main.go deleted file mode 100644 index f5a2a3d7..00000000 --- a/recipe/thirdpartyemailpassword/recipeimplementation/main.go +++ /dev/null @@ -1,328 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/recipe/emailpassword" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeRecipeImplementation(emailPasswordQuerier supertokens.Querier, thirdPartyQuerier *supertokens.Querier, getEmailPasswordConfig func() epmodels.TypeNormalisedInput, providers []tpmodels.ProviderInput) tpepmodels.RecipeInterface { - result := tpepmodels.RecipeInterface{} - emailPasswordImplementation := emailpassword.MakeRecipeImplementation(emailPasswordQuerier, getEmailPasswordConfig) - var thirdPartyImplementation *tpmodels.RecipeInterface - if thirdPartyQuerier != nil { - thirdPartyImplementationTemp := thirdparty.MakeRecipeImplementation(*thirdPartyQuerier, providers) - thirdPartyImplementation = &thirdPartyImplementationTemp - } - - ogSignUp := *emailPasswordImplementation.SignUp - signUp := func(email, password string, tenantId string, userContext supertokens.UserContext) (tpepmodels.SignUpResponse, error) { - response, err := ogSignUp(email, password, tenantId, userContext) - if err != nil { - return tpepmodels.SignUpResponse{}, err - } - if response.EmailAlreadyExistsError != nil { - return tpepmodels.SignUpResponse{ - EmailAlreadyExistsError: &struct{}{}, - }, nil - } - return tpepmodels.SignUpResponse{ - OK: &struct { - User tpepmodels.User - }{ - User: tpepmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - ThirdParty: nil, - }, - }, - }, nil - } - - ogSignIn := *emailPasswordImplementation.SignIn - signIn := func(email, password string, tenantId string, userContext supertokens.UserContext) (tpepmodels.SignInResponse, error) { - response, err := ogSignIn(email, password, tenantId, userContext) - if err != nil { - return tpepmodels.SignInResponse{}, err - } - if response.WrongCredentialsError != nil { - return tpepmodels.SignInResponse{ - WrongCredentialsError: &struct{}{}, - }, nil - } - return tpepmodels.SignInResponse{ - OK: &struct{ User tpepmodels.User }{ - User: tpepmodels.User{ - ID: response.OK.User.ID, - Email: response.OK.User.Email, - TimeJoined: response.OK.User.TimeJoined, - ThirdParty: nil, - }, - }, - }, nil - } - - var ogSignInUp func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) = nil - if thirdPartyImplementation != nil { - ogSignInUp = *thirdPartyImplementation.SignInUp - } - signInUp := func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpepmodels.SignInUpResponse, error) { - if ogSignInUp == nil { - return tpepmodels.SignInUpResponse{}, errors.New("no thirdparty provider configured") - } - result, err := ogSignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) - if err != nil { - return tpepmodels.SignInUpResponse{}, err - } - - return tpepmodels.SignInUpResponse{ - OK: &struct { - CreatedNewUser bool - User tpepmodels.User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpepmodels.User{ - ID: result.OK.User.ID, - TimeJoined: result.OK.User.TimeJoined, - Email: result.OK.User.Email, - ThirdParty: &result.OK.User.ThirdParty, - }, - OAuthTokens: result.OK.OAuthTokens, - RawUserInfoFromProvider: result.OK.RawUserInfoFromProvider, - }, - }, nil - } - - var ogManuallyCreateOrUpdateUser func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tpmodels.ManuallyCreateOrUpdateUserResponse, error) = nil - if thirdPartyImplementation != nil { - ogManuallyCreateOrUpdateUser = *thirdPartyImplementation.ManuallyCreateOrUpdateUser - } - manuallyCreateOrUpdateUser := func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tpepmodels.ManuallyCreateOrUpdateUserResponse, error) { - if ogManuallyCreateOrUpdateUser == nil { - return tpepmodels.ManuallyCreateOrUpdateUserResponse{}, errors.New("no thirdparty provider configured") - } - result, err := ogManuallyCreateOrUpdateUser(thirdPartyID, thirdPartyUserID, email, tenantId, userContext) - if err != nil { - return tpepmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - - return tpepmodels.ManuallyCreateOrUpdateUserResponse{ - OK: &struct { - CreatedNewUser bool - User tpepmodels.User - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpepmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - ThirdParty: &result.OK.User.ThirdParty, - }, - }, - }, nil - } - - var ogGetProvider func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) - if thirdPartyImplementation != nil { - ogGetProvider = *thirdPartyImplementation.GetProvider - } - - getProvider := func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) { - if ogGetProvider == nil { - return nil, errors.New("no thirdparty provider configured") - } - - return ogGetProvider(thirdPartyID, clientType, tenantId, userContext) - } - - ogEPGetUserByID := *emailPasswordImplementation.GetUserByID - var ogTPGetUserById func(userID string, userContext supertokens.UserContext) (*tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogTPGetUserById = *thirdPartyImplementation.GetUserByID - } - getUserByID := func(userID string, userContext supertokens.UserContext) (*tpepmodels.User, error) { - user, err := ogEPGetUserByID(userID, userContext) - if err != nil { - return nil, err - } - if user != nil { - return &tpepmodels.User{ - ID: user.ID, - Email: user.Email, - TimeJoined: user.TimeJoined, - TenantIds: user.TenantIds, - ThirdParty: nil, - }, nil - } - if ogTPGetUserById == nil { - return nil, nil - } - - userinfo, err := ogTPGetUserById(userID, userContext) - if err != nil { - return nil, err - } - - if userinfo != nil { - return &tpepmodels.User{ - ID: userinfo.ID, - Email: userinfo.Email, - TimeJoined: userinfo.TimeJoined, - ThirdParty: &userinfo.ThirdParty, - TenantIds: userinfo.TenantIds, - }, nil - } - return nil, nil - } - - ogEPGetUserByEmail := *emailPasswordImplementation.GetUserByEmail - var ogTPGetUsersByEmail func(email string, tenantId string, userContext supertokens.UserContext) ([]tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogTPGetUsersByEmail = *thirdPartyImplementation.GetUsersByEmail - } - getUsersByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]tpepmodels.User, error) { - fromEP, err := ogEPGetUserByEmail(email, tenantId, userContext) - if err != nil { - return []tpepmodels.User{}, err - } - - fromTP := []tpmodels.User{} - if ogTPGetUsersByEmail != nil { - fromTP, err = ogTPGetUsersByEmail(email, tenantId, userContext) - if err != nil { - return []tpepmodels.User{}, err - } - } - finalResult := []tpepmodels.User{} - - if fromEP != nil { - finalResult = append(finalResult, tpepmodels.User{ - ID: fromEP.ID, - TimeJoined: fromEP.TimeJoined, - Email: fromEP.Email, - ThirdParty: nil, - }) - } - - for _, tpUser := range fromTP { - finalResult = append(finalResult, tpepmodels.User{ - ID: tpUser.ID, - TimeJoined: tpUser.TimeJoined, - Email: tpUser.Email, - ThirdParty: &tpUser.ThirdParty, - }) - } - - return finalResult, nil - } - - var ogGetUserByThirdPartyInfo func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogGetUserByThirdPartyInfo = *thirdPartyImplementation.GetUserByThirdPartyInfo - } - getUserByThirdPartyInfo := func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tpepmodels.User, error) { - if ogGetUserByThirdPartyInfo == nil { - return nil, nil - } - - userinfo, err := ogGetUserByThirdPartyInfo(thirdPartyID, thirdPartyUserID, tenantId, userContext) - if err != nil { - return nil, err - } - - if userinfo != nil { - return &tpepmodels.User{ - ID: userinfo.ID, - Email: userinfo.Email, - TimeJoined: userinfo.TimeJoined, - TenantIds: userinfo.TenantIds, - ThirdParty: &userinfo.ThirdParty, - }, nil - } - return nil, nil - } - - ogCreateResetPasswordToken := *emailPasswordImplementation.CreateResetPasswordToken - createResetPasswordToken := func(userID string, tenantId string, userContext supertokens.UserContext) (epmodels.CreateResetPasswordTokenResponse, error) { - return ogCreateResetPasswordToken(userID, tenantId, userContext) - } - - ogResetPasswordUsingToken := *emailPasswordImplementation.ResetPasswordUsingToken - resetPasswordUsingToken := func(token, newPassword string, tenantId string, userContext supertokens.UserContext) (epmodels.ResetPasswordUsingTokenResponse, error) { - return ogResetPasswordUsingToken(token, newPassword, tenantId, userContext) - } - - ogUpdateEmailOrPassword := *emailPasswordImplementation.UpdateEmailOrPassword - updateEmailOrPassword := func(userId string, email, password *string, applyPasswordPolicy *bool, tenantIdForPasswordPolicy string, userContext supertokens.UserContext) (epmodels.UpdateEmailOrPasswordResponse, error) { - user, err := (*result.GetUserByID)(userId, userContext) - if err != nil { - return epmodels.UpdateEmailOrPasswordResponse{}, err - } - - if user == nil { - return epmodels.UpdateEmailOrPasswordResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } else if user.ThirdParty != nil { - return epmodels.UpdateEmailOrPasswordResponse{}, errors.New("cannot update email or password of a user who signed up using third party login") - } - - return ogUpdateEmailOrPassword(userId, email, password, applyPasswordPolicy, tenantIdForPasswordPolicy, userContext) - } - - result.GetUserByID = &getUserByID - result.GetUsersByEmail = &getUsersByEmail - result.GetUserByThirdPartyInfo = &getUserByThirdPartyInfo - result.ThirdPartySignInUp = &signInUp - result.ThirdPartyManuallyCreateOrUpdateUser = &manuallyCreateOrUpdateUser - result.ThirdPartyGetProvider = &getProvider - result.EmailPasswordSignUp = &signUp - result.EmailPasswordSignIn = &signIn - result.CreateResetPasswordToken = &createResetPasswordToken - result.ResetPasswordUsingToken = &resetPasswordUsingToken - result.UpdateEmailOrPassword = &updateEmailOrPassword - - modifiedEp := MakeEmailPasswordRecipeImplementation(result) - (*emailPasswordImplementation.CreateResetPasswordToken) = *modifiedEp.CreateResetPasswordToken - (*emailPasswordImplementation.GetUserByEmail) = *modifiedEp.GetUserByEmail - (*emailPasswordImplementation.GetUserByID) = *modifiedEp.GetUserByID - (*emailPasswordImplementation.ResetPasswordUsingToken) = *modifiedEp.ResetPasswordUsingToken - (*emailPasswordImplementation.SignIn) = *modifiedEp.SignIn - (*emailPasswordImplementation.SignUp) = *modifiedEp.SignUp - (*emailPasswordImplementation.UpdateEmailOrPassword) = *modifiedEp.UpdateEmailOrPassword - - if thirdPartyImplementation != nil { - modifiedTp := MakeThirdPartyRecipeImplementation(result) - (*thirdPartyImplementation.GetUserByID) = *modifiedTp.GetUserByID - (*thirdPartyImplementation.GetUserByThirdPartyInfo) = *modifiedTp.GetUserByThirdPartyInfo - (*thirdPartyImplementation.GetUsersByEmail) = *modifiedTp.GetUsersByEmail - (*thirdPartyImplementation.SignInUp) = *modifiedTp.SignInUp - (*thirdPartyImplementation.ManuallyCreateOrUpdateUser) = *modifiedTp.ManuallyCreateOrUpdateUser - (*thirdPartyImplementation.GetProvider) = *modifiedTp.GetProvider - } - - return result -} diff --git a/recipe/thirdpartyemailpassword/recipeimplementation/thirdPartyRecipeImplementation.go b/recipe/thirdpartyemailpassword/recipeimplementation/thirdPartyRecipeImplementation.go deleted file mode 100644 index e1dd3b6e..00000000 --- a/recipe/thirdpartyemailpassword/recipeimplementation/thirdPartyRecipeImplementation.go +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeThirdPartyRecipeImplementation(recipeImplementation tpepmodels.RecipeInterface) tpmodels.RecipeInterface { - - getUserByThirdPartyInfo := func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tpmodels.User, error) { - user, err := (*recipeImplementation.GetUserByThirdPartyInfo)(thirdPartyID, thirdPartyUserID, tenantId, userContext) - if err != nil { - return nil, err - } - if user == nil || user.ThirdParty == nil { - return nil, nil - } - return &tpmodels.User{ - ID: user.ID, - Email: user.Email, - TimeJoined: user.TimeJoined, - TenantIds: user.TenantIds, - ThirdParty: *user.ThirdParty, - }, nil - } - - signInUp := func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) { - result, err := (*recipeImplementation.ThirdPartySignInUp)(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) - if err != nil { - return tpmodels.SignInUpResponse{}, err - } - - return tpmodels.SignInUpResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - TenantIds: result.OK.User.TenantIds, - ThirdParty: *result.OK.User.ThirdParty, - }, - OAuthTokens: result.OK.OAuthTokens, - RawUserInfoFromProvider: result.OK.RawUserInfoFromProvider, - }, - }, nil - } - - manuallyCreateOrUpdateUser := func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tpmodels.ManuallyCreateOrUpdateUserResponse, error) { - result, err := (*recipeImplementation.ThirdPartyManuallyCreateOrUpdateUser)(thirdPartyID, thirdPartyUserID, email, tenantId, userContext) - if err != nil { - return tpmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - return tpmodels.ManuallyCreateOrUpdateUserResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - TenantIds: result.OK.User.TenantIds, - ThirdParty: struct { - ID string "json:\"id\"" - UserID string "json:\"userId\"" - }{ - ID: result.OK.User.ThirdParty.ID, - UserID: result.OK.User.ThirdParty.UserID, - }, - }, - }, - }, nil - } - - getUserByID := func(userID string, userContext supertokens.UserContext) (*tpmodels.User, error) { - user, err := (*recipeImplementation.GetUserByID)(userID, userContext) - if err != nil { - return nil, err - } - if user == nil || user.ThirdParty == nil { - return nil, nil - } - return &tpmodels.User{ - ID: user.ID, - Email: user.Email, - TimeJoined: user.TimeJoined, - TenantIds: user.TenantIds, - ThirdParty: *user.ThirdParty, - }, nil - } - - getUserByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]tpmodels.User, error) { - users, err := (*recipeImplementation.GetUsersByEmail)(email, tenantId, userContext) - if err != nil { - return nil, err - } - - finalResult := []tpmodels.User{} - - for _, tpepUser := range users { - if tpepUser.ThirdParty != nil { - finalResult = append(finalResult, tpmodels.User{ - ID: tpepUser.ID, - TimeJoined: tpepUser.TimeJoined, - Email: tpepUser.Email, - TenantIds: tpepUser.TenantIds, - ThirdParty: *tpepUser.ThirdParty, - }) - } - } - return finalResult, nil - } - - getProvider := func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) { - return (*recipeImplementation.ThirdPartyGetProvider)(thirdPartyID, clientType, tenantId, userContext) - } - - return tpmodels.RecipeInterface{ - GetUserByID: &getUserByID, - GetUsersByEmail: &getUserByEmail, - GetUserByThirdPartyInfo: &getUserByThirdPartyInfo, - SignInUp: &signInUp, - ManuallyCreateOrUpdateUser: &manuallyCreateOrUpdateUser, - GetProvider: &getProvider, - } -} diff --git a/recipe/thirdpartyemailpassword/signinFeature_test.go b/recipe/thirdpartyemailpassword/signinFeature_test.go deleted file mode 100644 index 21d36280..00000000 --- a/recipe/thirdpartyemailpassword/signinFeature_test.go +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" -) - -func TestAfterDisablingTheDefaultSigninupAPIdoesNotWork(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(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.ThirdPartySignInUpPOST = nil - return originalImplementation - }, - }, - }), - }, - } - - 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() - - signinupPostData := map[string]interface{}{ - "thirdPartyId": "google", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(signinupPostData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - -func TestAfterDisablingTheDefaultSigninAPIdoesNotWork(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(&tpepmodels.TypeInput{ - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - *originalImplementation.EmailPasswordSignInPOST = nil - return originalImplementation - }, - }, - }), - }, - } - - 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() - - resp, err := unittesting.SignInRequest("random@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - -func TestHandlePostSignUpInGetsSetCorrectly(t *testing.T) { - userId := "" - loginType := "" - customAntiCsrfVal := "VIA_TOKEN" - 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(&tpepmodels.TypeInput{ - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - originalSignInUpPost := *originalImplementation.ThirdPartySignInUpPOST - *originalImplementation.ThirdPartySignInUpPOST = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.ThirdPartySignInUpPOSTResponse, error) { - resp, err := originalSignInUpPost(provider, input, tenantId, options, userContext) - if err != nil { - t.Error(err.Error()) - } - userId = resp.OK.User.ID - loginType = "thirdparty" - return resp, err - } - return originalImplementation - }, - }, - Providers: []tpmodels.ProviderInput{ - customProvider2, - }, - }), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfVal, - 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() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - resp.Body.Close() - - var result map[string]interface{} - - err = json.Unmarshal(dataInBytes, &result) - if err != nil { - t.Error(err.Error()) - } - - user := result["user"].(map[string]interface{}) - - assert.Equal(t, userId, user["id"]) - assert.Equal(t, "thirdparty", loginType) -} - -func TestSignInAPIWorksWhenInputIsFine(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), - 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() - - resp, err := unittesting.SignupRequest("random@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - var result map[string]interface{} - json.Unmarshal(dataInBytes, &result) - resp.Body.Close() - - assert.Equal(t, "OK", result["status"]) - - signupUserInfo := result["user"].(map[string]interface{}) - - resp1, err := unittesting.SignInRequest("random@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp1.StatusCode) - dataInBytes1, err := io.ReadAll(resp1.Body) - if err != nil { - t.Error(err.Error()) - } - var result1 map[string]interface{} - json.Unmarshal(dataInBytes1, &result1) - resp1.Body.Close() - - assert.Equal(t, "OK", result1["status"]) - - signInUserInfo := result1["user"].(map[string]interface{}) - - assert.Equal(t, signInUserInfo["id"], signupUserInfo["id"]) - assert.Equal(t, signInUserInfo["email"], signupUserInfo["email"]) -} - -func TestSigninAPIthrowsAnErrorWhenEmailDoesNotExist(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), - 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() - - resp, err := unittesting.SignupRequest("random@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - var result map[string]interface{} - json.Unmarshal(dataInBytes, &result) - resp.Body.Close() - - assert.Equal(t, "OK", result["status"]) - - resp1, err := unittesting.SignInRequest("rand@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp1.StatusCode) - dataInBytes1, err := io.ReadAll(resp1.Body) - if err != nil { - t.Error(err.Error()) - } - var result1 map[string]interface{} - json.Unmarshal(dataInBytes1, &result1) - resp1.Body.Close() - - assert.Equal(t, "WRONG_CREDENTIALS_ERROR", result1["status"]) -} - -func TestCustomEmailValidatorsToSignupAndMakeSureTheyAreAppliedToSignIn(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(&tpepmodels.TypeInput{ - SignUpFeature: &epmodels.TypeInputSignUp{ - FormFields: []epmodels.TypeInputFormField{ - { - ID: "email", - Validate: func(value interface{}, tenantId string) *string { - customErrorMessage := "email does not start with test" - if strings.HasPrefix(value.(string), "test") { - return nil - } - return &customErrorMessage - }, - }, - }, - }, - }), - 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() - - resp, err := unittesting.SignupRequest("testrandom@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp.StatusCode) - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - var result map[string]interface{} - json.Unmarshal(dataInBytes, &result) - resp.Body.Close() - - assert.Equal(t, "OK", result["status"]) - - resp1, err := unittesting.SignInRequest("rand@gmail.com", "validpass123", testServer.URL) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, resp1.StatusCode) - dataInBytes1, err := io.ReadAll(resp1.Body) - if err != nil { - t.Error(err.Error()) - } - var result1 map[string]interface{} - json.Unmarshal(dataInBytes1, &result1) - resp1.Body.Close() - - assert.Equal(t, "FIELD_ERROR", result1["status"]) - assert.Equal(t, "email does not start with test", result1["formFields"].([]interface{})[0].(map[string]interface{})["error"]) - assert.Equal(t, "email", result1["formFields"].([]interface{})[0].(map[string]interface{})["id"]) -} diff --git a/recipe/thirdpartyemailpassword/testingUtils.go b/recipe/thirdpartyemailpassword/testingUtils.go deleted file mode 100644 index aa81b282..00000000 --- a/recipe/thirdpartyemailpassword/testingUtils.go +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailpassword" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/multitenancy" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func resetAll() { - supertokens.ResetForTest() - ResetForTest() - session.ResetForTest() - emailverification.ResetForTest() - thirdparty.ResetForTest() - emailpassword.ResetForTest() - multitenancy.ResetForTest() -} - -func BeforeEach() { - unittesting.KillAllST() - resetAll() - unittesting.SetUpST() -} - -func AfterEach() { - unittesting.KillAllST() - resetAll() - unittesting.CleanST() -} - -type PostDataForCustomProvider struct { - ThirdPartyId string `json:"thirdPartyId"` - OAuthTokens map[string]interface{} `json:"oAuthTokens"` -} - -var customProvider1 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - AuthorizationEndpointQueryParams: map[string]interface{}{ - "scope": "test", - "client_id": "supertokens", - }, - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: true, - }, - }, nil - - } - return originalImplementation - }, -} - -var customProvider2 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: true, - }, - }, nil - } - return originalImplementation - }, -} - -func supertokensInitForTest(t *testing.T, recipes ...supertokens.Recipe) *httptest.Server { - config := supertokens.TypeInput{ - Supertokens: &supertokens.ConnectionInfo{ - ConnectionURI: "http://localhost:8080", - }, - AppInfo: supertokens.AppInfo{ - APIDomain: "api.supertokens.io", - AppName: "SuperTokens", - WebsiteDomain: "supertokens.io", - }, - RecipeList: recipes, - } - - err := supertokens.Init(config) - assert.NoError(t, err) - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - return testServer -} - -var customProviderForEmailVerification = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "test@example.com", - IsVerified: false, - }, - }, nil - } - return originalImplementation - }, -} diff --git a/recipe/thirdpartyemailpassword/tpep_email_test.go b/recipe/thirdpartyemailpassword/tpep_email_test.go deleted file mode 100644 index 828eeb8c..00000000 --- a/recipe/thirdpartyemailpassword/tpep_email_test.go +++ /dev/null @@ -1,968 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "bytes" - "encoding/json" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailpassword" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/emailverification/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestDefaultBackwardCompatibilityPasswordResetForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(nil), - ) - defer testServer.Close() - - EmailPasswordSignUp("public", "test@example.com", "1234abcd") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.True(t, emailpassword.PasswordResetEmailSentForTest) - assert.Equal(t, emailpassword.PasswordResetDataForTest.User.Email, "test@example.com") - assert.NotEmpty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) -} - -func TestDefaultBackwardCompatibilityPasswordResetForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(nil), - ) - defer testServer.Close() - - ThirdPartyManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) -} - -func TestDefaultBackwardCompatibilityPasswordResetForNonExistantUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(nil), - ) - defer testServer.Close() - - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) -} - -func TestCustomOverrideResetPasswordForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - passwordResetLink := "" - - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordReset != nil { - customCalled = true - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - } - return nil - } - return originalImplementation - }, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - EmailPasswordSignUp("public", "test@example.com", "1234abcd") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler called - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, passwordResetLink) - assert.True(t, customCalled) -} - -func TestCustomOverrideResetPasswordForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - passwordResetLink := "" - - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordReset != nil { - customCalled = true - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - } - return nil - } - return originalImplementation - }, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - ThirdPartyManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, passwordResetLink) - assert.False(t, customCalled) -} - -func TestCustomOverrideResetPasswordForNonExistantUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - passwordResetLink := "" - - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordReset != nil { - customCalled = true - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - } - return nil - } - return originalImplementation - }, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, passwordResetLink) - assert.False(t, customCalled) -} - -func TestSMTPOverridePasswordResetForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - passwordResetLink := "" - - smtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordReset != nil { - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - EmailPasswordSignUp("public", "test@example.com", "1234abcd") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, passwordResetLink) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) -} - -func TestSMTPOverridePasswordResetForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - passwordResetLink := "" - - smtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordReset != nil { - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - ThirdPartyManuallyCreateOrUpdateUser("public", "custom", "user-id", "test@example.com") - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, passwordResetLink) - assert.False(t, getContentCalled) - assert.False(t, sendRawEmailCalled) -} - -func TestSMTPOverridePasswordResetForNonExistantUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - passwordResetLink := "" - - smtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordReset != nil { - email = input.PasswordReset.User.Email - passwordResetLink = input.PasswordReset.PasswordResetLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tpepConfig := &tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - resp, err := unittesting.PasswordResetTokenRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, passwordResetLink) - assert.False(t, getContentCalled) - assert.False(t, sendRawEmailCalled) -} - -func TestDefaultBackwardCompatibilityEmailVerifyForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(nil), - ) - defer testServer.Close() - - resp, err := unittesting.SignupRequest("test@example.com", "1234abcd", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.True(t, emailverification.EmailVerificationEmailSentForTest) - assert.Equal(t, emailverification.EmailVerificationDataForTest.User.Email, "test@example.com") - assert.NotEmpty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) -} - -func TestDefaultBackwardCompatibilityEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - tpepConfig := &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProviderForEmailVerification, - }, - } - testServer := supertokensInitForTest(t, - emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.True(t, emailverification.EmailVerificationEmailSentForTest) - assert.Equal(t, emailverification.EmailVerificationDataForTest.User.Email, "test@example.com") - assert.NotEmpty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) -} - -// func TestBackwardCompatibilityEmailVerifyForEmailPasswordUser(t *testing.T) { -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() - -// customCalled := false -// email := "" -// emailVerifyLink := "" - -// tpepConfig := &tpepmodels.TypeInput{ -// EmailVerificationFeature: &tpepmodels.TypeInputEmailVerificationFeature{ -// CreateAndSendCustomEmail: func(user tpepmodels.User, emailVerificationURLWithToken string, userContext supertokens.UserContext) { -// email = user.Email -// emailVerifyLink = emailVerificationURLWithToken -// customCalled = true -// }, -// }, -// } -// testServer := supertokensInitForTest(t, session.Init(nil), Init(tpepConfig)) -// defer testServer.Close() - -// resp, err := unittesting.SignupRequest("test@example.com", "1234abcd", testServer.URL) -// assert.NoError(t, err) - -// cookies := resp.Cookies() -// resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) - -// // Default handler not called -// assert.False(t, emailpassword.PasswordResetEmailSentForTest) -// assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) -// assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - -// // Custom handler called -// assert.Equal(t, email, "test@example.com") -// assert.NotEmpty(t, emailVerifyLink) -// assert.True(t, customCalled) -// } - -// func TestBackwardCompatibilityEmailVerifyForThirdpartyUser(t *testing.T) { -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() - -// customCalled := false -// email := "" -// emailVerifyLink := "" -// var thirdparty *struct { -// ID string `json:"id"` -// UserID string `json:"userId"` -// } - -// tpepConfig := &tpepmodels.TypeInput{ -// EmailVerificationFeature: &tpepmodels.TypeInputEmailVerificationFeature{ -// CreateAndSendCustomEmail: func(user tpepmodels.User, emailVerificationURLWithToken string, userContext supertokens.UserContext) { -// email = user.Email -// emailVerifyLink = emailVerificationURLWithToken -// thirdparty = user.ThirdParty -// customCalled = true -// }, -// }, -// Providers: []tpmodels.TypeProvider{customProviderForEmailVerification}, -// } -// testServer := supertokensInitForTest(t, session.Init(nil), Init(tpepConfig)) -// defer testServer.Close() - -// signinupPostData := PostDataForCustomProvider{ -// ThirdPartyId: "custom", -// AuthCodeResponse: map[string]string{ -// "access_token": "saodiasjodai", -// }, -// RedirectUri: "http://127.0.0.1/callback", -// } - -// postBody, err := json.Marshal(signinupPostData) -// resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) -// assert.NoError(t, err) - -// cookies := resp.Cookies() -// resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) - -// // Default handler not called -// assert.False(t, emailpassword.PasswordResetEmailSentForTest) -// assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) -// assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - -// // Custom handler called -// assert.Equal(t, email, "test@example.com") -// assert.NotEmpty(t, emailVerifyLink) -// assert.NotNil(t, thirdparty) -// assert.True(t, customCalled) -// } - -func TestCustomOverrideEmailVerifyForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - emailVerifyLink := "" - - tpepConfig := &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProviderForEmailVerification, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.EmailVerification != nil { - customCalled = true - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - } - return nil - } - return originalImplementation - }, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - resp, err := unittesting.SignupRequest("test@example.com", "1234abcd", testServer.URL) - assert.NoError(t, err) - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler called - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.True(t, customCalled) -} - -func TestCustomOverrideEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - emailVerifyLink := "" - - tpepConfig := &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - customProviderForEmailVerification, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.EmailVerification != nil { - customCalled = true - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - } - return nil - } - return originalImplementation - }, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - // Custom handler called - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.True(t, customCalled) -} - -func TestSMTPOverrideEmailVerifyForEmailPasswordUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - emailVerifyLink := "" - - smtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.EmailVerification != nil { - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tpepConfig := &tpepmodels.TypeInput{} - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - resp, err := unittesting.SignupRequest("test@example.com", "1234abcd", testServer.URL) - assert.NoError(t, err) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) -} - -func TestSMTPOverrideEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - emailVerifyLink := "" - - smtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.EmailVerification != nil { - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tpepConfig := &tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{customProviderForEmailVerification}, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tpepConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailpassword.PasswordResetEmailSentForTest) - assert.Empty(t, emailpassword.PasswordResetDataForTest.User.Email) - assert.Empty(t, emailpassword.PasswordResetDataForTest.PasswordResetURLWithToken) - - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) -} - -func TestSendResetPassworEmailFunction(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - resetLink := "" - - testServer := supertokensInitForTest(t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(&tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - resetLink = input.PasswordReset.PasswordResetLink - return nil - } - return originalImplementation - }, - }, - }), - ) - defer testServer.Close() - - user, err := EmailPasswordSignUp("public", "test@example.com", "pass1234") - assert.NoError(t, err) - - resp, err := SendResetPasswordEmail("public", user.OK.User.ID) - assert.NoError(t, err) - assert.True(t, resp.OK != nil) - - assert.Contains(t, resetLink, "rid=thirdpartyemailpassword") - assert.Contains(t, resetLink, "tenantId=public") - assert.Contains(t, resetLink, "token=") -} diff --git a/recipe/thirdpartyemailpassword/tpep_userIdMapping_test.go b/recipe/thirdpartyemailpassword/tpep_userIdMapping_test.go deleted file mode 100644 index 34ecd32f..00000000 --- a/recipe/thirdpartyemailpassword/tpep_userIdMapping_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package thirdpartyemailpassword - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func initForUserIdMappingTest(t *testing.T) { - - config := 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(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - })}, - } - - err := supertokens.Init(config) - assert.NoError(t, err) -} - -func TestCreateUserIdMappingUsingEmail(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := ThirdPartyManuallyCreateOrUpdateUser("public", "google", "googleID", "test@example.com") - assert.NoError(t, err) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - { // Using supertokens ID - userResp, err := GetUserById(signUpResponse.OK.User.ID) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using external ID - userResp, err := GetUserById(externalUserId) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using thirdparty info - userResp, err := GetUserByThirdPartyInfo("public", "google", "googleID") - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } -} - -func TestEPCreateUserIdMappingGetUserById(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := EmailPasswordSignUp("public", "test@example.com", "testpass123") - assert.NoError(t, err) - - assert.NotNil(t, signUpResponse.OK) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - { // Using supertokens ID - userResp, err := GetUserById(signUpResponse.OK.User.ID) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using external ID - userResp, err := GetUserById(externalUserId) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } -} - -func TestEPCreateUserIdMappingGetUserByEmail(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := EmailPasswordSignUp("public", "test@example.com", "testpass123") - assert.NoError(t, err) - - assert.NotNil(t, signUpResponse.OK) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - userResp, err := GetUsersByEmail("public", "test@example.com") - assert.NoError(t, err) - assert.NotNil(t, userResp) - assert.Equal(t, 1, len(userResp)) - for _, user := range userResp { - assert.Equal(t, externalUserId, user.ID) - } -} diff --git a/recipe/thirdpartyemailpassword/tpepmodels/apiInterface.go b/recipe/thirdpartyemailpassword/tpepmodels/apiInterface.go deleted file mode 100644 index d2f7a758..00000000 --- a/recipe/thirdpartyemailpassword/tpepmodels/apiInterface.go +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tpepmodels - -import ( - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -type APIInterface struct { - AuthorisationUrlGET *func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) - AppleRedirectHandlerPOST *func(formPostInfoFromProvider map[string]interface{}, options tpmodels.APIOptions, userContext supertokens.UserContext) error - ThirdPartySignInUpPOST *func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (ThirdPartySignInUpPOSTResponse, error) - - EmailPasswordEmailExistsGET *func(email string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) - GeneratePasswordResetTokenPOST *func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.GeneratePasswordResetTokenPOSTResponse, error) - PasswordResetPOST *func(formFields []epmodels.TypeFormField, token string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.ResetPasswordPOSTResponse, error) - EmailPasswordSignInPOST *func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (SignInPOSTResponse, error) - EmailPasswordSignUpPOST *func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (SignUpPOSTResponse, error) -} - -type SignUpPOSTResponse struct { - OK *struct { - User User - Session sessmodels.SessionContainer - } - EmailAlreadyExistsError *struct{} - GeneralError *supertokens.GeneralErrorResponse -} - -type SignInPOSTResponse struct { - OK *struct { - User User - Session sessmodels.SessionContainer - } - WrongCredentialsError *struct{} - GeneralError *supertokens.GeneralErrorResponse -} - -type EmailpasswordInput struct { - IsSignIn bool - FormFields []epmodels.TypeFormField - Options epmodels.APIOptions -} - -type EmailpasswordOutput struct { - OK *struct { - User User - CreatedNewUser bool - } - EmailAlreadyExistsError *struct{} - WrongCredentialsError *struct{} -} - -type ThirdPartySignInUpPOSTResponse struct { - OK *struct { - CreatedNewUser bool - User User - Session sessmodels.SessionContainer - OAuthTokens tpmodels.TypeOAuthTokens - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - } - NoEmailGivenByProviderError *struct{} - GeneralError *supertokens.GeneralErrorResponse -} diff --git a/recipe/thirdpartyemailpassword/tpepmodels/models.go b/recipe/thirdpartyemailpassword/tpepmodels/models.go deleted file mode 100644 index 369b4631..00000000 --- a/recipe/thirdpartyemailpassword/tpepmodels/models.go +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tpepmodels - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" -) - -type User struct { - ID string `json:"id"` - TimeJoined uint64 `json:"timeJoined"` - Email string `json:"email"` - ThirdParty *struct { - ID string `json:"id"` - UserID string `json:"userId"` - } `json:"thirdParty"` - TenantIds []string `json:"tenantIds"` -} - -type TypeContext struct { - FormFields []epmodels.TypeFormField - ThirdPartyAuthCodeResponse interface{} -} - -type TypeInput struct { - SignUpFeature *epmodels.TypeInputSignUp - Providers []tpmodels.ProviderInput - Override *OverrideStruct - EmailDelivery *emaildelivery.TypeInput -} - -type TypeNormalisedInput struct { - SignUpFeature *epmodels.TypeInputSignUp - Providers []tpmodels.ProviderInput - Override OverrideStruct - GetEmailDeliveryConfig func(recipeImpl RecipeInterface, epRecipeImpl epmodels.RecipeInterface) emaildelivery.TypeInputWithService -} - -type OverrideStruct struct { - Functions func(originalImplementation RecipeInterface) RecipeInterface - APIs func(originalImplementation APIInterface) APIInterface -} - -type EmailStruct struct { - ID string `json:"id"` - IsVerified bool `json:"isVerified"` -} diff --git a/recipe/thirdpartyemailpassword/tpepmodels/recipeInterface.go b/recipe/thirdpartyemailpassword/tpepmodels/recipeInterface.go deleted file mode 100644 index c99f7e00..00000000 --- a/recipe/thirdpartyemailpassword/tpepmodels/recipeInterface.go +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tpepmodels - -import ( - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -type RecipeInterface struct { - GetUserByID *func(userID string, userContext supertokens.UserContext) (*User, error) - GetUsersByEmail *func(email string, tenantId string, userContext supertokens.UserContext) ([]User, error) - GetUserByThirdPartyInfo *func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*User, error) - - ThirdPartySignInUp *func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (SignInUpResponse, error) - ThirdPartyManuallyCreateOrUpdateUser *func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (ManuallyCreateOrUpdateUserResponse, error) - ThirdPartyGetProvider *func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) - - EmailPasswordSignUp *func(email string, password string, tenantId string, userContext supertokens.UserContext) (SignUpResponse, error) - EmailPasswordSignIn *func(email string, password string, tenantId string, userContext supertokens.UserContext) (SignInResponse, error) - CreateResetPasswordToken *func(userID string, tenantId string, userContext supertokens.UserContext) (epmodels.CreateResetPasswordTokenResponse, error) - ResetPasswordUsingToken *func(token string, newPassword string, tenantId string, userContext supertokens.UserContext) (epmodels.ResetPasswordUsingTokenResponse, error) - UpdateEmailOrPassword *func(userId string, email *string, password *string, applyPasswordPolicy *bool, tenantIdForPasswordPolicy string, userContext supertokens.UserContext) (epmodels.UpdateEmailOrPasswordResponse, error) -} - -type SignInUpResponse struct { - OK *struct { - CreatedNewUser bool - User User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - } -} - -type ManuallyCreateOrUpdateUserResponse struct { - OK *struct { - CreatedNewUser bool - User User - } -} - -type SignUpResponse struct { - OK *struct { - User User - } - EmailAlreadyExistsError *struct{} -} - -type SignInResponse struct { - OK *struct { - User User - } - WrongCredentialsError *struct{} -} diff --git a/recipe/thirdpartyemailpassword/utils.go b/recipe/thirdpartyemailpassword/utils.go deleted file mode 100644 index 0f351079..00000000 --- a/recipe/thirdpartyemailpassword/utils.go +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartyemailpassword - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailpassword" - "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/emaildelivery/backwardCompatibilityService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func validateAndNormaliseUserInput(recipeInstance *Recipe, appInfo supertokens.NormalisedAppinfo, config *tpepmodels.TypeInput) (tpepmodels.TypeNormalisedInput, error) { - typeNormalisedInput := makeTypeNormalisedInput(recipeInstance) - - if config != nil && config.SignUpFeature != nil { - typeNormalisedInput.SignUpFeature = config.SignUpFeature - } - - if config != nil && config.Providers != nil { - typeNormalisedInput.Providers = config.Providers - } - - typeNormalisedInput.GetEmailDeliveryConfig = func(recipeImpl tpepmodels.RecipeInterface, epRecipeImpl epmodels.RecipeInterface) emaildelivery.TypeInputWithService { - sendPasswordResetEmail := emailpassword.DefaultCreateAndSendCustomPasswordResetEmail(appInfo) - emailService := backwardCompatibilityService.MakeBackwardCompatibilityService(recipeImpl, epRecipeImpl, appInfo, sendPasswordResetEmail) - if config != nil && config.EmailDelivery != nil && config.EmailDelivery.Service != nil { - emailService = *config.EmailDelivery.Service - } - result := emaildelivery.TypeInputWithService{ - Service: emailService, - } - if config != nil && config.EmailDelivery != nil && config.EmailDelivery.Override != nil { - result.Override = config.EmailDelivery.Override - } - - return result - } - - if config != nil && config.Override != nil { - if config.Override.Functions != nil { - typeNormalisedInput.Override.Functions = config.Override.Functions - } - if config.Override.APIs != nil { - typeNormalisedInput.Override.APIs = config.Override.APIs - } - } - - return typeNormalisedInput, nil -} - -func makeTypeNormalisedInput(recipeInstance *Recipe) tpepmodels.TypeNormalisedInput { - return tpepmodels.TypeNormalisedInput{ - SignUpFeature: nil, - Providers: nil, - Override: tpepmodels.OverrideStruct{ - Functions: func(originalImplementation tpepmodels.RecipeInterface) tpepmodels.RecipeInterface { - return originalImplementation - }, - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - return originalImplementation - }, - }, - } -} diff --git a/test/auth-react-server/main.go b/test/auth-react-server/main.go index 7f79e2e8..ef4418bc 100644 --- a/test/auth-react-server/main.go +++ b/test/auth-react-server/main.go @@ -44,8 +44,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" "github.com/supertokens/supertokens-golang/recipe/userroles" @@ -94,7 +92,6 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { passwordless.ResetForTest() session.ResetForTest() thirdparty.ResetForTest() - thirdpartyemailpassword.ResetForTest() thirdpartypasswordless.ResetForTest() userroles.ResetForTest() multitenancy.ResetForTest() @@ -332,134 +329,134 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { }, }, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendPasswordResetEmail, - }, - }, - Override: &tpepmodels.OverrideStruct{ - APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - ogPasswordResetPOST := *originalImplementation.PasswordResetPOST - ogGeneratePasswordResetTokenPOST := *originalImplementation.GeneratePasswordResetTokenPOST - ogEmailExistsGET := *originalImplementation.EmailPasswordEmailExistsGET - ogSignUpPOST := *originalImplementation.EmailPasswordSignUpPOST - ogSignInPOST := *originalImplementation.EmailPasswordSignInPOST - ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET - ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST - - (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) - if gr != nil { - return tpmodels.AuthorisationUrlGETResponse{ - GeneralError: gr, - }, nil - } - return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - } - - (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.ThirdPartySignInUpPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) - if gr != nil { - return tpepmodels.ThirdPartySignInUpPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogSignInUpPOST(provider, input, tenantId, options, userContext) - } - - (*originalImplementation.PasswordResetPOST) = func(formFields []epmodels.TypeFormField, token string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.ResetPasswordPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password consume", false) - if gr != nil { - return epmodels.ResetPasswordPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogPasswordResetPOST(formFields, token, tenantId, options, userContext) - } - - (*originalImplementation.GeneratePasswordResetTokenPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.GeneratePasswordResetTokenPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password", false) - if gr != nil { - return epmodels.GeneratePasswordResetTokenPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogGeneratePasswordResetTokenPOST(formFields, tenantId, options, userContext) - } - - (*originalImplementation.EmailPasswordEmailExistsGET) = func(email string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API email exists", true) - if gr != nil { - return epmodels.EmailExistsGETResponse{ - GeneralError: gr, - }, nil - } - return ogEmailExistsGET(email, tenantId, options, userContext) - } - - (*originalImplementation.EmailPasswordSignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignUpPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign up", false) - if gr != nil { - return tpepmodels.SignUpPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogSignUpPOST(formFields, tenantId, options, userContext) - } - - (*originalImplementation.EmailPasswordSignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignInPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in", false) - if gr != nil { - return tpepmodels.SignInPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogSignInPOST(formFields, tenantId, options, userContext) - } - return originalImplementation - }, - }, - SignUpFeature: &epmodels.TypeInputSignUp{ - FormFields: formFields, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("GOOGLE_CLIENT_ID"), - ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), - }, - }, - }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("GITHUB_CLIENT_ID"), - ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), - }, - }, - }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "facebook", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), - ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), - }, - }, - }, - }, - customAuth0Provider(), - }, - }), + // thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + // EmailDelivery: &emaildelivery.TypeInput{ + // Service: &emaildelivery.EmailDeliveryInterface{ + // SendEmail: &sendPasswordResetEmail, + // }, + // }, + // Override: &tpepmodels.OverrideStruct{ + // APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { + // ogPasswordResetPOST := *originalImplementation.PasswordResetPOST + // ogGeneratePasswordResetTokenPOST := *originalImplementation.GeneratePasswordResetTokenPOST + // ogEmailExistsGET := *originalImplementation.EmailPasswordEmailExistsGET + // ogSignUpPOST := *originalImplementation.EmailPasswordSignUpPOST + // ogSignInPOST := *originalImplementation.EmailPasswordSignInPOST + // ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET + // ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST + + // (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) + // if gr != nil { + // return tpmodels.AuthorisationUrlGETResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) + // } + + // (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.ThirdPartySignInUpPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) + // if gr != nil { + // return tpepmodels.ThirdPartySignInUpPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogSignInUpPOST(provider, input, tenantId, options, userContext) + // } + + // (*originalImplementation.PasswordResetPOST) = func(formFields []epmodels.TypeFormField, token string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.ResetPasswordPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password consume", false) + // if gr != nil { + // return epmodels.ResetPasswordPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogPasswordResetPOST(formFields, token, tenantId, options, userContext) + // } + + // (*originalImplementation.GeneratePasswordResetTokenPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.GeneratePasswordResetTokenPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password", false) + // if gr != nil { + // return epmodels.GeneratePasswordResetTokenPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogGeneratePasswordResetTokenPOST(formFields, tenantId, options, userContext) + // } + + // (*originalImplementation.EmailPasswordEmailExistsGET) = func(email string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API email exists", true) + // if gr != nil { + // return epmodels.EmailExistsGETResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogEmailExistsGET(email, tenantId, options, userContext) + // } + + // (*originalImplementation.EmailPasswordSignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignUpPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign up", false) + // if gr != nil { + // return tpepmodels.SignUpPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogSignUpPOST(formFields, tenantId, options, userContext) + // } + + // (*originalImplementation.EmailPasswordSignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignInPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in", false) + // if gr != nil { + // return tpepmodels.SignInPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogSignInPOST(formFields, tenantId, options, userContext) + // } + // return originalImplementation + // }, + // }, + // SignUpFeature: &epmodels.TypeInputSignUp{ + // FormFields: formFields, + // }, + // Providers: []tpmodels.ProviderInput{ + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "google", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("GOOGLE_CLIENT_ID"), + // ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "github", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("GITHUB_CLIENT_ID"), + // ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "facebook", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), + // ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // customAuth0Provider(), + // }, + // }), session.Init(&sessmodels.TypeInput{ Override: &sessmodels.OverrideStruct{ APIs: func(originalImplementation sessmodels.APIInterface) sessmodels.APIInterface { From bc07f5b0b6e2e6333f081ca5633b5df9350ba891 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Tue, 9 Apr 2024 14:41:58 +0530 Subject: [PATCH 03/19] small changes --- recipe/dashboard/api/userdetails/userPasswordPut.go | 2 +- recipe/dashboard/api/utils.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/recipe/dashboard/api/userdetails/userPasswordPut.go b/recipe/dashboard/api/userdetails/userPasswordPut.go index bff11fdf..f66460c1 100644 --- a/recipe/dashboard/api/userdetails/userPasswordPut.go +++ b/recipe/dashboard/api/userdetails/userPasswordPut.go @@ -69,7 +69,7 @@ func UserPasswordPut(apiInterface dashboardmodels.APIInterface, tenantId string, } if recipeToUse == "none" { - // This means that neither emailpassword or thirdpartyemailpassword is initialised + // This means that emailpassword is not init return userPasswordPutResponse{}, errors.New("Should never come here") } diff --git a/recipe/dashboard/api/utils.go b/recipe/dashboard/api/utils.go index 7179f08c..5490a2bc 100644 --- a/recipe/dashboard/api/utils.go +++ b/recipe/dashboard/api/utils.go @@ -18,12 +18,10 @@ func IsValidRecipeId(recipeId string) bool { /* This function tries to fetch a user for the given user id and recipe id. The input recipe id should be one of the primary recipes (emailpassword, thirdparty, passwordless) but the returned -recipe will be the exact recipe that matched for the user (including thirdpartyemailpassword and -thirdpartypasswordless). +recipe will be the exact recipe that matched for the user When fetching a user we need to check for multiple recipes per input recipe id, for example a user -created using email and password could be present for the EmailPassword recipe and the ThirdPartyEmailPassword -recipe so we need to check for both. +created using email and password could be present for the EmailPassword recipe so we need to check for both. If this function returns an empty user struct, it should be treated as if the user does not exist */ From 684569985d90b9d764693d81379bc46a8f91d9f9 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Tue, 9 Apr 2024 23:25:08 +0530 Subject: [PATCH 04/19] more test removal --- recipe/passwordless/api_test.go | 599 +++++++ recipe/passwordless/config_test.go | 679 ++++++++ recipe/thirdpartypasswordless/api_test.go | 1461 ----------------- .../authorizationUrlFeature_test.go | 163 -- recipe/thirdpartypasswordless/config_test.go | 906 ---------- 5 files changed, 1278 insertions(+), 2530 deletions(-) delete mode 100644 recipe/thirdpartypasswordless/api_test.go delete mode 100644 recipe/thirdpartypasswordless/authorizationUrlFeature_test.go delete mode 100644 recipe/thirdpartypasswordless/config_test.go diff --git a/recipe/passwordless/api_test.go b/recipe/passwordless/api_test.go index 0852fe56..e223cc6e 100644 --- a/recipe/passwordless/api_test.go +++ b/recipe/passwordless/api_test.go @@ -21,6 +21,7 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "testing" "time" @@ -34,6 +35,604 @@ import ( "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestWithEmailExistAPI(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + query := req.URL.Query() + query.Add("email", "test@example.com") + req.URL.RawQuery = query.Encode() + assert.NoError(t, err) + emailDoesNotExistResp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailDoesNotExistResp.StatusCode) + + emailDoesNotExistResponse := *unittesting.HttpResponseToConsumableInformation(emailDoesNotExistResp.Body) + + assert.Equal(t, "OK", emailDoesNotExistResponse["status"]) + assert.False(t, emailDoesNotExistResponse["exists"].(bool)) + + codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) + assert.NoError(t, err) + + ConsumeCodeWithLinkCode("public", codeInfo.OK.LinkCode, codeInfo.OK.PreAuthSessionID) + + req, err = http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + query = req.URL.Query() + query.Add("email", "test@example.com") + req.URL.RawQuery = query.Encode() + assert.NoError(t, err) + emailExistsResp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailExistsResp.StatusCode) + + emailExistsResponse := *unittesting.HttpResponseToConsumableInformation(emailExistsResp.Body) + + assert.Equal(t, "OK", emailExistsResponse["status"]) + assert.True(t, emailExistsResponse["exists"].(bool)) +} + +func TestMagicLinkFormatInCreateCodeAPI(t *testing.T) { + var magicLinkURL *url.URL + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + magicLinkURL, _ = url.Parse(*input.PasswordlessLogin.UrlWithLinkCode) + return nil + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + validCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, validCreateCodeResp.StatusCode) + + validCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(validCreateCodeResp.Body) + + assert.Equal(t, "OK", validCreateCodeResponse["status"]) + assert.Equal(t, "supertokens.io", magicLinkURL.Hostname()) + assert.Equal(t, "/auth/verify", magicLinkURL.Path) + assert.Equal(t, "passwordless", magicLinkURL.Query().Get("rid")) + assert.Equal(t, validCreateCodeResponse["preAuthSessionId"], magicLinkURL.Query().Get("preAuthSessionId")) +} + +func TestPhoneNumberToAUsersInfoAndSigningInWillSignInTheSameUserUsingTheEmailOrPhoneContactMethod(t *testing.T) { + var userInputCodeRef string + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + userInputCodeRef = *input.PasswordlessLogin.UserInputCode + return nil + } + sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { + userInputCodeRef = *input.PasswordlessLogin.UserInputCode + return nil + } + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + SmsDelivery: &smsdelivery.TypeInput{ + Service: &smsdelivery.SmsDeliveryInterface{ + SendSms: &sendSms, + }, + }, + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailCreateCodeResult := *unittesting.HttpResponseToConsumableInformation(emailResp.Body) + + assert.Equal(t, "OK", emailCreateCodeResult["status"]) + + consumeCodePostData := map[string]interface{}{ + "preAuthSessionId": emailCreateCodeResult["preAuthSessionId"], + "userInputCode": userInputCodeRef, + "deviceId": emailCreateCodeResult["deviceId"], + } + + consumeCodePostBody, err := json.Marshal(consumeCodePostData) + if err != nil { + t.Error(err.Error()) + } + + consumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, consumeCodeResp.StatusCode) + + emailUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp.Body) + + assert.Equal(t, "OK", emailUserInputCodeResponse["status"]) + user := emailUserInputCodeResponse["user"].(map[string]interface{}) + + phoneNumber := "+12345678901" + UpdateUser(user["id"].(string), nil, &phoneNumber) + + phoneNumberPostData := map[string]interface{}{ + "phoneNumber": "+12345678901", + } + + phoneNumberPostBody, err := json.Marshal(phoneNumberPostData) + if err != nil { + t.Error(err.Error()) + } + + phoneNumberPostResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneNumberPostBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, phoneNumberPostResp.StatusCode) + + phoneCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(phoneNumberPostResp.Body) + + assert.Equal(t, "OK", phoneCreateCodeResponse["status"]) + + consumeCodePostData1 := map[string]interface{}{ + "preAuthSessionId": phoneCreateCodeResponse["preAuthSessionId"], + "userInputCode": userInputCodeRef, + "deviceId": phoneCreateCodeResponse["deviceId"], + } + + consumeCodePostBody1, err := json.Marshal(consumeCodePostData1) + if err != nil { + t.Error(err.Error()) + } + + consumeCodeResp1, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody1)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, consumeCodeResp1.StatusCode) + + phoneUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp1.Body) + + assert.Equal(t, "OK", phoneUserInputCodeResponse["status"]) + user1 := phoneUserInputCodeResponse["user"].(map[string]interface{}) + + assert.Equal(t, user["id"], user1["id"]) +} + +func TestWithInvalidInputToCreateCodeAPIWhileUsingTheEmailOrPhoneContactMethod(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + postData := map[string]interface{}{ + "email": "test@example.com", + "phoneNumber": "+12345678901", + } + + postBody, err := json.Marshal(postData) + if err != nil { + t.Error(err.Error()) + } + + resp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(postBody)) + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) + assert.NoError(t, err) + + result := *unittesting.HttpResponseToConsumableInformation(resp.Body) + + assert.Equal(t, "Please provide exactly one of email or phoneNumber", result["message"]) + + postData = map[string]interface{}{} + + postBody, err = json.Marshal(postData) + if err != nil { + t.Error(err.Error()) + } + + resp1, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(postBody)) + assert.Equal(t, http.StatusBadRequest, resp1.StatusCode) + assert.NoError(t, err) + + result1 := *unittesting.HttpResponseToConsumableInformation(resp1.Body) + + assert.Equal(t, "Please provide exactly one of email or phoneNumber", result1["message"]) +} + +func TestForCreatingACodeWithEmailAndThenResendingTheCodeAndCheckThatTheSendingCustomEmailFunctionIsCalledWhileUsingTheEmailOrPhoneContactMethod(t *testing.T) { + isCreateAndSendCustomEmailCalled := false + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + isCreateAndSendCustomEmailCalled = true + return nil + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + result := *unittesting.HttpResponseToConsumableInformation(emailResp.Body) + + assert.Equal(t, "OK", result["status"]) + assert.True(t, isCreateAndSendCustomEmailCalled) + + isCreateAndSendCustomEmailCalled = false + + codeResendPostData := map[string]interface{}{ + "deviceId": result["deviceId"], + "preAuthSessionId": result["preAuthSessionId"], + } + + codeResendPostBody, err := json.Marshal(codeResendPostData) + if err != nil { + t.Error(err.Error()) + } + + codeResendPostResp, err := http.Post(testServer.URL+"/auth/signinup/code/resend", "application/json", bytes.NewBuffer(codeResendPostBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, codeResendPostResp.StatusCode) + + codeResendResult := *unittesting.HttpResponseToConsumableInformation(codeResendPostResp.Body) + assert.Equal(t, "OK", codeResendResult["status"]) + assert.True(t, isCreateAndSendCustomEmailCalled) +} + +func TestSignUpSignInFlowWithPhoneNumberUsingEmailOrPhoneContactMethod(t *testing.T) { + var userInputCodeRef string + sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { + userInputCodeRef = *input.PasswordlessLogin.UserInputCode + return nil + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + SmsDelivery: &smsdelivery.TypeInput{ + Service: &smsdelivery.SmsDeliveryInterface{ + SendSms: &sendSms, + }, + }, + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + phone := map[string]interface{}{ + "phoneNumber": "+12345678901", + } + + phoneBody, err := json.Marshal(phone) + if err != nil { + t.Error(err.Error()) + } + + phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, phoneResp.StatusCode) + + result := *unittesting.HttpResponseToConsumableInformation(phoneResp.Body) + + assert.Equal(t, "OK", result["status"]) + assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", result["flowType"]) + + consumeCodePostData := map[string]interface{}{ + "preAuthSessionId": result["preAuthSessionId"], + "userInputCode": userInputCodeRef, + "deviceId": result["deviceId"], + } + + consumeCodePostBody, err := json.Marshal(consumeCodePostData) + if err != nil { + t.Error(err.Error()) + } + + consumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, consumeCodeResp.StatusCode) + + codeConsumeResult := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp.Body) + + user := codeConsumeResult["user"].(map[string]interface{}) + assert.Equal(t, "OK", codeConsumeResult["status"]) + assert.True(t, codeConsumeResult["createdNewUser"].(bool)) + assert.NotNil(t, user) + assert.Nil(t, user["email"]) + assert.NotNil(t, user["id"]) + assert.NotNil(t, user["timeJoined"]) + assert.NotNil(t, user["phoneNumber"]) +} + func TestSignInUpFlowWithEmailUsingTheEmailOrPhoneContactMethod(t *testing.T) { var userInputCodeRef *string sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { diff --git a/recipe/passwordless/config_test.go b/recipe/passwordless/config_test.go index 6189f9a7..868cfe07 100644 --- a/recipe/passwordless/config_test.go +++ b/recipe/passwordless/config_test.go @@ -34,6 +34,685 @@ import ( "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestForThatForCreateAndCustomEmailIfErrorIsThrownTheStatusInTheResponseShouldBeA500Error(t *testing.T) { + isCreateAndSendCustomEmailCalled := false + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + isCreateAndSendCustomEmailCalled = true + return errors.New("test message") + } + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, 500, emailResp.StatusCode) + assert.True(t, isCreateAndSendCustomEmailCalled) +} + +func TestWithCreateAndSendCustomEmailWithFlowTypeUserInputCodeAndMagicLinkAndEmailContactMethod(t *testing.T) { + isUserInputCodeAndUrlWithLinkCodeValid := false + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode != nil { + isUserInputCodeAndUrlWithLinkCodeValid = true + } + return nil + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailDataInBytes, err := io.ReadAll(emailResp.Body) + if err != nil { + t.Error(err.Error()) + } + emailResp.Body.Close() + + var emailResult map[string]interface{} + err = json.Unmarshal(emailDataInBytes, &emailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", emailResult["status"]) + assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) +} + +func TestCreateAndSendCustomEmailWithFlowTypeMagicLinkAndEmailContactMethod(t *testing.T) { + isUserInputCodeAndUrlWithLinkCodeValid := false + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.PasswordlessLogin.UserInputCode == nil && input.PasswordlessLogin.UrlWithLinkCode != nil { + isUserInputCodeAndUrlWithLinkCodeValid = true + } + return nil + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "MAGIC_LINK", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailDataInBytes, err := io.ReadAll(emailResp.Body) + if err != nil { + t.Error(err.Error()) + } + emailResp.Body.Close() + + var emailResult map[string]interface{} + err = json.Unmarshal(emailDataInBytes, &emailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", emailResult["status"]) + assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) +} + +func TestCreateAndSendCustomEmailWithFlowTypeUserInputCodeAndEmailContactMethod(t *testing.T) { + isUserInputCodeAndUrlWithLinkCodeValid := false + sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode == nil { + isUserInputCodeAndUrlWithLinkCodeValid = true + } + return nil + + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE", + EmailDelivery: &emaildelivery.TypeInput{ + Service: &emaildelivery.EmailDeliveryInterface{ + SendEmail: &sendEmail, + }, + }, + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailDataInBytes, err := io.ReadAll(emailResp.Body) + if err != nil { + t.Error(err.Error()) + } + emailResp.Body.Close() + + var emailResult map[string]interface{} + err = json.Unmarshal(emailDataInBytes, &emailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", emailResult["status"]) + assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) +} + +func TestValidateEmailAdressThrowsGenericErrorInCaseOfReturningAString(t *testing.T) { + isValidateEmailAddressCalled := false + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + ValidateEmailAddress: func(email interface{}, tenantId string) *string { + isValidateEmailAddressCalled = true + message := "test error" + return &message + }, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailDataInBytes, err := io.ReadAll(emailResp.Body) + if err != nil { + t.Error(err.Error()) + } + emailResp.Body.Close() + + var emailResult map[string]interface{} + err = json.Unmarshal(emailDataInBytes, &emailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "GENERAL_ERROR", emailResult["status"]) + assert.Equal(t, "test error", emailResult["message"]) + assert.True(t, isValidateEmailAddressCalled) +} + +func TestIfValidateEmailAdressIsCalledWithContactMethod(t *testing.T) { + isValidateEmailAddressCalled := false + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + ValidateEmailAddress: func(email interface{}, tenantId string) *string { + isValidateEmailAddressCalled = true + return nil + }, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + email := map[string]interface{}{ + "email": "test@example.com", + } + + emailBody, err := json.Marshal(email) + if err != nil { + t.Error(err.Error()) + } + + emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailResp.StatusCode) + + emailDataInBytes, err := io.ReadAll(emailResp.Body) + if err != nil { + t.Error(err.Error()) + } + emailResp.Body.Close() + + var emailResult map[string]interface{} + err = json.Unmarshal(emailDataInBytes, &emailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", emailResult["status"]) + assert.True(t, isValidateEmailAddressCalled) +} + +func TestCreateAndSendCustomTextMessageIfErrorIsThrownItShouldReturnA500Error(t *testing.T) { + isUserInputCodeAndUrlWithLinkCodeValid := false + sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { + isUserInputCodeAndUrlWithLinkCodeValid = true + return errors.New("test message") + } + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "MAGIC_LINK", + SmsDelivery: &smsdelivery.TypeInput{ + Service: &smsdelivery.SmsDeliveryInterface{ + SendSms: &sendSms, + }, + }, + ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + phone := map[string]interface{}{ + "phoneNumber": "+12345678901", + } + + phoneBody, err := json.Marshal(phone) + if err != nil { + t.Error(err.Error()) + } + + phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) + + assert.NoError(t, err) + assert.Equal(t, 500, phoneResp.StatusCode) + assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) +} + +func TestCreateAndSendCustomMessageWithFlowTypeUserInputCodeAndMagicLinkAndPhoneContactMethod(t *testing.T) { + isUserInputCodeAndUrlWithLinkCodeValid := false + sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { + if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode != nil { + isUserInputCodeAndUrlWithLinkCodeValid = true + } + return nil + } + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + SmsDelivery: &smsdelivery.TypeInput{ + Service: &smsdelivery.SmsDeliveryInterface{ + SendSms: &sendSms, + }, + }, + ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + phone := map[string]interface{}{ + "phoneNumber": "+12345678901", + } + + phoneBody, err := json.Marshal(phone) + if err != nil { + t.Error(err.Error()) + } + + phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, phoneResp.StatusCode) + + phoneDataInBytes, err := io.ReadAll(phoneResp.Body) + if err != nil { + t.Error(err.Error()) + } + phoneResp.Body.Close() + + var phoneResult map[string]interface{} + err = json.Unmarshal(phoneDataInBytes, &phoneResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", phoneResult["status"]) + assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) +} + func TestMinimumConfigWithEmailOrPhoneContactMethod(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/recipe/thirdpartypasswordless/api_test.go b/recipe/thirdpartypasswordless/api_test.go deleted file mode 100644 index a2192828..00000000 --- a/recipe/thirdpartypasswordless/api_test.go +++ /dev/null @@ -1,1461 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "net/url" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestForThirdPartyPasswordlessSignInUpFlowWithEmailUsingTheEmailOrPhoneContactMethod(t *testing.T) { - var userInputCodeRef string - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - userInputCodeRef = *input.PasswordlessLogin.UserInputCode - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var validCreateCodeResponse map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &validCreateCodeResponse) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", validCreateCodeResponse["status"]) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validCreateCodeResponse["flowType"]) - - data := map[string]interface{}{ - "preAuthSessionId": validCreateCodeResponse["preAuthSessionId"], - "userInputCode": userInputCodeRef, - "deviceId": validCreateCodeResponse["deviceId"], - } - - condeConsumePostBody, err := json.Marshal(data) - if err != nil { - t.Error(err.Error()) - } - - validUserInputCodeResponse, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(condeConsumePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, validUserInputCodeResponse.StatusCode) - - validUserInputCodeDataInBytes, err := io.ReadAll(validUserInputCodeResponse.Body) - if err != nil { - t.Error(err.Error()) - } - validUserInputCodeResponse.Body.Close() - - var validUserInputCodeDataResponse map[string]interface{} - err = json.Unmarshal(validUserInputCodeDataInBytes, &validUserInputCodeDataResponse) - if err != nil { - t.Error(err.Error()) - } - - user := validUserInputCodeDataResponse["user"].(map[string]interface{}) - assert.Equal(t, "OK", validUserInputCodeDataResponse["status"]) - assert.True(t, validUserInputCodeDataResponse["createdNewUser"].(bool)) - assert.NotNil(t, user) - assert.NotNil(t, user["email"]) - assert.NotNil(t, user["id"]) - assert.NotNil(t, user["timeJoined"]) - assert.Nil(t, user["phoneNumber"]) -} - -func TestForThirdPartyPasswordlessSignUpSignInFlowWithPhoneNumberUsingEmailOrPhoneContactMethod(t *testing.T) { - var userInputCodeRef string - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - userInputCodeRef = *input.PasswordlessLogin.UserInputCode - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - phone := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneBody, err := json.Marshal(phone) - if err != nil { - t.Error(err.Error()) - } - - phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneResp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(phoneResp.Body) - - assert.Equal(t, "OK", result["status"]) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", result["flowType"]) - - consumeCodePostData := map[string]interface{}{ - "preAuthSessionId": result["preAuthSessionId"], - "userInputCode": userInputCodeRef, - "deviceId": result["deviceId"], - } - - consumeCodePostBody, err := json.Marshal(consumeCodePostData) - if err != nil { - t.Error(err.Error()) - } - - consumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, consumeCodeResp.StatusCode) - - codeConsumeResult := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp.Body) - - user := codeConsumeResult["user"].(map[string]interface{}) - assert.Equal(t, "OK", codeConsumeResult["status"]) - assert.True(t, codeConsumeResult["createdNewUser"].(bool)) - assert.NotNil(t, user) - assert.Nil(t, user["email"]) - assert.NotNil(t, user["id"]) - assert.NotNil(t, user["timeJoined"]) - assert.NotNil(t, user["phoneNumber"]) -} - -func TestForThirdPartyPasswordlessCreatingACodeWithEmailAndThenResendingTheCodeAndCheckThatTheSendingCustomEmailFunctionIsCalledWhileUsingTheEmailOrPhoneContactMethod(t *testing.T) { - isCreateAndSendCustomEmailCalled := false - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - isCreateAndSendCustomEmailCalled = true - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(emailResp.Body) - - assert.Equal(t, "OK", result["status"]) - assert.True(t, isCreateAndSendCustomEmailCalled) - - isCreateAndSendCustomEmailCalled = false - - codeResendPostData := map[string]interface{}{ - "deviceId": result["deviceId"], - "preAuthSessionId": result["preAuthSessionId"], - } - - codeResendPostBody, err := json.Marshal(codeResendPostData) - if err != nil { - t.Error(err.Error()) - } - - codeResendPostResp, err := http.Post(testServer.URL+"/auth/signinup/code/resend", "application/json", bytes.NewBuffer(codeResendPostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, codeResendPostResp.StatusCode) - - codeResendResult := *unittesting.HttpResponseToConsumableInformation(codeResendPostResp.Body) - assert.Equal(t, "OK", codeResendResult["status"]) - assert.True(t, isCreateAndSendCustomEmailCalled) -} - -func TestWithThirdPartyPasswordlessInvalidInputToCreateCodeAPIWhileUsingTheEmailOrPhoneContactMethod(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - postData := map[string]interface{}{ - "email": "test@example.com", - "phoneNumber": "+12345678901", - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(postBody)) - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - assert.NoError(t, err) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, "Please provide exactly one of email or phoneNumber", result["message"]) - - postData = map[string]interface{}{} - - postBody, err = json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - resp1, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(postBody)) - assert.Equal(t, http.StatusBadRequest, resp1.StatusCode) - assert.NoError(t, err) - - result1 := *unittesting.HttpResponseToConsumableInformation(resp1.Body) - - assert.Equal(t, "Please provide exactly one of email or phoneNumber", result1["message"]) -} - -func TestWithThirdPartyPasswordLessAddingPhoneNumberToAUsersInfoAndSigningInWillSignInTheSameUserUsingTheEmailOrPhoneContactMethod(t *testing.T) { - var userInputCodeRef string - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - userInputCodeRef = *input.PasswordlessLogin.UserInputCode - return nil - } - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - userInputCodeRef = *input.PasswordlessLogin.UserInputCode - return nil - } - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailCreateCodeResult := *unittesting.HttpResponseToConsumableInformation(emailResp.Body) - - assert.Equal(t, "OK", emailCreateCodeResult["status"]) - - consumeCodePostData := map[string]interface{}{ - "preAuthSessionId": emailCreateCodeResult["preAuthSessionId"], - "userInputCode": userInputCodeRef, - "deviceId": emailCreateCodeResult["deviceId"], - } - - consumeCodePostBody, err := json.Marshal(consumeCodePostData) - if err != nil { - t.Error(err.Error()) - } - - consumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, consumeCodeResp.StatusCode) - - emailUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp.Body) - - assert.Equal(t, "OK", emailUserInputCodeResponse["status"]) - user := emailUserInputCodeResponse["user"].(map[string]interface{}) - - phoneNumber := "+12345678901" - UpdatePasswordlessUser(user["id"].(string), nil, &phoneNumber) - - phoneNumberPostData := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneNumberPostBody, err := json.Marshal(phoneNumberPostData) - if err != nil { - t.Error(err.Error()) - } - - phoneNumberPostResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneNumberPostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneNumberPostResp.StatusCode) - - phoneCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(phoneNumberPostResp.Body) - - assert.Equal(t, "OK", phoneCreateCodeResponse["status"]) - - consumeCodePostData1 := map[string]interface{}{ - "preAuthSessionId": phoneCreateCodeResponse["preAuthSessionId"], - "userInputCode": userInputCodeRef, - "deviceId": phoneCreateCodeResponse["deviceId"], - } - - consumeCodePostBody1, err := json.Marshal(consumeCodePostData1) - if err != nil { - t.Error(err.Error()) - } - - consumeCodeResp1, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody1)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, consumeCodeResp1.StatusCode) - - phoneUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp1.Body) - - assert.Equal(t, "OK", phoneUserInputCodeResponse["status"]) - user1 := phoneUserInputCodeResponse["user"].(map[string]interface{}) - - assert.Equal(t, user["id"], user1["id"]) -} - -func TestNotPassingAnyFieldsToConsumeCodeAPI(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - consumeCodePostData := map[string]interface{}{ - "preAuthSessionId": "preAuthSessionId", - } - - consumeCodePostBody, err := json.Marshal(consumeCodePostData) - if err != nil { - t.Error(err.Error()) - } - - consumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusBadRequest, consumeCodeResp.StatusCode) - - emailUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(consumeCodeResp.Body) - - assert.Equal(t, "Please provide one of (linkCode) or (deviceId+userInputCode) and not both", emailUserInputCodeResponse["message"]) -} - -func TestWithThirdPartyPasswordlessConsumeCodeAPIWithMagicLink(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - consumeCodePostData := map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "linkCode": "invalidLinkCode", - } - - consumeCodePostBody, err := json.Marshal(consumeCodePostData) - if err != nil { - t.Error(t, err) - } - - invalidConsumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, invalidConsumeCodeResp.StatusCode) - - invalidLinkCodeResponse := *unittesting.HttpResponseToConsumableInformation(invalidConsumeCodeResp.Body) - assert.Equal(t, "RESTART_FLOW_ERROR", invalidLinkCodeResponse["status"]) - - consumeCodePostData = map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "linkCode": codeInfo.OK.LinkCode, - } - - consumeCodePostBody, err = json.Marshal(consumeCodePostData) - if err != nil { - t.Error(t, err) - } - - validConsumeCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, validConsumeCodeResp.StatusCode) - - validLinkCodeResponse := *unittesting.HttpResponseToConsumableInformation(validConsumeCodeResp.Body) - assert.Equal(t, "OK", validLinkCodeResponse["status"]) - assert.True(t, validLinkCodeResponse["createdNewUser"].(bool)) - user := validLinkCodeResponse["user"].(map[string]interface{}) - assert.NotNil(t, user) - assert.NotNil(t, user["email"]) - assert.NotNil(t, user["id"]) - assert.NotNil(t, user["timeJoined"]) - assert.Nil(t, user["phoneNumber"]) -} - -func TestWithThirdPartyPasswordlessConsumeCodeAPIWithCode(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - consumeCodePostData := map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "deviceId": codeInfo.OK.DeviceID, - "userInputCode": "invalidCode", - } - - consumeCodePostBody, err := json.Marshal(consumeCodePostData) - if err != nil { - t.Error(t, err) - } - - incorrectUserInputCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, incorrectUserInputCodeResp.StatusCode) - - incorrectUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(incorrectUserInputCodeResp.Body) - assert.Equal(t, "INCORRECT_USER_INPUT_CODE_ERROR", incorrectUserInputCodeResponse["status"]) - assert.Equal(t, float64(1), incorrectUserInputCodeResponse["failedCodeInputAttemptCount"]) - assert.Equal(t, float64(5), incorrectUserInputCodeResponse["maximumCodeInputAttempts"]) - - consumeCodePostData = map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "deviceId": codeInfo.OK.DeviceID, - "userInputCode": codeInfo.OK.UserInputCode, - } - - consumeCodePostBody, err = json.Marshal(consumeCodePostData) - if err != nil { - t.Error(t, err) - } - - correctUserInputCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, correctUserInputCodeResp.StatusCode) - - correctUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(correctUserInputCodeResp.Body) - assert.Equal(t, "OK", correctUserInputCodeResponse["status"]) - assert.True(t, correctUserInputCodeResponse["createdNewUser"].(bool)) - - user := correctUserInputCodeResponse["user"].(map[string]interface{}) - assert.NotNil(t, user) - assert.NotNil(t, user["email"]) - assert.NotNil(t, user["id"]) - assert.NotNil(t, user["timeJoined"]) - assert.Nil(t, user["phoneNumber"]) - - consumeCodePostData = map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "deviceId": codeInfo.OK.DeviceID, - "userInputCode": codeInfo.OK.UserInputCode, - } - - consumeCodePostBody, err = json.Marshal(consumeCodePostData) - if err != nil { - t.Error(t, err) - } - - usedUserInputCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(consumeCodePostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, usedUserInputCodeResp.StatusCode) - - usedUserInputCodeResponse := *unittesting.HttpResponseToConsumableInformation(usedUserInputCodeResp.Body) - assert.Equal(t, "RESTART_FLOW_ERROR", usedUserInputCodeResponse["status"]) -} - -func TestWithThirdPartyPasswordLessConsumeCodeAPIWithExpiredCode(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - time.Sleep(2 * time.Second) - - expiredCodeResendPostBody := map[string]interface{}{ - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - "userInputCode": codeInfo.OK.UserInputCode, - "deviceId": codeInfo.OK.DeviceID, - } - - expiredCodeResendPostBodyJson, err := json.Marshal(expiredCodeResendPostBody) - if err != nil { - t.Error(err.Error()) - } - - expiredCodeResendResp, err := http.Post(testServer.URL+"/auth/signinup/code/consume", "application/json", bytes.NewBuffer(expiredCodeResendPostBodyJson)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, expiredCodeResendResp.StatusCode) - - expiredCodeResendResponse := *unittesting.HttpResponseToConsumableInformation(expiredCodeResendResp.Body) - assert.Equal(t, "EXPIRED_USER_INPUT_CODE_ERROR", expiredCodeResendResponse["status"]) - assert.Equal(t, float64(1), expiredCodeResendResponse["failedCodeInputAttemptCount"]) - assert.Equal(t, float64(5), expiredCodeResendResponse["maximumCodeInputAttempts"]) -} - -func TestWithThirdPartyPasswordlessCreateCodeAPIWithEmail(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - validCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, validCreateCodeResp.StatusCode) - - validCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(validCreateCodeResp.Body) - - assert.Equal(t, "OK", validCreateCodeResponse["status"]) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validCreateCodeResponse["flowType"]) - - email = map[string]interface{}{ - "email": "testmpeom", - } - - emailBody, err = json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - inValidCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, inValidCreateCodeResp.StatusCode) - - inValidCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(inValidCreateCodeResp.Body) - - assert.Equal(t, "GENERAL_ERROR", inValidCreateCodeResponse["status"]) - assert.Equal(t, "Email is invalid", inValidCreateCodeResponse["message"]) -} - -func TestWithThirdPartyPasswordlessCreateCodeAPIWithPhoneNumber(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - phoneNumber := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneNumberBody, err := json.Marshal(phoneNumber) - if err != nil { - t.Error(err.Error()) - } - - validCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneNumberBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, validCreateCodeResp.StatusCode) - - validCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(validCreateCodeResp.Body) - - assert.Equal(t, "OK", validCreateCodeResponse["status"]) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validCreateCodeResponse["flowType"]) - - phoneNumber = map[string]interface{}{ - "phoneNumber": "231", - } - - phoneNumberBody, err = json.Marshal(phoneNumber) - if err != nil { - t.Error(err.Error()) - } - - inValidCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneNumberBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, inValidCreateCodeResp.StatusCode) - - inValidCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(inValidCreateCodeResp.Body) - - assert.Equal(t, "GENERAL_ERROR", inValidCreateCodeResponse["status"]) - assert.Equal(t, "Phone number is invalid", inValidCreateCodeResponse["message"]) -} - -func TestWithThirdPartyPasswordlessMagicLinkFormatInCreateCodeAPI(t *testing.T) { - var magicLinkURL *url.URL - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - magicLinkURL, _ = url.Parse(*input.PasswordlessLogin.UrlWithLinkCode) - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - validCreateCodeResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, validCreateCodeResp.StatusCode) - - validCreateCodeResponse := *unittesting.HttpResponseToConsumableInformation(validCreateCodeResp.Body) - - assert.Equal(t, "OK", validCreateCodeResponse["status"]) - assert.Equal(t, "supertokens.io", magicLinkURL.Hostname()) - assert.Equal(t, "/auth/verify", magicLinkURL.Path) - assert.Equal(t, "thirdpartypasswordless", magicLinkURL.Query().Get("rid")) - assert.Equal(t, validCreateCodeResponse["preAuthSessionId"], magicLinkURL.Query().Get("preAuthSessionId")) -} - -func TestWithThirdPartyPasswordlessEmailExistAPI(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - query := req.URL.Query() - query.Add("email", "test@example.com") - req.URL.RawQuery = query.Encode() - assert.NoError(t, err) - emailDoesNotExistResp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailDoesNotExistResp.StatusCode) - - emailDoesNotExistResponse := *unittesting.HttpResponseToConsumableInformation(emailDoesNotExistResp.Body) - - assert.Equal(t, "OK", emailDoesNotExistResponse["status"]) - assert.False(t, emailDoesNotExistResponse["exists"].(bool)) - - codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - ConsumeCodeWithLinkCode("public", codeInfo.OK.LinkCode, codeInfo.OK.PreAuthSessionID) - - req, err = http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) - query = req.URL.Query() - query.Add("email", "test@example.com") - req.URL.RawQuery = query.Encode() - assert.NoError(t, err) - emailExistsResp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailExistsResp.StatusCode) - - emailExistsResponse := *unittesting.HttpResponseToConsumableInformation(emailExistsResp.Body) - - assert.Equal(t, "OK", emailExistsResponse["status"]) - assert.True(t, emailExistsResponse["exists"].(bool)) -} - -func TestWithThirdPartyPasswordlessPhoneNumberExistsAPI(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/phonenumber/exists", nil) - query := req.URL.Query() - query.Add("phoneNumber", "+1234567890") - req.URL.RawQuery = query.Encode() - assert.NoError(t, err) - phoneNumberDoesNotExistResp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneNumberDoesNotExistResp.StatusCode) - - phoneNumberDoesNotExistResponse := *unittesting.HttpResponseToConsumableInformation(phoneNumberDoesNotExistResp.Body) - - assert.Equal(t, "OK", phoneNumberDoesNotExistResponse["status"]) - assert.False(t, phoneNumberDoesNotExistResponse["exists"].(bool)) - - codeInfo, err := CreateCodeWithPhoneNumber("public", "+1234567890", nil) - assert.NoError(t, err) - - ConsumeCodeWithLinkCode("public", codeInfo.OK.LinkCode, codeInfo.OK.PreAuthSessionID) - - req, err = http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/phonenumber/exists", nil) - query = req.URL.Query() - query.Add("phoneNumber", "+1234567890") - req.URL.RawQuery = query.Encode() - assert.NoError(t, err) - phoneNumberExistsResp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneNumberExistsResp.StatusCode) - - phoneNumberExistsResponse := *unittesting.HttpResponseToConsumableInformation(phoneNumberExistsResp.Body) - - assert.Equal(t, "OK", phoneNumberExistsResponse["status"]) - assert.True(t, phoneNumberExistsResponse["exists"].(bool)) -} - -func TestWithThirdPartyPasswordlessResendCodeAPI(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - codeInfo, err := CreateCodeWithPhoneNumber("public", "+1234567890", nil) - assert.NoError(t, err) - - codeResendPostData := map[string]interface{}{ - "deviceId": codeInfo.OK.DeviceID, - "preAuthSessionId": codeInfo.OK.PreAuthSessionID, - } - - codeResendPostBody, err := json.Marshal(codeResendPostData) - if err != nil { - t.Error(err.Error()) - } - - codeResendPostResp, err := http.Post(testServer.URL+"/auth/signinup/code/resend", "application/json", bytes.NewBuffer(codeResendPostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, codeResendPostResp.StatusCode) - - codeResendResult := *unittesting.HttpResponseToConsumableInformation(codeResendPostResp.Body) - assert.Equal(t, "OK", codeResendResult["status"]) - - codeResendPostData = map[string]interface{}{ - "deviceId": "codeInfo", - "preAuthSessionId": "PreAuthSessionID", - } - - codeResendPostBody, err = json.Marshal(codeResendPostData) - if err != nil { - t.Error(err.Error()) - } - - codeResendPostResp, err = http.Post(testServer.URL+"/auth/signinup/code/resend", "application/json", bytes.NewBuffer(codeResendPostBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, codeResendPostResp.StatusCode) - - codeResendResult = *unittesting.HttpResponseToConsumableInformation(codeResendPostResp.Body) - assert.Equal(t, "RESTART_FLOW_ERROR", codeResendResult["status"]) -} diff --git a/recipe/thirdpartypasswordless/authorizationUrlFeature_test.go b/recipe/thirdpartypasswordless/authorizationUrlFeature_test.go deleted file mode 100644 index 95d55450..00000000 --- a/recipe/thirdpartypasswordless/authorizationUrlFeature_test.go +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestWithThirdPartyPasswordlessMinimumConfigForThirdPartyModule(t *testing.T) { - antiCsrfVal := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &antiCsrfVal, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - customProvider1, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - resp, err := http.Get(testServer.URL + "/auth/authorisationurl?thirdPartyId=custom") - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - - fetchedUrl := result["urlWithQueryParams"].(string) - fetchedParsedUrl, err := url.Parse(fetchedUrl) - - assert.NoError(t, err) - assert.Equal(t, "test.com", fetchedParsedUrl.Host) - assert.Equal(t, "/oauth/auth", fetchedParsedUrl.Path) - assert.Equal(t, "test", fetchedParsedUrl.Query().Get("scope")) - assert.Equal(t, "supertokens", fetchedParsedUrl.Query().Get("client_id")) -} - -func TestWithThirdPartyPasswordlessThirdPartyProviderDoesNotExist(t *testing.T) { - antiCsrfVal := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &antiCsrfVal, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - customProvider1, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - resp, err := http.Get(testServer.URL + "/auth/authorisationurl?thirdPartyId=google") - assert.NoError(t, err) - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "the provider google could not be found in the configuration", result["message"]) -} diff --git a/recipe/thirdpartypasswordless/config_test.go b/recipe/thirdpartypasswordless/config_test.go deleted file mode 100644 index 2e3a5af1..00000000 --- a/recipe/thirdpartypasswordless/config_test.go +++ /dev/null @@ -1,906 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "errors" - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestMinimumConfigForThirdPartyPasswordlessWithEmailOrPhoneContactMethod(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - thirdPartyPasswordlessRecipe, err := GetRecipeInstanceOrThrowError() - assert.NoError(t, err) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", thirdPartyPasswordlessRecipe.Config.FlowType) - assert.NotNil(t, thirdPartyPasswordlessRecipe.thirdPartyRecipe) // thirdPartyRecipe must be created always -} - -func TestForThirdPartyPasswordLessCreateAndSendCustomTextMessageWithFlowTypeMagicLinkAndPhoneContactMethod(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin.UserInputCode == nil && input.PasswordlessLogin.UrlWithLinkCode != nil { - isUserInputCodeAndUrlWithLinkCodeValid = true - } - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "MAGIC_LINK", - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - phone := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneBody, err := json.Marshal(phone) - if err != nil { - t.Error(err.Error()) - } - - phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneResp.StatusCode) - - phoneDataInBytes, err := io.ReadAll(phoneResp.Body) - if err != nil { - t.Error(err.Error()) - } - phoneResp.Body.Close() - - var phoneResult map[string]interface{} - err = json.Unmarshal(phoneDataInBytes, &phoneResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", phoneResult["status"]) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestForThirdPartyPasswordlessCreateAndSendCustomMessageWithFlowTypeUserInputCodeAndMagicLinkAndPhoneContactMethod(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode != nil { - isUserInputCodeAndUrlWithLinkCodeValid = true - } - return nil - } - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - phone := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneBody, err := json.Marshal(phone) - if err != nil { - t.Error(err.Error()) - } - - phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, phoneResp.StatusCode) - - phoneDataInBytes, err := io.ReadAll(phoneResp.Body) - if err != nil { - t.Error(err.Error()) - } - phoneResp.Body.Close() - - var phoneResult map[string]interface{} - err = json.Unmarshal(phoneDataInBytes, &phoneResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", phoneResult["status"]) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestWithThirdPartyPasswordLessCreateAndSendCustomTextMessageIfErrorIsThrownItShouldReturnA500Error(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - isUserInputCodeAndUrlWithLinkCodeValid = true - return errors.New("test message") - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "MAGIC_LINK", - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - phone := map[string]interface{}{ - "phoneNumber": "+12345678901", - } - - phoneBody, err := json.Marshal(phone) - if err != nil { - t.Error(err.Error()) - } - - phoneResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(phoneBody)) - - assert.NoError(t, err) - assert.Equal(t, 500, phoneResp.StatusCode) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestWithThirdPartyPasswordLessMinimumConfigWithEmailContactMethod(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - thirdPartyPasswordlessRecipe, err := GetRecipeInstanceOrThrowError() - assert.NoError(t, err) - assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", thirdPartyPasswordlessRecipe.Config.FlowType) -} - -func TestWithThirdPartyPasswordlessIfValidateEmailAdressIsCalledWithContactMethod(t *testing.T) { - isValidateEmailAddressCalled := false - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - ValidateEmailAddress: func(email interface{}, tenantId string) *string { - isValidateEmailAddressCalled = true - return nil - }, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var emailResult map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &emailResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", emailResult["status"]) - assert.True(t, isValidateEmailAddressCalled) -} - -func TestWithThirdPartyPasswordlessIfValidateEmailAdressThrowsGenericErrorInCaseOfReturningAString(t *testing.T) { - isValidateEmailAddressCalled := false - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - ValidateEmailAddress: func(email interface{}, tenantId string) *string { - isValidateEmailAddressCalled = true - message := "test error" - return &message - }, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var emailResult map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &emailResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "GENERAL_ERROR", emailResult["status"]) - assert.Equal(t, "test error", emailResult["message"]) - assert.True(t, isValidateEmailAddressCalled) -} - -func TestForThirdPartyPasswordlessCreateAndSendCustomEmailWithFlowTypeUserInputCodeAndEmailContactMethod(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode == nil { - isUserInputCodeAndUrlWithLinkCodeValid = true - } - return nil - - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var emailResult map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &emailResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", emailResult["status"]) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestWithThirdPartyPasswordlessCreateAndSendCustomEmailWithFlowTypeMagicLinkAndEmailContactMethod(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin.UserInputCode == nil && input.PasswordlessLogin.UrlWithLinkCode != nil { - isUserInputCodeAndUrlWithLinkCodeValid = true - } - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var emailResult map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &emailResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", emailResult["status"]) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestWithThirdPartyPasswordlessCreateAndSendCustomEmailWithFlowTypeUserInputCodeAndMagicLinkAndEmailContactMethod(t *testing.T) { - isUserInputCodeAndUrlWithLinkCodeValid := false - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin.UserInputCode != nil && input.PasswordlessLogin.UrlWithLinkCode != nil { - isUserInputCodeAndUrlWithLinkCodeValid = true - } - return nil - } - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, emailResp.StatusCode) - - emailDataInBytes, err := io.ReadAll(emailResp.Body) - if err != nil { - t.Error(err.Error()) - } - emailResp.Body.Close() - - var emailResult map[string]interface{} - err = json.Unmarshal(emailDataInBytes, &emailResult) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", emailResult["status"]) - assert.True(t, isUserInputCodeAndUrlWithLinkCodeValid) -} - -func TestForThirdPartyPasswordLessThatForCreateAndCustomEmailIfErrorIsThrownTheStatusInTheResponseShouldBeA500Error(t *testing.T) { - isCreateAndSendCustomEmailCalled := false - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - isCreateAndSendCustomEmailCalled = true - return errors.New("test message") - } - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - email := map[string]interface{}{ - "email": "test@example.com", - } - - emailBody, err := json.Marshal(email) - if err != nil { - t.Error(err.Error()) - } - - emailResp, err := http.Post(testServer.URL+"/auth/signinup/code", "application/json", bytes.NewBuffer(emailBody)) - - assert.NoError(t, err) - assert.Equal(t, 500, emailResp.StatusCode) - assert.True(t, isCreateAndSendCustomEmailCalled) -} From 325bfae810f25863ae75b27c384c3ab8e1649143 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 10 Apr 2024 14:36:30 +0530 Subject: [PATCH 05/19] more test transfers --- recipe/thirdparty/override_test.go | 342 +++++ recipe/thirdparty/provider_test.go | 462 ++++++- .../thirdpartypasswordless/deleteUser_test.go | 223 --- .../getUserByEmailFeature_test.go | 137 -- .../thirdpartypasswordless/override_test.go | 367 ----- .../thirdpartypasswordless/provider_test.go | 1207 ----------------- 6 files changed, 803 insertions(+), 1935 deletions(-) delete mode 100644 recipe/thirdpartypasswordless/deleteUser_test.go delete mode 100644 recipe/thirdpartypasswordless/getUserByEmailFeature_test.go delete mode 100644 recipe/thirdpartypasswordless/override_test.go delete mode 100644 recipe/thirdpartypasswordless/provider_test.go diff --git a/recipe/thirdparty/override_test.go b/recipe/thirdparty/override_test.go index 72b31451..ae992bcc 100644 --- a/recipe/thirdparty/override_test.go +++ b/recipe/thirdparty/override_test.go @@ -26,6 +26,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/supertokens/supertokens-golang/recipe/passwordless" + "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" @@ -34,6 +36,346 @@ import ( "gopkg.in/h2non/gock.v1" ) +func TestOverridingAPIs(t *testing.T) { + var userRef *tpmodels.User + var newUser bool + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + passwordless.Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{customProvider1}, + }, + Override: &tpmodels.OverrideStruct{ + APIs: func(originalImplementation tpmodels.APIInterface) tpmodels.APIInterface { + originalThirdPartySignInUpPost := *originalImplementation.SignInUpPOST + *originalImplementation.SignInUpPOST = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.SignInUpPOSTResponse, error) { + resp, err := originalThirdPartySignInUpPost(provider, input, tenantId, options, userContext) + userRef = &resp.OK.User + newUser = resp.OK.CreatedNewUser + return resp, err + } + return originalImplementation + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + + mux.HandleFunc("/user", func(rw http.ResponseWriter, r *http.Request) { + userId := r.URL.Query().Get("userId") + fetchedUser, err := GetUserByID(userId) + if err != nil { + t.Error(err.Error()) + } + jsonResp, err := json.Marshal(fetchedUser) + if err != nil { + t.Errorf("Error happened in JSON marshal. Err: %s", err) + } + rw.WriteHeader(200) + rw.Write(jsonResp) + }) + + defer gock.OffAll() + gock.New("https://test.com"). + Post("/oauth/token"). + Persist(). + Reply(200). + JSON(map[string]string{}) + + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + formFields := map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": testServer.URL + "/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err := json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + gock.New(testServer.URL).EnableNetworking().Persist() + gock.New("http://localhost:8080/").EnableNetworking().Persist() + + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + signUpResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) + fetchedUser := signUpResponse["user"].(map[string]interface{}) + + assert.NotNil(t, userRef) + assert.True(t, newUser) + assert.Equal(t, fetchedUser["email"], userRef.Email) + assert.Equal(t, fetchedUser["id"], userRef.ID) + assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) + assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) + + userRef = nil + assert.Nil(t, userRef) + + formFields = map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": testServer.URL + "/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err = json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + resp, err = http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + signInResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) + fetchedUserFromSignIn := signInResponse["user"].(map[string]interface{}) + + assert.NotNil(t, userRef) + assert.False(t, newUser) + assert.Equal(t, fetchedUserFromSignIn["email"], userRef.Email) + assert.Equal(t, fetchedUserFromSignIn["id"], userRef.ID) + assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) + assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) +} + +func TestOverridingFunctions(t *testing.T) { + var userRef *tpmodels.User + var newUser bool + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + passwordless.Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{customProvider1}, + }, + Override: &tpmodels.OverrideStruct{ + Functions: func(originalImplementation tpmodels.RecipeInterface) tpmodels.RecipeInterface { + originalThirdPartySignInUp := *originalImplementation.SignInUp + *originalImplementation.SignInUp = func(thirdPartyID, thirdPartyUserID, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) { + resp, err := originalThirdPartySignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) + userRef = &resp.OK.User + newUser = resp.OK.CreatedNewUser + return resp, err + } + originalGetUserById := *originalImplementation.GetUserByID + *originalImplementation.GetUserByID = func(userID string, userContext supertokens.UserContext) (*tpmodels.User, error) { + resp, err := originalGetUserById(userID, userContext) + userRef = resp + return resp, err + } + return originalImplementation + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + + mux.HandleFunc("/user", func(rw http.ResponseWriter, r *http.Request) { + userId := r.URL.Query().Get("userId") + fetchedUser, err := GetUserByID(userId) + if err != nil { + t.Error(err.Error()) + } + jsonResp, err := json.Marshal(fetchedUser) + if err != nil { + t.Errorf("Error happened in JSON marshal. Err: %s", err) + } + rw.WriteHeader(200) + rw.Write(jsonResp) + }) + + defer gock.OffAll() + gock.New("https://test.com"). + Post("/oauth/token"). + Persist(). + Reply(200). + JSON(map[string]string{}) + + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + formFields := map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": testServer.URL + "/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err := json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + gock.New(testServer.URL).EnableNetworking().Persist() + gock.New("http://localhost:8080/").EnableNetworking().Persist() + + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + signUpResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) + fetchedUser := signUpResponse["user"].(map[string]interface{}) + + assert.NotNil(t, userRef) + assert.True(t, newUser) + assert.Equal(t, fetchedUser["email"], userRef.Email) + assert.Equal(t, fetchedUser["id"], userRef.ID) + assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) + assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) + + userRef = nil + assert.Nil(t, userRef) + + formFields = map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": testServer.URL + "/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err = json.Marshal(formFields) + if err != nil { + t.Error(err.Error()) + } + + resp, err = http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + signInResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) + fetchedUserFromSignIn := signInResponse["user"].(map[string]interface{}) + + assert.NotNil(t, userRef) + assert.False(t, newUser) + assert.Equal(t, fetchedUserFromSignIn["email"], userRef.Email) + assert.Equal(t, fetchedUserFromSignIn["id"], userRef.ID) + assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) + assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) + + userRef = nil + assert.Nil(t, userRef) + + req, err := http.NewRequest(http.MethodPost, testServer.URL+"/user", nil) + assert.NoError(t, err) + + query := req.URL.Query() + query.Add("userId", fetchedUserFromSignIn["id"].(string)) + req.URL.RawQuery = query.Encode() + + res, err := http.DefaultClient.Do(req) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, res.StatusCode) + + userByIdResponse := *unittesting.HttpResponseToConsumableInformation(res.Body) + + assert.NotNil(t, userRef) + assert.Equal(t, userByIdResponse["email"], userRef.Email) + assert.Nil(t, userByIdResponse["phoneNumber"]) + assert.Equal(t, userByIdResponse["id"], userRef.ID) + assert.Equal(t, userByIdResponse["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) + assert.Equal(t, userByIdResponse["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) +} + func TestOverrideFunctions(t *testing.T) { var createdNewUser bool var user tpmodels.User diff --git a/recipe/thirdparty/provider_test.go b/recipe/thirdparty/provider_test.go index 73b1f82b..0549e927 100644 --- a/recipe/thirdparty/provider_test.go +++ b/recipe/thirdparty/provider_test.go @@ -19,7 +19,6 @@ package thirdparty import ( "encoding/json" "errors" - "github.com/supertokens/supertokens-golang/recipe/session" "io" "io/ioutil" "net" @@ -29,6 +28,9 @@ import ( "strings" "testing" + "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens" @@ -36,6 +38,408 @@ import ( "gopkg.in/h2non/gock.v1" ) +const privateKey = "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----" + +func TestWithAdditionalParamsCheckTheyArePresentInAuthorizationURLForThirdPartyProviderApple(t *testing.T) { + clientId := "test" + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: clientId, + AdditionalConfig: map[string]interface{}{ + "keyId": "test-key", + "privateKey": privateKey, + "teamId": "test-team-id", + }, + }, + }, + AuthorizationEndpointQueryParams: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + }, + }, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + providerRes, err := GetProvider("public", "apple", nil) + assert.NoError(t, err) + + providerInfo := providerRes + + assert.Equal(t, "apple", providerInfo.ID) + + assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) + assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) + + authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) + assert.NoError(t, err) + + urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) + assert.NoError(t, err) + + authParams := urlObj.Query() + + assert.Equal(t, url.Values{ + "client_id": {"test"}, + "response_mode": {"form_post"}, + "response_type": {"code"}, + "redirect_uri": {"redirect"}, + "scope": {"openid email"}, + "key1": {"value1"}, + "key2": {"value2"}, + }, authParams) +} + +func TestWithPassingScopesInConfigForThirdPartyProviderApple(t *testing.T) { + clientId := "test" + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: clientId, + Scope: []string{"test-scope-1", "test-scope-2"}, + AdditionalConfig: map[string]interface{}{ + "keyId": "test-key", + "privateKey": privateKey, + "teamId": "test-team-id", + }, + }, + }, + }, + }, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + providerRes, err := GetProvider("public", "apple", nil) + assert.NoError(t, err) + + providerInfo := providerRes + + assert.Equal(t, "apple", providerInfo.ID) + + assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) + assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) + + authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) + assert.NoError(t, err) + + urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) + assert.NoError(t, err) + + authParams := urlObj.Query() + + assert.Equal(t, url.Values{ + "client_id": {"test"}, + "response_mode": {"form_post"}, + "response_type": {"code"}, + "redirect_uri": {"redirect"}, + "scope": {"test-scope-1 test-scope-2"}, + }, authParams) +} + +func TestWithMinimumConfigForThirdPartyProviderApple(t *testing.T) { + clientId := "test" + + 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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: clientId, + AdditionalConfig: map[string]interface{}{ + "keyId": "test-key", + "privateKey": privateKey, + "teamId": "test-team-id", + }, + }, + }, + }, + }, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + providerRes, err := GetProvider("public", "apple", nil) + assert.NoError(t, err) + + providerInfo := providerRes + + assert.Equal(t, "apple", providerInfo.ID) + + assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) + assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) + + authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) + assert.NoError(t, err) + + urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) + assert.NoError(t, err) + + authParams := urlObj.Query() + + assert.Equal(t, url.Values{ + "client_id": {"test"}, + "response_mode": {"form_post"}, + "response_type": {"code"}, + "redirect_uri": {"redirect"}, + "scope": {"openid email"}, + }, authParams) + + tokenParams := url.Values{} + + defer gock.OffAll() + gock.New("https://appleid.apple.com"). + Post("/auth/token"). + Persist(). + Map(func(r *http.Request) *http.Request { + data, err := ioutil.ReadAll(r.Body) + assert.NoError(t, err) + tokenParams, err = url.ParseQuery(string(data)) + assert.NoError(t, err) + return r + }). + Reply(200). + JSON(map[string]string{ + "id_token": "abcd", + }) + + _, err = providerInfo.ExchangeAuthCodeForOAuthTokens(tpmodels.TypeRedirectURIInfo{ + RedirectURIOnProviderDashboard: "redirect", + RedirectURIQueryParams: map[string]interface{}{ + "code": "abcd", + }, + }, &map[string]interface{}{}) + assert.NoError(t, err) + + assert.NotEmpty(t, tokenParams.Get("client_secret")) + tokenParams.Del("client_secret") + + assert.Equal(t, url.Values{ + "client_id": {"test"}, + "grant_type": {"authorization_code"}, + "code": {"abcd"}, + "redirect_uri": {"redirect"}, + }, tokenParams) +} + +func TestPassingAdditionalParamsCheckTheyArePresentInAuthorizationUrlForThirdPartyProviderGoogle(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "test", + ClientSecret: "test-secret", + }, + }, + AuthorizationEndpointQueryParams: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + }, + }, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + providerRes, err := GetProvider("public", "google", nil) + assert.NoError(t, err) + + providerInfo := providerRes + assert.Equal(t, "google", providerInfo.ID) + + assert.Equal(t, "https://oauth2.googleapis.com/token", providerInfo.Config.TokenEndpoint) + assert.Equal(t, "https://accounts.google.com/o/oauth2/v2/auth", providerInfo.Config.AuthorizationEndpoint) + assert.Equal(t, "https://openidconnect.googleapis.com/v1/userinfo", providerInfo.Config.UserInfoEndpoint) + + authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) + assert.NoError(t, err) + + urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) + assert.NoError(t, err) + + authParams := urlObj.Query() + + assert.Equal(t, url.Values{ + "client_id": {"test"}, + "access_type": {"offline"}, + "include_granted_scopes": {"true"}, + "response_type": {"code"}, + "redirect_uri": {"redirect"}, + "scope": {"openid email"}, + "key1": {"value1"}, + "key2": {"value2"}, + }, authParams) +} + func TestMinimumConfigForGoogleAsThirdPartyProvider(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ @@ -901,3 +1305,59 @@ func TestThatSignInUpWorksIfValidateAccessTokenDoesNotReturnError(t *testing.T) assert.True(t, overrideValidateCalled) assert.Equal(t, response["status"], "OK") } + +func TestWithDuplicateProvider(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "test", + ClientSecret: "test-secret", + }, + }, + }, + }, + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "test", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + assert.Equal(t, "The providers array has multiple entries for the same third party provider.", err.Error()) + } +} diff --git a/recipe/thirdpartypasswordless/deleteUser_test.go b/recipe/thirdpartypasswordless/deleteUser_test.go deleted file mode 100644 index 77faed48..00000000 --- a/recipe/thirdpartypasswordless/deleteUser_test.go +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestDeletePhoneNumber(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(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - 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()) - } - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.11", cdiVersion) == cdiVersion { - res, err := PasswordlessSignInUpByEmail("public", "test@example.com") - if err != nil { - t.Error(err.Error()) - } - phoneNumber := "+1234567890" - _, err = UpdatePasswordlessUser(res.User.ID, nil, &phoneNumber) - if err != nil { - t.Error(err.Error()) - } - deleteResponse, err := DeletePhoneNumberForUser(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.NotNil(t, deleteResponse.OK) - - userInfo, err := GetUserByID(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.Nil(t, userInfo.PhoneNumber) - } -} - -func TestDeleteEmail(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(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - 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()) - } - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.11", cdiVersion) == cdiVersion { - res, err := PasswordlessSignInUpByEmail("public", "test@example.com") - if err != nil { - t.Error(err.Error()) - } - phoneNumber := "+1234567890" - _, err = UpdatePasswordlessUser(res.User.ID, nil, &phoneNumber) - if err != nil { - t.Error(err.Error()) - } - deleteResponse, err := DeleteEmailForPasswordlessUser(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.NotNil(t, deleteResponse.OK) - - userInfo, err := GetUserByID(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.Nil(t, userInfo.Email) - } -} - -func TestDeleteEmailAndPhoneShouldThrowError(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(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - 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()) - } - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.11", cdiVersion) == cdiVersion { - res, err := PasswordlessSignInUpByEmail("public", "test@example.com") - if err != nil { - t.Error(err.Error()) - } - phoneNumber := "+1234567890" - _, err = UpdatePasswordlessUser(res.User.ID, nil, &phoneNumber) - if err != nil { - t.Error(err.Error()) - } - deleteResponse, err := DeleteEmailForPasswordlessUser(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.NotNil(t, deleteResponse.OK) - - userInfo, err := GetUserByID(res.User.ID) - if err != nil { - t.Error(err.Error()) - } - assert.Nil(t, userInfo.Email) - - _, err = DeletePhoneNumberForUser(res.User.ID) - assert.NotNil(t, err) - assert.Equal(t, err.Error(), "SuperTokens core threw an error for a request to path: '/recipe/user' with status code: 400 and message: You cannot clear both email and phone number of a user\n") - } -} diff --git a/recipe/thirdpartypasswordless/getUserByEmailFeature_test.go b/recipe/thirdpartypasswordless/getUserByEmailFeature_test.go deleted file mode 100644 index 4e499721..00000000 --- a/recipe/thirdpartypasswordless/getUserByEmailFeature_test.go +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestInvalidEmailYieldsEmptyUsersArray(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(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - mockThirdPartyProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - users, err := GetUsersByEmail("public", "john.doe@example.com") - assert.NoError(t, err) - assert.Equal(t, 0, len(users)) -} - -func TestValidEmailYieldsThirdPartyUsers(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(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - mockThirdPartyProvider1, - mockThirdPartyProvider2, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - ThirdPartyManuallyCreateOrUpdateUser("public", "mock1", "thirdPartyJohnDoe", "john.doe@example.com") - ThirdPartyManuallyCreateOrUpdateUser("public", "mock2", "thirdPartyJohnDoe", "john.doe@example.com") - - users, err := GetUsersByEmail("public", "john.doe@example.com") - assert.NoError(t, err) - assert.Equal(t, 2, len(users)) - - for _, u := range users { - assert.Equal(t, "john.doe@example.com", *u.Email) - assert.Equal(t, "thirdPartyJohnDoe", u.ThirdParty.UserID) - assert.NotNil(t, u.ID) - assert.NotNil(t, u.TimeJoined) - assert.NotNil(t, u.ThirdParty.ID) - assert.Nil(t, u.PhoneNumber) - } -} diff --git a/recipe/thirdpartypasswordless/override_test.go b/recipe/thirdpartypasswordless/override_test.go deleted file mode 100644 index 605eea36..00000000 --- a/recipe/thirdpartypasswordless/override_test.go +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" -) - -func TestOverridingFunctions(t *testing.T) { - var userRef *tplmodels.User - var newUser bool - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{customProvider1}, - Override: &tplmodels.OverrideStruct{ - Functions: func(originalImplementation tplmodels.RecipeInterface) tplmodels.RecipeInterface { - originalThirdPartySignInUp := *originalImplementation.ThirdPartySignInUp - *originalImplementation.ThirdPartySignInUp = func(thirdPartyID, thirdPartyUserID, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUp, error) { - resp, err := originalThirdPartySignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) - userRef = &resp.OK.User - newUser = resp.OK.CreatedNewUser - return resp, err - } - originalGetUserById := *originalImplementation.GetUserByID - *originalImplementation.GetUserByID = func(userID string, userContext supertokens.UserContext) (*tplmodels.User, error) { - resp, err := originalGetUserById(userID, userContext) - userRef = resp - return resp, err - } - return originalImplementation - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - - mux.HandleFunc("/user", func(rw http.ResponseWriter, r *http.Request) { - userId := r.URL.Query().Get("userId") - fetchedUser, err := GetUserByID(userId) - if err != nil { - t.Error(err.Error()) - } - jsonResp, err := json.Marshal(fetchedUser) - if err != nil { - t.Errorf("Error happened in JSON marshal. Err: %s", err) - } - rw.WriteHeader(200) - rw.Write(jsonResp) - }) - - defer gock.OffAll() - gock.New("https://test.com"). - Post("/oauth/token"). - Persist(). - Reply(200). - JSON(map[string]string{}) - - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - formFields := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": testServer.URL + "/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(formFields) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - signUpResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) - fetchedUser := signUpResponse["user"].(map[string]interface{}) - - assert.NotNil(t, userRef) - assert.True(t, newUser) - assert.Equal(t, fetchedUser["email"], *userRef.Email) - assert.Equal(t, fetchedUser["id"], userRef.ID) - assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) - assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) - - userRef = nil - assert.Nil(t, userRef) - - formFields = map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": testServer.URL + "/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err = json.Marshal(formFields) - if err != nil { - t.Error(err.Error()) - } - - resp, err = http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - signInResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) - fetchedUserFromSignIn := signInResponse["user"].(map[string]interface{}) - - assert.NotNil(t, userRef) - assert.False(t, newUser) - assert.Equal(t, fetchedUserFromSignIn["email"], *userRef.Email) - assert.Equal(t, fetchedUserFromSignIn["id"], userRef.ID) - assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) - assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) - - userRef = nil - assert.Nil(t, userRef) - - req, err := http.NewRequest(http.MethodPost, testServer.URL+"/user", nil) - assert.NoError(t, err) - - query := req.URL.Query() - query.Add("userId", fetchedUserFromSignIn["id"].(string)) - req.URL.RawQuery = query.Encode() - - res, err := http.DefaultClient.Do(req) - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, res.StatusCode) - - userByIdResponse := *unittesting.HttpResponseToConsumableInformation(res.Body) - - assert.NotNil(t, userRef) - assert.Equal(t, userByIdResponse["email"], *userRef.Email) - assert.Nil(t, userByIdResponse["phoneNumber"]) - assert.Equal(t, userByIdResponse["id"], userRef.ID) - assert.Equal(t, userByIdResponse["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) - assert.Equal(t, userByIdResponse["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) -} - -func TestOverridingAPIs(t *testing.T) { - var userRef *tplmodels.User - var newUser bool - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{customProvider1}, - Override: &tplmodels.OverrideStruct{ - APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - originalThirdPartySignInUpPost := *originalImplementation.ThirdPartySignInUpPOST - *originalImplementation.ThirdPartySignInUpPOST = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUpPOSTResponse, error) { - resp, err := originalThirdPartySignInUpPost(provider, input, tenantId, options, userContext) - userRef = &resp.OK.User - newUser = resp.OK.CreatedNewUser - return resp, err - } - return originalImplementation - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - - mux.HandleFunc("/user", func(rw http.ResponseWriter, r *http.Request) { - userId := r.URL.Query().Get("userId") - fetchedUser, err := GetUserByID(userId) - if err != nil { - t.Error(err.Error()) - } - jsonResp, err := json.Marshal(fetchedUser) - if err != nil { - t.Errorf("Error happened in JSON marshal. Err: %s", err) - } - rw.WriteHeader(200) - rw.Write(jsonResp) - }) - - defer gock.OffAll() - gock.New("https://test.com"). - Post("/oauth/token"). - Persist(). - Reply(200). - JSON(map[string]string{}) - - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - formFields := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": testServer.URL + "/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(formFields) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - signUpResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) - fetchedUser := signUpResponse["user"].(map[string]interface{}) - - assert.NotNil(t, userRef) - assert.True(t, newUser) - assert.Equal(t, fetchedUser["email"], *userRef.Email) - assert.Equal(t, fetchedUser["id"], userRef.ID) - assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) - assert.Equal(t, fetchedUser["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) - - userRef = nil - assert.Nil(t, userRef) - - formFields = map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": testServer.URL + "/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err = json.Marshal(formFields) - if err != nil { - t.Error(err.Error()) - } - - resp, err = http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - signInResponse := *unittesting.HttpResponseToConsumableInformation(resp.Body) - fetchedUserFromSignIn := signInResponse["user"].(map[string]interface{}) - - assert.NotNil(t, userRef) - assert.False(t, newUser) - assert.Equal(t, fetchedUserFromSignIn["email"], *userRef.Email) - assert.Equal(t, fetchedUserFromSignIn["id"], userRef.ID) - assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["id"], userRef.ThirdParty.ID) - assert.Equal(t, fetchedUserFromSignIn["thirdParty"].(map[string]interface{})["userId"], userRef.ThirdParty.UserID) -} diff --git a/recipe/thirdpartypasswordless/provider_test.go b/recipe/thirdpartypasswordless/provider_test.go deleted file mode 100644 index 57ab59c0..00000000 --- a/recipe/thirdpartypasswordless/provider_test.go +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "io/ioutil" - "net/http" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" -) - -const privateKey = "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----" - -func TestForThirdPartyPasswordlessTheMinimumConfigForThirdPartyProviderGoogle(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "google", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "google", providerInfo.ID) - - assert.Equal(t, "https://accounts.google.com/o/oauth2/v2/auth", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://oauth2.googleapis.com/token", providerInfo.Config.TokenEndpoint) - assert.Equal(t, "https://openidconnect.googleapis.com/v1/userinfo", providerInfo.Config.UserInfoEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "access_type": {"offline"}, - "include_granted_scopes": {"true"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"openid email"}, - }, authParams) - - tokenParams := url.Values{} - - defer gock.OffAll() - gock.New("https://oauth2.googleapis.com"). - Post("/token"). - Persist(). - Map(func(r *http.Request) *http.Request { - data, err := ioutil.ReadAll(r.Body) - assert.NoError(t, err) - tokenParams, err = url.ParseQuery(string(data)) - assert.NoError(t, err) - return r - }). - Reply(200). - JSON(map[string]string{ - "access_token": "abcd", - }) - - _, err = providerInfo.ExchangeAuthCodeForOAuthTokens(tpmodels.TypeRedirectURIInfo{ - RedirectURIOnProviderDashboard: "redirect", - RedirectURIQueryParams: map[string]interface{}{ - "code": "abcd", - }, - }, &map[string]interface{}{}) - assert.NoError(t, err) - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "client_secret": {"test-secret"}, - "grant_type": {"authorization_code"}, - "code": {"abcd"}, - "redirect_uri": {"redirect"}, - }, tokenParams) -} - -func TestWithThirdPartyPasswordlessPassingAdditionalParamsCheckTheyArePresentInAuthorizationUrlForThirdPartyProviderGoogle(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - AuthorizationEndpointQueryParams: map[string]interface{}{ - "key1": "value1", - "key2": "value2", - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "google", nil) - assert.NoError(t, err) - - providerInfo := providerRes - assert.Equal(t, "google", providerInfo.ID) - - assert.Equal(t, "https://oauth2.googleapis.com/token", providerInfo.Config.TokenEndpoint) - assert.Equal(t, "https://accounts.google.com/o/oauth2/v2/auth", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://openidconnect.googleapis.com/v1/userinfo", providerInfo.Config.UserInfoEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "access_type": {"offline"}, - "include_granted_scopes": {"true"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"openid email"}, - "key1": {"value1"}, - "key2": {"value2"}, - }, authParams) -} - -func TestForThirdpartyPasswordlessPassingScopesInConfigForThirdpartyProviderGoogle(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - Scope: []string{"test-scope-1", "test-scope-2"}, - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "google", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "google", providerInfo.ID) - - assert.Equal(t, "https://accounts.google.com/o/oauth2/v2/auth", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://oauth2.googleapis.com/token", providerInfo.Config.TokenEndpoint) - assert.Equal(t, "https://openidconnect.googleapis.com/v1/userinfo", providerInfo.Config.UserInfoEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "access_type": {"offline"}, - "include_granted_scopes": {"true"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"test-scope-1 test-scope-2"}, - }, authParams) -} - -func TestForThirdPartyPasswordlessMinimumConfigForThirdPartyProviderFacebook(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "facebook", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "facebook", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "facebook", providerInfo.ID) - - assert.Equal(t, "https://graph.facebook.com/v12.0/oauth/access_token", providerInfo.Config.TokenEndpoint) - assert.Equal(t, "https://www.facebook.com/v12.0/dialog/oauth", providerInfo.Config.AuthorizationEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"email"}, - }, authParams) - - tokenParams := url.Values{} - - defer gock.OffAll() - gock.New("https://graph.facebook.com"). - Post("/v12.0/oauth/access_token"). - Persist(). - Map(func(r *http.Request) *http.Request { - data, err := ioutil.ReadAll(r.Body) - assert.NoError(t, err) - tokenParams, err = url.ParseQuery(string(data)) - assert.NoError(t, err) - return r - }). - Reply(200). - JSON(map[string]string{ - "access_token": "abcd", - }) - - _, err = providerInfo.ExchangeAuthCodeForOAuthTokens(tpmodels.TypeRedirectURIInfo{ - RedirectURIOnProviderDashboard: "redirect", - RedirectURIQueryParams: map[string]interface{}{ - "code": "abcd", - }, - }, &map[string]interface{}{}) - assert.NoError(t, err) - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "client_secret": {"test-secret"}, - "grant_type": {"authorization_code"}, - "code": {"abcd"}, - "redirect_uri": {"redirect"}, - }, tokenParams) -} - -func TestWithThirdPartyPasswordlessPassingScopesInConfigForThirdPartyProviderFacebook(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "facebook", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - Scope: []string{"test-scope-1", "test-scope-2"}, - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "facebook", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "facebook", providerInfo.ID) - - assert.Equal(t, "https://graph.facebook.com/v12.0/oauth/access_token", providerInfo.Config.TokenEndpoint) - assert.Equal(t, "https://www.facebook.com/v12.0/dialog/oauth", providerInfo.Config.AuthorizationEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"test-scope-1 test-scope-2"}, - }, authParams) -} - -func TestWithThirdPartyPasswordlessMinimumConfigForThirdPartyProviderGithub(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "github", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "github", providerInfo.ID) - - assert.Equal(t, "https://github.com/login/oauth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://github.com/login/oauth/access_token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"read:user user:email"}, - }, authParams) - - tokenParams := url.Values{} - - defer gock.OffAll() - gock.New("https://github.com"). - Post("/login/oauth/access_token"). - Persist(). - Map(func(r *http.Request) *http.Request { - data, err := ioutil.ReadAll(r.Body) - assert.NoError(t, err) - tokenParams, err = url.ParseQuery(string(data)) - assert.NoError(t, err) - return r - }). - Reply(200). - JSON(map[string]string{ - "access_token": "abcd", - }) - - _, err = providerInfo.ExchangeAuthCodeForOAuthTokens(tpmodels.TypeRedirectURIInfo{ - RedirectURIOnProviderDashboard: "redirect", - RedirectURIQueryParams: map[string]interface{}{ - "code": "abcd", - }, - }, &map[string]interface{}{}) - assert.NoError(t, err) - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "client_secret": {"test-secret"}, - "grant_type": {"authorization_code"}, - "code": {"abcd"}, - "redirect_uri": {"redirect"}, - }, tokenParams) -} - -func TestWithThirdPartyPasswordlessParamCheckTheyArePresentInAuthorizationURLForThirdPartyProviderGithub(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - AuthorizationEndpointQueryParams: map[string]interface{}{ - "key1": "value1", - "key2": "value2", - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "github", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "github", providerInfo.ID) - - assert.Equal(t, "https://github.com/login/oauth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://github.com/login/oauth/access_token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"read:user user:email"}, - "key1": {"value1"}, - "key2": {"value2"}, - }, authParams) -} - -func TestWithThirdPartyPasswordlessPassingScopesInConfigForThirdPartyProviderGithub(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - Scope: []string{"test-scope-1", "test-scope-2"}, - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "github", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "github", providerInfo.ID) - - assert.Equal(t, "https://github.com/login/oauth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://github.com/login/oauth/access_token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"test-scope-1 test-scope-2"}, - }, authParams) -} - -func TestWithThirdPartyPasswordlessMinimumConfigForThirdPartyProviderApple(t *testing.T) { - clientId := "test" - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: clientId, - AdditionalConfig: map[string]interface{}{ - "keyId": "test-key", - "privateKey": privateKey, - "teamId": "test-team-id", - }, - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "apple", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "apple", providerInfo.ID) - - assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_mode": {"form_post"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"openid email"}, - }, authParams) - - tokenParams := url.Values{} - - defer gock.OffAll() - gock.New("https://appleid.apple.com"). - Post("/auth/token"). - Persist(). - Map(func(r *http.Request) *http.Request { - data, err := ioutil.ReadAll(r.Body) - assert.NoError(t, err) - tokenParams, err = url.ParseQuery(string(data)) - assert.NoError(t, err) - return r - }). - Reply(200). - JSON(map[string]string{ - "id_token": "abcd", - }) - - _, err = providerInfo.ExchangeAuthCodeForOAuthTokens(tpmodels.TypeRedirectURIInfo{ - RedirectURIOnProviderDashboard: "redirect", - RedirectURIQueryParams: map[string]interface{}{ - "code": "abcd", - }, - }, &map[string]interface{}{}) - assert.NoError(t, err) - - assert.NotEmpty(t, tokenParams.Get("client_secret")) - tokenParams.Del("client_secret") - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "grant_type": {"authorization_code"}, - "code": {"abcd"}, - "redirect_uri": {"redirect"}, - }, tokenParams) -} - -func TestWithThirdPartyPasswordlessPassingAdditionalParamsCheckTheyArePresentInAuthorizationURLForThirdPartyProviderApple(t *testing.T) { - clientId := "test" - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: clientId, - AdditionalConfig: map[string]interface{}{ - "keyId": "test-key", - "privateKey": privateKey, - "teamId": "test-team-id", - }, - }, - }, - AuthorizationEndpointQueryParams: map[string]interface{}{ - "key1": "value1", - "key2": "value2", - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "apple", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "apple", providerInfo.ID) - - assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_mode": {"form_post"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"openid email"}, - "key1": {"value1"}, - "key2": {"value2"}, - }, authParams) -} - -func TestWithThirdPartyProviderPasswordlessPassingScopesInConfigForThirdPartyProviderApple(t *testing.T) { - clientId := "test" - - 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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: clientId, - Scope: []string{"test-scope-1", "test-scope-2"}, - AdditionalConfig: map[string]interface{}{ - "keyId": "test-key", - "privateKey": privateKey, - "teamId": "test-team-id", - }, - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - providerRes, err := ThirdPartyGetProvider("public", "apple", nil) - assert.NoError(t, err) - - providerInfo := providerRes - - assert.Equal(t, "apple", providerInfo.ID) - - assert.Equal(t, "https://appleid.apple.com/auth/authorize", providerInfo.Config.AuthorizationEndpoint) - assert.Equal(t, "https://appleid.apple.com/auth/token", providerInfo.Config.TokenEndpoint) - - authUrlRes, err := providerInfo.GetAuthorisationRedirectURL("redirect", &map[string]interface{}{}) - assert.NoError(t, err) - - urlObj, err := url.Parse(authUrlRes.URLWithQueryParams) - assert.NoError(t, err) - - authParams := urlObj.Query() - - assert.Equal(t, url.Values{ - "client_id": {"test"}, - "response_mode": {"form_post"}, - "response_type": {"code"}, - "redirect_uri": {"redirect"}, - "scope": {"test-scope-1 test-scope-2"}, - }, authParams) -} - -func TestWithThirdPartyPasswordlessDuplicateProvider(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - assert.Equal(t, "The providers array has multiple entries for the same third party provider.", err.Error()) - } -} From 102b63a193f3aa4bc24b9db3d83e262ef9f8f8b5 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 10 Apr 2024 14:55:57 +0530 Subject: [PATCH 06/19] moves more code around --- recipe/passwordless/recipeFucntions_test.go | 169 +++ recipe/thirdparty/signinupFeature_test.go | 69 + .../recipeFunctions_test.go | 1150 ----------------- 3 files changed, 238 insertions(+), 1150 deletions(-) delete mode 100644 recipe/thirdpartypasswordless/recipeFunctions_test.go diff --git a/recipe/passwordless/recipeFucntions_test.go b/recipe/passwordless/recipeFucntions_test.go index 44fde356..99ae9f6d 100644 --- a/recipe/passwordless/recipeFucntions_test.go +++ b/recipe/passwordless/recipeFucntions_test.go @@ -22,6 +22,8 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/supertokens/supertokens-golang/recipe/emailverification" + "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" @@ -29,6 +31,173 @@ import ( "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestWithThirdPartyPasswordlessGetUserFunctionality(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + user, err := GetUserByID("random") + assert.NoError(t, err) + assert.Nil(t, user) + + resp, err := SignInUpByEmail("public", "test@example.com") + assert.NoError(t, err) + userId := resp.User.ID + + user, err = GetUserByID(userId) + assert.NoError(t, err) + assert.NotNil(t, user) + + assert.Equal(t, userId, user.ID) + assert.Equal(t, resp.User.Email, user.Email) + assert.Nil(t, user.PhoneNumber) + + users, err := GetUserByEmail("public", "random") + assert.NoError(t, err) + assert.Nil(t, users) + + users, err = GetUserByEmail("public", "test@example.com") + assert.NoError(t, err) + assert.NotNil(t, users) + + userInfo := users + + assert.Equal(t, user.Email, userInfo.Email) + assert.Equal(t, user.ID, userInfo.ID) + assert.Equal(t, user.PhoneNumber, userInfo.PhoneNumber) + assert.Nil(t, userInfo.PhoneNumber) + assert.Equal(t, user.TimeJoined, userInfo.TimeJoined) + + user, err = GetUserByPhoneNumber("public", "random") + assert.NoError(t, err) + assert.Nil(t, user) + + resp, err = SignInUpByPhoneNumber("public", "+1234567890") + assert.NoError(t, err) + + user, err = GetUserByPhoneNumber("public", *resp.User.PhoneNumber) + assert.NoError(t, err) + assert.NotNil(t, user) + + assert.Equal(t, user.Email, resp.User.Email) + assert.Equal(t, user.ID, resp.User.ID) + assert.Equal(t, user.PhoneNumber, resp.User.PhoneNumber) + assert.Nil(t, user.Email) +} + +func TestForPasswordlessUserThatIsEmailVerifiedReturnsTrueForPhoneAndFalseForEmail(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{ + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + response, err := SignInUpByEmail("public", "test@example.com") + assert.NoError(t, err) + + isVerified, err := emailverification.IsEmailVerified(response.User.ID, nil) + assert.NoError(t, err) + assert.False(t, isVerified) // this is a change in behavior + + emailVerificationResp, err := emailverification.CreateEmailVerificationToken("public", response.User.ID, nil) + assert.NoError(t, err) + assert.Nil(t, emailVerificationResp.EmailAlreadyVerifiedError) + assert.NotNil(t, emailVerificationResp.OK) + + response, err = SignInUpByPhoneNumber("public", "+123456789012") + assert.NoError(t, err) + + isVerified, err = emailverification.IsEmailVerified(response.User.ID, nil) + assert.NoError(t, err) + assert.True(t, isVerified) + + emailVerificationResp, err = emailverification.CreateEmailVerificationToken("public", response.User.ID, nil) + assert.NoError(t, err) + assert.NotNil(t, emailVerificationResp.EmailAlreadyVerifiedError) + assert.Nil(t, emailVerificationResp.OK) +} + func TestGetUser(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/recipe/thirdparty/signinupFeature_test.go b/recipe/thirdparty/signinupFeature_test.go index 88c99dce..1b7e23c3 100644 --- a/recipe/thirdparty/signinupFeature_test.go +++ b/recipe/thirdparty/signinupFeature_test.go @@ -35,6 +35,75 @@ import ( "gopkg.in/h2non/gock.v1" ) +func TestThatThirdPartyUserThatIsEmailVerifiedReturnsTheCorrectEmailVerificationStatus(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{ + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + customProvider1, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + resp, err := ManuallyCreateOrUpdateUser("public", "custom", "verifiedUser", "test@example.com") + assert.NoError(t, err) + + emailVerificationToken, err := emailverification.CreateEmailVerificationToken("public", resp.OK.User.ID, nil) + assert.NoError(t, err) + + emailverification.VerifyEmailUsingToken("public", emailVerificationToken.OK.Token) + + isVerfied, err := emailverification.IsEmailVerified(resp.OK.User.ID, nil) + assert.NoError(t, err) + assert.True(t, isVerfied) + + resp1, err := ManuallyCreateOrUpdateUser("public", "custom2", "NotVerifiedUser", "test@example.com") + assert.NoError(t, err) + + isVerfied1, err := emailverification.IsEmailVerified(resp1.OK.User.ID, nil) + assert.NoError(t, err) + assert.False(t, isVerfied1) +} + func TestWithDisabledAPIDefaultSigninupAPIdoesnNotWork(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/recipe/thirdpartypasswordless/recipeFunctions_test.go b/recipe/thirdpartypasswordless/recipeFunctions_test.go deleted file mode 100644 index 34e68d40..00000000 --- a/recipe/thirdpartypasswordless/recipeFunctions_test.go +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "net/http" - "net/url" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestWithThirdPartyPasswordlessForThirdPartyUserThatIsEmailVerifiedReturnsTheCorrectEmailVerificationStatus(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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - customProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - resp, err := ThirdPartyManuallyCreateOrUpdateUser("public", "custom", "verifiedUser", "test@example.com") - assert.NoError(t, err) - - emailVerificationToken, err := emailverification.CreateEmailVerificationToken("public", resp.OK.User.ID, nil) - assert.NoError(t, err) - - emailverification.VerifyEmailUsingToken("public", emailVerificationToken.OK.Token) - - isVerfied, err := emailverification.IsEmailVerified(resp.OK.User.ID, nil) - assert.NoError(t, err) - assert.True(t, isVerfied) - - resp1, err := ThirdPartyManuallyCreateOrUpdateUser("public", "custom2", "NotVerifiedUser", "test@example.com") - assert.NoError(t, err) - - isVerfied1, err := emailverification.IsEmailVerified(resp1.OK.User.ID, nil) - assert.NoError(t, err) - assert.False(t, isVerfied1) -} - -func TestWithThirdPartyPasswordlessForPasswordlessUserThatIsEmailVerifiedReturnsTrueForPhoneAndFalseForEmail(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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - response, err := PasswordlessSignInUpByEmail("public", "test@example.com") - assert.NoError(t, err) - - isVerified, err := emailverification.IsEmailVerified(response.User.ID, nil) - assert.NoError(t, err) - assert.False(t, isVerified) // this is a change in behavior - - emailVerificationResp, err := emailverification.CreateEmailVerificationToken("public", response.User.ID, nil) - assert.NoError(t, err) - assert.Nil(t, emailVerificationResp.EmailAlreadyVerifiedError) - assert.NotNil(t, emailVerificationResp.OK) - - response, err = PasswordlessSignInUpByPhoneNumber("public", "+123456789012") - assert.NoError(t, err) - - isVerified, err = emailverification.IsEmailVerified(response.User.ID, nil) - assert.NoError(t, err) - assert.True(t, isVerified) - - emailVerificationResp, err = emailverification.CreateEmailVerificationToken("public", response.User.ID, nil) - assert.NoError(t, err) - assert.NotNil(t, emailVerificationResp.EmailAlreadyVerifiedError) - assert.Nil(t, emailVerificationResp.OK) -} - -func TestWithThirdPartyPasswordlessGetUserFunctionality(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - user, err := GetUserByID("random") - assert.NoError(t, err) - assert.Nil(t, user) - - resp, err := PasswordlessSignInUpByEmail("public", "test@example.com") - assert.NoError(t, err) - userId := resp.User.ID - - user, err = GetUserByID(userId) - assert.NoError(t, err) - assert.NotNil(t, user) - - assert.Equal(t, userId, user.ID) - assert.Equal(t, resp.User.Email, user.Email) - assert.Nil(t, user.PhoneNumber) - - users, err := GetUsersByEmail("public", "random") - assert.NoError(t, err) - assert.Equal(t, 0, len(users)) - - users, err = GetUsersByEmail("public", "test@example.com") - assert.NoError(t, err) - assert.Equal(t, 1, len(users)) - - userInfo := users[0] - - assert.Equal(t, user.Email, userInfo.Email) - assert.Equal(t, user.ID, userInfo.ID) - assert.Equal(t, user.PhoneNumber, userInfo.PhoneNumber) - assert.Nil(t, userInfo.PhoneNumber) - assert.Nil(t, userInfo.ThirdParty) - assert.Equal(t, user.TimeJoined, userInfo.TimeJoined) - - user, err = GetUserByPhoneNumber("public", "random") - assert.NoError(t, err) - assert.Nil(t, user) - - resp, err = PasswordlessSignInUpByPhoneNumber("public", "+1234567890") - assert.NoError(t, err) - - user, err = GetUserByPhoneNumber("public", *resp.User.PhoneNumber) - assert.NoError(t, err) - assert.NotNil(t, user) - - assert.Equal(t, user.Email, resp.User.Email) - assert.Equal(t, user.ID, resp.User.ID) - assert.Equal(t, user.PhoneNumber, resp.User.PhoneNumber) - assert.Equal(t, user.ThirdParty, resp.User.ThirdParty) - assert.Equal(t, user.ThirdParty, resp.User.ThirdParty) - assert.Nil(t, user.Email) - assert.Nil(t, user.ThirdParty) -} - -func TestWithThirdPartyPasswordlessCreateCodeTest(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - resp, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - assert.NotNil(t, resp.OK) - assert.NotNil(t, resp.OK.CodeID) - assert.NotNil(t, resp.OK.PreAuthSessionID) - assert.NotNil(t, resp.OK.CodeLifetime) - assert.NotNil(t, resp.OK.DeviceID) - assert.NotNil(t, resp.OK.LinkCode) - assert.NotNil(t, resp.OK.TimeCreated) - assert.NotNil(t, resp.OK.UserInputCode) - - userInputCode := "23123" - resp1, err := CreateCodeWithEmail("public", "test@example.com", &userInputCode) - assert.NoError(t, err) - assert.NotNil(t, resp1.OK) - assert.NotNil(t, resp1.OK.CodeID) - assert.NotNil(t, resp1.OK.PreAuthSessionID) - assert.NotNil(t, resp1.OK.CodeLifetime) - assert.NotNil(t, resp1.OK.DeviceID) - assert.NotNil(t, resp1.OK.LinkCode) - assert.NotNil(t, resp1.OK.TimeCreated) - assert.NotNil(t, resp1.OK.UserInputCode) -} - -func TestThirdPartyPasswordlessCreateNewCodeFromDevice(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - resp, err := CreateCodeWithEmail("public", "test@example.com", nil) - - assert.NoError(t, err) - - resp1, err := CreateNewCodeForDevice("public", resp.OK.DeviceID, nil) - assert.NoError(t, err) - - assert.NoError(t, err) - assert.NotNil(t, resp1.OK) - assert.NotNil(t, resp1.OK.CodeID) - assert.NotNil(t, resp1.OK.PreAuthSessionID) - assert.NotNil(t, resp1.OK.CodeLifetime) - assert.NotNil(t, resp1.OK.DeviceID) - assert.NotNil(t, resp1.OK.LinkCode) - assert.NotNil(t, resp1.OK.TimeCreated) - assert.NotNil(t, resp1.OK.UserInputCode) - - resp, err = CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - userInputCode := "2314" - resp1, err = CreateNewCodeForDevice("public", resp.OK.DeviceID, &userInputCode) - assert.NoError(t, err) - - assert.NoError(t, err) - assert.NotNil(t, resp1.OK) - assert.NotNil(t, resp1.OK.CodeID) - assert.NotNil(t, resp1.OK.PreAuthSessionID) - assert.NotNil(t, resp1.OK.CodeLifetime) - assert.NotNil(t, resp1.OK.DeviceID) - assert.NotNil(t, resp1.OK.LinkCode) - assert.NotNil(t, resp1.OK.TimeCreated) - assert.NotNil(t, resp1.OK.UserInputCode) - - resp, err = CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - resp1, err = CreateNewCodeForDevice("public", "random", nil) - assert.NoError(t, err) - assert.NotNil(t, resp1.RestartFlowError) - assert.Nil(t, resp1.OK) - - resp, err = CreateCodeWithEmail("public", "test@example.com", &userInputCode) - assert.NoError(t, err) - - resp1, err = CreateNewCodeForDevice("public", resp.OK.DeviceID, &userInputCode) - assert.NoError(t, err) - assert.NotNil(t, resp1.UserInputCodeAlreadyUsedError) - assert.Nil(t, resp1.OK) -} - -func TestThirdPartyPasswordlessConsumeCoed(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - resp, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - result, err := ConsumeCodeWithUserInputCode("public", resp.OK.DeviceID, resp.OK.UserInputCode, resp.OK.PreAuthSessionID) - assert.NoError(t, err) - - assert.NotNil(t, result.OK) - assert.True(t, result.OK.CreatedNewUser) - assert.Equal(t, "test@example.com", *result.OK.User.Email) - assert.NotNil(t, result.OK) - assert.NotNil(t, result.OK.User) - assert.NotNil(t, result.OK.User.ID) - assert.NotNil(t, result.OK.User.TimeJoined) - assert.Nil(t, result.OK.User.PhoneNumber) - assert.Nil(t, result.OK.User.ThirdParty) - - resp, err = CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - result, err = ConsumeCodeWithUserInputCode("public", resp.OK.DeviceID, "random", resp.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, result.IncorrectUserInputCodeError) - assert.Equal(t, 1, result.IncorrectUserInputCodeError.FailedCodeInputAttemptCount) - assert.Equal(t, 5, result.IncorrectUserInputCodeError.MaximumCodeInputAttempts) - - resp, err = CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - _, err = ConsumeCodeWithUserInputCode("public", resp.OK.DeviceID, resp.OK.UserInputCode, "random") - assert.Contains(t, err.Error(), "preAuthSessionId and deviceId doesn't match") -} - -func TestThirdPartyPasswordlessConsumeCodeTestWithExpiredUserInputCodeError(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - resp, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - time.Sleep(2 * time.Second) - - result, err := ConsumeCodeWithUserInputCode("public", resp.OK.DeviceID, resp.OK.UserInputCode, resp.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, result.ExpiredUserInputCodeError) - assert.Equal(t, 1, result.ExpiredUserInputCodeError.FailedCodeInputAttemptCount) - assert.Equal(t, 5, result.ExpiredUserInputCodeError.MaximumCodeInputAttempts) - assert.Nil(t, result.OK) -} - -func TestThirdPartyPasswordlessUpdateUserContactMethodEmailTest(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - userInfo, err := PasswordlessSignInUpByEmail("public", "test@example.com") - assert.NoError(t, err) - - updatedEmail := "test2@example.com" - resp, err := UpdatePasswordlessUser(userInfo.User.ID, &updatedEmail, nil) - assert.NoError(t, err) - assert.NotNil(t, resp.OK) - - user, err := GetUserByID(userInfo.User.ID) - assert.NoError(t, err) - assert.Equal(t, updatedEmail, *user.Email) - - resp, err = UpdatePasswordlessUser("random", &updatedEmail, nil) - assert.NoError(t, err) - assert.Nil(t, resp.OK) - assert.NotNil(t, resp.UnknownUserIdError) - - userInfo2, err := PasswordlessSignInUpByEmail("public", "test3@example.com") - assert.NoError(t, err) - - resp, err = UpdatePasswordlessUser(userInfo2.User.ID, &updatedEmail, nil) - assert.NoError(t, err) - assert.Nil(t, resp.OK) - assert.NotNil(t, resp.EmailAlreadyExistsError) -} - -func TestThirdPartyPasswordlessUpdateUserContactPhone(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - phoneNumber_1 := "+1234567891" - phoneNumber_2 := "+1234567892" - phoneNumber_3 := "+1234567893" - - userInfo, err := PasswordlessSignInUpByPhoneNumber("public", phoneNumber_1) - assert.NoError(t, err) - - res1, err := UpdatePasswordlessUser(userInfo.User.ID, nil, &phoneNumber_2) - assert.NoError(t, err) - - assert.NotNil(t, res1.OK) - - result, err := GetUserByID(userInfo.User.ID) - assert.NoError(t, err) - - assert.Equal(t, phoneNumber_2, *result.PhoneNumber) - - userInfo1, err := PasswordlessSignInUpByPhoneNumber("public", phoneNumber_3) - assert.NoError(t, err) - - res1, err = UpdatePasswordlessUser(userInfo1.User.ID, nil, &phoneNumber_2) - assert.NoError(t, err) - - assert.Nil(t, res1.OK) - assert.NotNil(t, res1.PhoneNumberAlreadyExistsError) -} - -func TestThirdPartyPasswordlessRevokeAllCodesTest(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - codeInfo1, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - codeInfo2, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - err = RevokeAllCodesByEmail("public", "test@example.com") - assert.NoError(t, err) - - result1, err := ConsumeCodeWithUserInputCode("public", codeInfo1.OK.DeviceID, codeInfo1.OK.UserInputCode, codeInfo1.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, result1.RestartFlowError) - assert.Nil(t, result1.OK) - - result2, err := ConsumeCodeWithUserInputCode("public", codeInfo2.OK.DeviceID, codeInfo2.OK.UserInputCode, codeInfo2.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, result2.RestartFlowError) - assert.Nil(t, result2.OK) -} - -func TestThirdPartyPasswordlessRevokeCode(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - codeInfo1, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - codeInfo2, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - err = RevokeCode("public", codeInfo1.OK.CodeID) - assert.NoError(t, err) - - result1, err := ConsumeCodeWithUserInputCode("public", codeInfo1.OK.DeviceID, codeInfo1.OK.UserInputCode, codeInfo1.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, result1.RestartFlowError) - assert.Nil(t, result1.OK) - - result2, err := ConsumeCodeWithUserInputCode("public", codeInfo2.OK.DeviceID, codeInfo2.OK.UserInputCode, codeInfo2.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.Nil(t, result2.RestartFlowError) - assert.NotNil(t, result2.OK) -} - -func TestThirdPartyPasswordlessListCodesByEmail(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - codeInfo1, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - codeInfo2, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - - result, err := ListCodesByEmail("public", "test@example.com") - assert.NoError(t, err) - - assert.Equal(t, 2, len(result)) - for _, dt := range result { - for _, c := range dt.Codes { - if !(c.CodeID == codeInfo1.OK.CodeID || c.CodeID == codeInfo2.OK.CodeID) { - t.Fail() - } - } - } -} - -func TestListCodesByPhoneNumber(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - codeInfo1, err := CreateCodeWithEmail("public", "+1234567890", nil) - assert.NoError(t, err) - - codeInfo2, err := CreateCodeWithEmail("public", "+1234567890", nil) - assert.NoError(t, err) - - result, err := ListCodesByEmail("public", "+1234567890") - assert.NoError(t, err) - - assert.Equal(t, 2, len(result)) - for _, dt := range result { - for _, c := range dt.Codes { - if !(c.CodeID == codeInfo1.OK.CodeID || c.CodeID == codeInfo2.OK.CodeID) { - t.Fail() - } - } - } -} - -func TestThirdPartyPasswordlessListCodesByDeviceIdAndListCodesByPreAuthSessionId(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - codeInfo1, err := CreateCodeWithEmail("public", "+1234567890", nil) - assert.NoError(t, err) - - result, err := ListCodesByDeviceID("public", codeInfo1.OK.DeviceID) - assert.NoError(t, err) - - assert.Equal(t, codeInfo1.OK.CodeID, result.Codes[0].CodeID) - - result, err = ListCodesByPreAuthSessionID("public", codeInfo1.OK.PreAuthSessionID) - assert.NoError(t, err) - - assert.Equal(t, codeInfo1.OK.CodeID, result.Codes[0].CodeID) -} - -func TestCreateMagicLinkTest(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - result, err := CreateMagicLinkByPhoneNumber("public", "+1234567890") - assert.NoError(t, err) - - magicLinkURL, err := url.Parse(result) - assert.NoError(t, err) - - assert.Equal(t, "supertokens.io", magicLinkURL.Host) - assert.Equal(t, "/auth/verify", magicLinkURL.Path) - assert.Equal(t, "thirdpartypasswordless", magicLinkURL.Query().Get("rid")) - assert.NotNil(t, magicLinkURL.Query().Get("preAuthSessionId")) -} - -func TestThirdPartyPasswordlessSignInUp(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - result, err := PasswordlessSignInUpByPhoneNumber("public", "+12345678901") - assert.NoError(t, err) - assert.NotNil(t, result.User) - assert.True(t, result.CreatedNewUser) - assert.Equal(t, "+12345678901", *result.User.PhoneNumber) - assert.NotNil(t, result.User.TimeJoined) - assert.NotNil(t, result.User.ID) - assert.Nil(t, result.User.ThirdParty) -} From 31d2f5dd13b82d6e9c7ecf93290bbb1b290a6ee7 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 10 Apr 2024 17:28:18 +0530 Subject: [PATCH 07/19] more tests moving around --- .../passwordless/passwordless_email_test.go | 299 +++++ recipe/thirdparty/email_test.go | 208 ++++ recipe/thirdparty/signinupFeature_test.go | 81 ++ recipe/thirdparty/testingUtils.go | 20 + .../signinupFeature_test.go | 1084 ----------------- .../signoutFeature_test.go | 436 ------- .../thirdpartypasswordless/tpl_email_test.go | 1046 ---------------- recipe/thirdpartypasswordless/tpl_sms_test.go | 402 ------ .../tpl_userIdMapping_test.go | 211 ---- recipe/thirdpartypasswordless/users_test.go | 422 ------- 10 files changed, 608 insertions(+), 3601 deletions(-) delete mode 100644 recipe/thirdpartypasswordless/signinupFeature_test.go delete mode 100644 recipe/thirdpartypasswordless/signoutFeature_test.go delete mode 100644 recipe/thirdpartypasswordless/tpl_email_test.go delete mode 100644 recipe/thirdpartypasswordless/tpl_sms_test.go delete mode 100644 recipe/thirdpartypasswordless/tpl_userIdMapping_test.go delete mode 100644 recipe/thirdpartypasswordless/users_test.go diff --git a/recipe/passwordless/passwordless_email_test.go b/recipe/passwordless/passwordless_email_test.go index 9ad85df0..368183d7 100644 --- a/recipe/passwordless/passwordless_email_test.go +++ b/recipe/passwordless/passwordless_email_test.go @@ -26,6 +26,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" + "github.com/supertokens/supertokens-golang/recipe/emailverification" + "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" + "github.com/supertokens/supertokens-golang/recipe/passwordless/emaildelivery/smtpService" "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" @@ -33,6 +36,302 @@ import ( "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestSMTPOverrideEmailVerifyForPasswordlessUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + getContentCalled := false + sendRawEmailCalled := false + email := "" + emailVerifyLink := "" + var userInputCode *string + + evSmtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ + Settings: emaildelivery.SMTPSettings{ + Host: "", + From: emaildelivery.SMTPFrom{ + Name: "Test User", + Email: "", + }, + Port: 123, + Password: "", + }, + Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { + (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { + if input.EmailVerification != nil { + email = input.EmailVerification.User.Email + emailVerifyLink = input.EmailVerification.EmailVerifyLink + getContentCalled = true + } + return emaildelivery.EmailContent{}, nil + } + + (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { + sendRawEmailCalled = true + return nil + } + + return originalImplementation + }, + }) + tplSmtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ + Settings: emaildelivery.SMTPSettings{ + Host: "", + From: emaildelivery.SMTPFrom{ + Name: "Test User", + Email: "", + }, + Port: 123, + Password: "", + }, + Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { + (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { + if input.PasswordlessLogin != nil { + userInputCode = input.PasswordlessLogin.UserInputCode + } + return emaildelivery.EmailContent{}, nil + } + + (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { + sendRawEmailCalled = true + return nil + } + + return originalImplementation + }, + }) + tplConfig := plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + EmailDelivery: &emaildelivery.TypeInput{ + Service: tplSmtpService, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + EmailDelivery: &emaildelivery.TypeInput{ + Service: evSmtpService, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(tplConfig), + ) + defer testServer.Close() + + querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + cdiVersion, err := querier.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { + return + } + + resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + bodyBytes, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + var response map[string]interface{} + json.Unmarshal(bodyBytes, &response) + + resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *userInputCode, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + sendRawEmailCalled = false // it would be true for the passwordless login, so reset it + + cookies := resp.Cookies() + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + bodyBytes, err = ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + json.Unmarshal(bodyBytes, &response) + assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") + + // Default handler not called + assert.False(t, emailverification.EmailVerificationEmailSentForTest) + assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) + assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) + + // Custom handler not called + assert.Empty(t, email) + assert.Empty(t, emailVerifyLink) + assert.False(t, getContentCalled) + assert.False(t, sendRawEmailCalled) +} + +func TestCustomOverrideEmailVerifyForPasswordlessUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + customCalled := false + email := "" + emailVerifyLink := "" + + tplConfig := plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + EmailDelivery: &emaildelivery.TypeInput{ + Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { + sendEmail := *originalImplementation.SendEmail + *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.EmailVerification != nil { + customCalled = true + email = input.EmailVerification.User.Email + emailVerifyLink = input.EmailVerification.EmailVerifyLink + return nil + } + return sendEmail(input, userContext) + } + return originalImplementation + }, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(tplConfig), + ) + defer testServer.Close() + + querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + cdiVersion, err := querier.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { + return + } + + resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + bodyBytes, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + var response map[string]interface{} + json.Unmarshal(bodyBytes, &response) + + resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *PasswordlessLoginEmailDataForTest.UserInputCode, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + cookies := resp.Cookies() + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + bodyBytes, err = ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + json.Unmarshal(bodyBytes, &response) + assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") + + // Default handler not called + assert.False(t, emailverification.EmailVerificationEmailSentForTest) + assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) + assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) + + // Custom handler not called + assert.Empty(t, email) + assert.Empty(t, emailVerifyLink) + assert.False(t, customCalled) +} + +func TestDefaultBackwardCompatibilityEmailVerifyForUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + tplConfig := plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(tplConfig), + ) + defer testServer.Close() + + querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + cdiVersion, err := querier.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { + return + } + + resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + bodyBytes, err := ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + var response map[string]interface{} + json.Unmarshal(bodyBytes, &response) + + resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *PasswordlessLoginEmailDataForTest.UserInputCode, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + cookies := resp.Cookies() + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + + bodyBytes, err = ioutil.ReadAll(resp.Body) + assert.NoError(t, err) + + json.Unmarshal(bodyBytes, &response) + assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.False(t, emailverification.EmailVerificationEmailSentForTest) + assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) + assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) +} + func TestDefaultBackwardCompatibilityPasswordlessLogin(t *testing.T) { BeforeEach() unittesting.StartUpST("localhost", "8080") diff --git a/recipe/thirdparty/email_test.go b/recipe/thirdparty/email_test.go index 4a895698..6812930d 100644 --- a/recipe/thirdparty/email_test.go +++ b/recipe/thirdparty/email_test.go @@ -17,6 +17,8 @@ package thirdparty import ( + "bytes" + "encoding/json" "net/http" "testing" @@ -24,12 +26,218 @@ import ( "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" + "github.com/supertokens/supertokens-golang/recipe/emailverification" + "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" + "github.com/supertokens/supertokens-golang/recipe/passwordless/emaildelivery/smtpService" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestSMTPOverrideEmailVerifyForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + getContentCalled := false + sendRawEmailCalled := false + email := "" + emailVerifyLink := "" + + smtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ + Settings: emaildelivery.SMTPSettings{ + Host: "", + From: emaildelivery.SMTPFrom{ + Name: "Test User", + Email: "", + }, + Port: 123, + Password: "", + }, + Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { + (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { + if input.EmailVerification != nil { + email = input.EmailVerification.User.Email + emailVerifyLink = input.EmailVerification.EmailVerifyLink + getContentCalled = true + } + return emaildelivery.EmailContent{}, nil + } + + (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { + sendRawEmailCalled = true + return nil + } + + return originalImplementation + }, + }) + tplConfig := tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{customProviderForEmailVerification}, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + EmailDelivery: &emaildelivery.TypeInput{ + Service: smtpService, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tplConfig), + ) + defer testServer.Close() + + signinupPostData := PostDataForCustomProvider{ + ThirdPartyId: "custom", + OAuthTokens: map[string]interface{}{ + "access_token": "saodiasjodai", + }, + } + + postBody, err := json.Marshal(signinupPostData) + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + + cookies := resp.Cookies() + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Default handler not called + assert.False(t, emailverification.EmailVerificationEmailSentForTest) + assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) + assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) + + assert.Equal(t, email, "test@example.com") + assert.NotEmpty(t, emailVerifyLink) + assert.Equal(t, getContentCalled, true) + assert.Equal(t, sendRawEmailCalled, true) +} + +func TestCustomOverrideEmailVerifyForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + customCalled := false + email := "" + emailVerifyLink := "" + + tplConfig := tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{customProviderForEmailVerification}, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{ + Mode: evmodels.ModeOptional, + EmailDelivery: &emaildelivery.TypeInput{ + Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { + sendEmail := *originalImplementation.SendEmail + *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + if input.EmailVerification != nil { + customCalled = true + email = input.EmailVerification.User.Email + emailVerifyLink = input.EmailVerification.EmailVerifyLink + return nil + } + return sendEmail(input, userContext) + } + return originalImplementation + }, + }, + }), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tplConfig), + ) + defer testServer.Close() + + signinupPostData := PostDataForCustomProvider{ + ThirdPartyId: "custom", + OAuthTokens: map[string]interface{}{ + "access_token": "saodiasjodai", + }, + } + + postBody, err := json.Marshal(signinupPostData) + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + + cookies := resp.Cookies() + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Default handler not called + assert.False(t, emailverification.EmailVerificationEmailSentForTest) + assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) + assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) + + // Custom handler called + assert.Equal(t, email, "test@example.com") + assert.NotEmpty(t, emailVerifyLink) + assert.True(t, customCalled) +} + +func TestDefaultBackwardCompatibilityEmailVerifyForThirdpartyUser(t *testing.T) { + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + + tplConfig := tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + customProviderForEmailVerification, + }, + }, + } + testServer := supertokensInitForTest( + t, + emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tplConfig), + ) + defer testServer.Close() + + signinupPostData := PostDataForCustomProvider{ + ThirdPartyId: "custom", + OAuthTokens: map[string]interface{}{ + "access_token": "saodiasjodai", + }, + } + + postBody, err := json.Marshal(signinupPostData) + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + assert.NoError(t, err) + + cookies := resp.Cookies() + + resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.True(t, emailverification.EmailVerificationEmailSentForTest) + assert.Equal(t, emailverification.EmailVerificationDataForTest.User.Email, "test@example.com") + assert.NotEmpty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) +} + func TestDefaultBackwardCompatibilityPasswordResetForThirdpartyUser(t *testing.T) { BeforeEach() unittesting.StartUpST("localhost", "8080") diff --git a/recipe/thirdparty/signinupFeature_test.go b/recipe/thirdparty/signinupFeature_test.go index 1b7e23c3..b6fe46b8 100644 --- a/recipe/thirdparty/signinupFeature_test.go +++ b/recipe/thirdparty/signinupFeature_test.go @@ -740,6 +740,87 @@ func TestInvalidPostParamsForThirdPartyModule(t *testing.T) { assert.Equal(t, "Please provide one of redirectURIInfo or oAuthTokens in the request body", response2["message"]) } +func TestErrorThrownFromGetProfileInfoFunction(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + signinupCustomProvider4, + }, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + defer gock.OffAll() + gock.New("https://test.com/"). + Post("oauth/token"). + Reply(200). + JSON(map[string]string{"access_token": "abcdefghj"}) + + postData := map[string]interface{}{ + "thirdPartyId": "custom", + "redirectURIInfo": map[string]interface{}{ + "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", + "redirectURIQueryParams": map[string]interface{}{ + "code": "abcdefghj", + }, + }, + } + + postBody, err := json.Marshal(postData) + if err != nil { + t.Error(err.Error()) + } + + gock.New(testServer.URL).EnableNetworking().Persist() + gock.New("http://localhost:8080/").EnableNetworking().Persist() + + resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) + if err != nil { + t.Error(err.Error()) + } + assert.Equal(t, 500, resp.StatusCode) +} + func TestEmailNotReturnedInGetProfileInfoFunction(t *testing.T) { customAntiCsrfValue := "VIA_TOKEN" configValue := supertokens.TypeInput{ diff --git a/recipe/thirdparty/testingUtils.go b/recipe/thirdparty/testingUtils.go index 00cc485d..a39b6e78 100644 --- a/recipe/thirdparty/testingUtils.go +++ b/recipe/thirdparty/testingUtils.go @@ -16,6 +16,7 @@ package thirdparty import ( + "errors" "net/http" "net/http/httptest" "testing" @@ -239,3 +240,22 @@ var customProvider3 = tpmodels.ProviderInput{ return originalImplementation }, } + +var signinupCustomProvider4 = tpmodels.ProviderInput{ + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "custom", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "supertokens", + }, + }, + AuthorizationEndpoint: "https://test.com/oauth/auth", + TokenEndpoint: "https://test.com/oauth/token", + }, + Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { + originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { + return tpmodels.TypeUserInfo{}, errors.New("error from getUserInfo") + } + return originalImplementation + }, +} diff --git a/recipe/thirdpartypasswordless/signinupFeature_test.go b/recipe/thirdpartypasswordless/signinupFeature_test.go deleted file mode 100644 index 2555213b..00000000 --- a/recipe/thirdpartypasswordless/signinupFeature_test.go +++ /dev/null @@ -1,1084 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" -) - -func TestThirdPartyPasswordlessThatIfYouDisableTheSignInUpAPIItDoesNotWork(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Override: &tplmodels.OverrideStruct{ - APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - *originalImplementation.ThirdPartySignInUpPOST = nil - return originalImplementation - }, - }, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "test", - ClientSecret: "test-secret", - }, - }, - }, - }, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - signinupPostData := map[string]interface{}{ - "thirdPartyId": "google", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(signinupPostData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - -func TestWithThirdPartyPasswordlessMinimumConfigWithoutCodeForThirdPartyModyule(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - signinupCustomProvider6, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - signinupPostData := thirdparty.PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, true, result["createdNewUser"]) - assert.Equal(t, "OK", result["status"]) - - user := result["user"].(map[string]interface{}) - - assert.Equal(t, "email@test.com", user["email"]) - assert.Equal(t, "custom", user["thirdParty"].(map[string]interface{})["id"]) - assert.Equal(t, "user", user["thirdParty"].(map[string]interface{})["userId"]) - - assert.NotNil(t, cookieData["antiCsrf"]) - assert.NotNil(t, cookieData["sAccessToken"]) - assert.NotNil(t, cookieData["sRefreshToken"]) - assert.NotNil(t, cookieData["refreshTokenExpiry"]) - assert.NotNil(t, cookieData["refreshTokenHttpOnly"]) - assert.NotNil(t, cookieData["accessTokenExpiry"]) - assert.NotNil(t, cookieData["accessTokenHttpOnly"]) -} - -func TestWithThirdPartyPasswordlessMissingCodeAndAuthCodeResponse(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - signinupCustomProvider6, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - signinupPostData := thirdparty.PostDataForCustomProvider{ - ThirdPartyId: "custom", - RedirectURIInfo: &struct { - RedirectURIOnProviderDashboard string "json:\"redirectURIOnProviderDashboard\"" - RedirectURIQueryParams map[string]interface{} "json:\"redirectURIQueryParams\"" - }{ - RedirectURIOnProviderDashboard: "http://127.0.0.1/callback", - }, - } - - postBody, err := json.Marshal(signinupPostData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) -} - -func TestWithThirdPartyPasswordlessMinimumConfigForThirdpartyModule(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{"access_token": "abcdefghj"}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, true, result["createdNewUser"]) - assert.Equal(t, "OK", result["status"]) - - user := result["user"].(map[string]interface{}) - - assert.Equal(t, "email@test.com", user["email"]) - assert.Equal(t, "custom", user["thirdParty"].(map[string]interface{})["id"]) - assert.Equal(t, "user", user["thirdParty"].(map[string]interface{})["userId"]) - - assert.NotNil(t, cookieData["antiCsrf"]) - assert.NotNil(t, cookieData["sAccessToken"]) - assert.NotNil(t, cookieData["sRefreshToken"]) - assert.NotNil(t, cookieData["refreshTokenExpiry"]) - assert.NotNil(t, cookieData["refreshTokenHttpOnly"]) - assert.NotNil(t, cookieData["accessTokenExpiry"]) - assert.NotNil(t, cookieData["accessTokenHttpOnly"]) -} - -func TestWithThirdPartyPasswordlessWithMinimumConfigForThirdPartyModuleEmailUnverified(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - }), - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - signinupCustomProvider5, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{"access_token": "abcdefghj"}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, true, result["createdNewUser"]) - assert.Equal(t, "OK", result["status"]) - - user := result["user"].(map[string]interface{}) - - isVerified, err := emailverification.IsEmailVerified(user["id"].(string), nil) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, false, isVerified) - - assert.Equal(t, "email@test.com", user["email"]) - assert.Equal(t, "custom", user["thirdParty"].(map[string]interface{})["id"]) - assert.Equal(t, "user", user["thirdParty"].(map[string]interface{})["userId"]) - - assert.NotNil(t, cookieData["antiCsrf"]) - assert.NotNil(t, cookieData["sAccessToken"]) - assert.NotNil(t, cookieData["sRefreshToken"]) - assert.NotNil(t, cookieData["refreshTokenExpiry"]) - assert.NotNil(t, cookieData["refreshTokenHttpOnly"]) - assert.NotNil(t, cookieData["accessTokenExpiry"]) - assert.NotNil(t, cookieData["accessTokenHttpOnly"]) -} - -func TestWithThirdPartyPasswordlessThirdPartyProviderDoesNotExistInConfig(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - postData := map[string]interface{}{ - "thirdPartyId": "google", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - - response := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, "the provider google could not be found in the configuration", response["message"]) -} - -func TestWithThirdPartyPasswordlessEmailNotReturnedInGetProfileInfoFunction(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - signinupCustomProvider3, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{"access_token": "abcdefghj"}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "NO_EMAIL_GIVEN_BY_PROVIDER", result["status"]) -} - -func TestWithThirdPartyPasswordlessErrorThrownFromGetProfileInfoFunction(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - signinupCustomProvider4, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{"access_token": "abcdefghj"}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "abcdefghj", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, 500, resp.StatusCode) -} - -func TestWithThirdPartyPasswordlessInvalidPostParamsForThirdPartyModule(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - //request where the postData was empty - postData := map[string]string{} - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - response := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "Please provide the thirdPartyId in request body", response["message"]) - - //request where the post data just had the thirdpartyid - postData1 := map[string]string{ - "thirdPartyId": "custom", - } - postBody1, err := json.Marshal(postData1) - if err != nil { - t.Error(err.Error()) - } - resp1, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody1)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusBadRequest, resp1.StatusCode) - response1 := *unittesting.HttpResponseToConsumableInformation(resp1.Body) - assert.Equal(t, "Please provide one of redirectURIInfo or oAuthTokens in the request body", response1["message"]) - - //request where the post data without redirect-uri - postData2 := map[string]interface{}{ - "thirdPartyId": "custom", - "code": "32432432", - } - postBody2, err := json.Marshal(postData2) - if err != nil { - t.Error(err.Error()) - } - resp2, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody2)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusBadRequest, resp2.StatusCode) - response2 := *unittesting.HttpResponseToConsumableInformation(resp2.Body) - assert.Equal(t, "Please provide one of redirectURIInfo or oAuthTokens in the request body", response2["message"]) -} - -func TestWithThirdPartyPasswordlessGetUserByIdWhenUserDoesNotExist(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://localhost.org", - "redirectURIQueryParams": map[string]interface{}{ - "code": "32432432", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - userDataBeforeSignup, err := GetUserByID("randomId") - - if err != nil { - t.Error(err.Error()) - } - - assert.Nil(t, userDataBeforeSignup) - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - - assert.Equal(t, "OK", result["status"]) - - user := result["user"].(map[string]interface{}) - userInfoAfterSignup, err := GetUserByID(user["id"].(string)) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, userInfoAfterSignup.ID, user["id"].(string)) - assert.Equal(t, *userInfoAfterSignup.Email, user["email"].(string)) -} - -func TestGetUserByThirdPartyInfoWhenUserDoesNotExist(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://localhost.org", - "redirectURIQueryParams": map[string]interface{}{ - "code": "32432432", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - userBegoreSignup, err := GetUserByThirdPartyInfo("public", "custom", "user") - if err != nil { - t.Error(err.Error()) - } - assert.Nil(t, userBegoreSignup) - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - - dataInBytes, err := io.ReadAll(resp.Body) - if err != nil { - t.Error(err.Error()) - } - resp.Body.Close() - - var result map[string]interface{} - - err = json.Unmarshal(dataInBytes, &result) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, "OK", result["status"]) - - user := result["user"].(map[string]interface{}) - userInfoAfterSignup, err := GetUserByThirdPartyInfo("public", "custom", "user") - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, userInfoAfterSignup.ID, user["id"].(string)) - assert.Equal(t, *userInfoAfterSignup.Email, user["email"].(string)) -} diff --git a/recipe/thirdpartypasswordless/signoutFeature_test.go b/recipe/thirdpartypasswordless/signoutFeature_test.go deleted file mode 100644 index 6b4ff826..00000000 --- a/recipe/thirdpartypasswordless/signoutFeature_test.go +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" - "gopkg.in/h2non/gock.v1" -) - -func TestTheDefaultRouteAndItShouldRevokeTheSession(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "32432432", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - - cookieData := unittesting.ExtractInfoFromResponse(resp) - - req, err := http.NewRequest(http.MethodPost, testServer.URL+"/auth/signout", nil) - if err != nil { - t.Error(err.Error()) - } - - req.Header.Add("Cookie", "sAccessToken="+cookieData["sAccessToken"]) - req.Header.Add("anti-csrf", cookieData["antiCsrf"]) - - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusOK, res.StatusCode) - - cookieData1 := unittesting.ExtractInfoFromResponseWhenAntiCSRFisNone(res) - - assert.Equal(t, "", cookieData1["sAccessToken"]) - assert.Equal(t, "", cookieData1["sRefreshToken"]) - - assert.Equal(t, "Thu, 01 Jan 1970 00:00:00 GMT", cookieData1["refreshTokenExpiry"]) - assert.Equal(t, "Thu, 01 Jan 1970 00:00:00 GMT", cookieData1["accessTokenExpiry"]) - - assert.Equal(t, "", cookieData1["accessTokenDomain"]) - assert.Equal(t, "", cookieData1["refreshTokenDomain"]) -} - -func TestDisablingDefaultRouteAndCallingTheAPIReturns404(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Override: &tplmodels.OverrideStruct{ - APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - *originalImplementation.ThirdPartySignInUpPOST = nil - return originalImplementation - }, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - req, err := http.NewRequest(http.MethodPost, testServer.URL+"/auth/signout", nil) - if err != nil { - t.Error(err.Error()) - } - - req.Header.Add("rid", "thirdparty") - - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - - assert.Equal(t, http.StatusNotFound, res.StatusCode) -} - -func TestCallingAPIWithoutSessionShouldReturnOk(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{ - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - resp, err := http.Post(testServer.URL+"/auth/signout", "application/json", nil) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, 0, len(resp.Cookies())) - assert.Equal(t, "", resp.Header.Get("set-cookie")) - - response := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", response["status"]) -} - -func TestThatSignoutAPIreturnsTryRefreshTokenRefreshSessionAndSignoutShouldReturnOk(t *testing.T) { - customAntiCsrfValue := "VIA_TOKEN" - 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{ - session.Init(&sessmodels.TypeInput{ - AntiCsrf: &customAntiCsrfValue, - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - SigninupCustomProvider1, - }, - }), - }, - } - - BeforeEach() - unittesting.SetKeyValueInConfig("access_token_validity", "2") - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - err := supertokens.Init(configValue) - if err != nil { - t.Error(err.Error()) - } - q, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - apiV, err := q.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - - if unittesting.MaxVersion(apiV, "2.11") == "2.11" { - return - } - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - defer testServer.Close() - - defer gock.OffAll() - gock.New("https://test.com/"). - Post("oauth/token"). - Reply(200). - JSON(map[string]string{}) - - postData := map[string]interface{}{ - "thirdPartyId": "custom", - "redirectURIInfo": map[string]interface{}{ - "redirectURIOnProviderDashboard": "http://127.0.0.1/callback", - "redirectURIQueryParams": map[string]interface{}{ - "code": "32432432", - }, - }, - } - - postBody, err := json.Marshal(postData) - if err != nil { - t.Error(err.Error()) - } - - gock.New(testServer.URL).EnableNetworking().Persist() - gock.New("http://localhost:8080/").EnableNetworking().Persist() - - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, resp.StatusCode) - cookieData := unittesting.ExtractInfoFromResponse(resp) - - result := *unittesting.HttpResponseToConsumableInformation(resp.Body) - assert.Equal(t, "OK", result["status"]) - - time.Sleep(5 * time.Second) - - req, err := http.NewRequest(http.MethodPost, testServer.URL+"/auth/signout", nil) - if err != nil { - t.Error(err.Error()) - } - - req.Header.Add("Cookie", "sAccessToken="+cookieData["sAccessToken"]) - req.Header.Add("anti-csrf", cookieData["antiCsrf"]) - - res, err := http.DefaultClient.Do(req) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusUnauthorized, res.StatusCode) - - result1 := *unittesting.HttpResponseToConsumableInformation(res.Body) - assert.Equal(t, "try refresh token", result1["message"]) - - req1, err := http.NewRequest(http.MethodPost, testServer.URL+"/auth/session/refresh", nil) - if err != nil { - t.Error(err.Error()) - } - req1.Header.Add("Cookie", "sRefreshToken="+cookieData["sRefreshToken"]) - req1.Header.Add("anti-csrf", cookieData["antiCsrf"]) - - res1, err := http.DefaultClient.Do(req1) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, res1.StatusCode) - cookieData1 := unittesting.ExtractInfoFromResponse(res1) - - req2, err := http.NewRequest(http.MethodPost, testServer.URL+"/auth/signout", nil) - if err != nil { - t.Error(err.Error()) - } - req2.Header.Add("Cookie", "sAccessToken="+cookieData1["sAccessToken"]) - req2.Header.Add("anti-csrf", cookieData1["antiCsrf"]) - - res2, err := http.DefaultClient.Do(req2) - if err != nil { - t.Error(err.Error()) - } - assert.Equal(t, http.StatusOK, res2.StatusCode) - - cookieData2 := unittesting.ExtractInfoFromResponseWhenAntiCSRFisNone(res2) - - assert.Equal(t, "", cookieData2["sAccessToken"]) - assert.Equal(t, "", cookieData2["sRefreshToken"]) - - assert.Equal(t, "Thu, 01 Jan 1970 00:00:00 GMT", cookieData2["refreshTokenExpiry"]) - assert.Equal(t, "Thu, 01 Jan 1970 00:00:00 GMT", cookieData2["accessTokenExpiry"]) - - assert.Equal(t, "", cookieData2["accessTokenDomain"]) - assert.Equal(t, "", cookieData2["refreshTokenDomain"]) -} diff --git a/recipe/thirdpartypasswordless/tpl_email_test.go b/recipe/thirdpartypasswordless/tpl_email_test.go deleted file mode 100644 index 69314107..00000000 --- a/recipe/thirdpartypasswordless/tpl_email_test.go +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/emailverification/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestDefaultBackwardCompatibilityPasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - assert.True(t, passwordless.PasswordlessLoginEmailSentForTest) - assert.Equal(t, passwordless.PasswordlessLoginEmailDataForTest.Email, "test@example.com") - assert.NotNil(t, passwordless.PasswordlessLoginEmailDataForTest.UrlWithLinkCode) - assert.NotNil(t, passwordless.PasswordlessLoginEmailDataForTest.UserInputCode) - - // Test resend - ResetForTest() - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.True(t, passwordless.PasswordlessLoginEmailSentForTest) - assert.Equal(t, passwordless.PasswordlessLoginEmailDataForTest.Email, "test@example.com") - assert.NotNil(t, passwordless.PasswordlessLoginEmailDataForTest.UrlWithLinkCode) - assert.NotNil(t, passwordless.PasswordlessLoginEmailDataForTest.UserInputCode) -} - -func TestBackwardCompatibilityPasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - plessEmail := "" - var code, urlWithCode *string - var codeLife uint64 - - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - plessEmail = input.PasswordlessLogin.Email - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - customCalled = true - return nil - } - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - EmailDelivery: &emaildelivery.TypeInput{ - Service: &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - }, - }, - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginEmailSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginEmailDataForTest.Email) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UrlWithLinkCode) - - // Custom handler called - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) - - // Test resend - customCalled = false - plessEmail = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) -} - -func TestCustomOverridePasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - plessEmail := "" - var code, urlWithCode *string - var codeLife uint64 - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin != nil { - customCalled = true - plessEmail = input.PasswordlessLogin.Email - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - } - return nil - } - return originalImplementation - }, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginEmailSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginEmailDataForTest.Email) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UrlWithLinkCode) - - // Custom handler called - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) - - // Test resend - customCalled = false - plessEmail = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) -} - -func TestSMTPOverridePasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - plessEmail := "" - var code, urlWithCode *string - var codeLife uint64 - - smtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordlessLogin != nil { - plessEmail = input.PasswordlessLogin.Email - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginEmailSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginEmailDataForTest.Email) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginEmailDataForTest.UrlWithLinkCode) - - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) - - // Test resend - getContentCalled = false - sendRawEmailCalled = false - plessEmail = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - assert.Equal(t, plessEmail, "test@example.com") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) -} - -func TestDefaultBackwardCompatibilityEmailVerifyForPasswordlessUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var response map[string]interface{} - json.Unmarshal(bodyBytes, &response) - - resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *passwordless.PasswordlessLoginEmailDataForTest.UserInputCode, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - - bodyBytes, err = ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - json.Unmarshal(bodyBytes, &response) - assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") - - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.False(t, emailverification.EmailVerificationEmailSentForTest) - assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) - assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) -} - -func TestDefaultBackwardCompatibilityEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{ - customProviderForEmailVerification, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{Mode: evmodels.ModeOptional}), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.True(t, emailverification.EmailVerificationEmailSentForTest) - assert.Equal(t, emailverification.EmailVerificationDataForTest.User.Email, "test@example.com") - assert.NotEmpty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) -} - -// func TestBackwardCompatibilityEmailVerifyForPasswordlessUser(t *testing.T) { -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() - -// customCalled := false -// email := "" -// emailVerifyLink := "" - -// tplConfig := tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// }, -// EmailVerificationFeature: &tplmodels.TypeInputEmailVerificationFeature{ -// CreateAndSendCustomEmail: func(user tplmodels.User, emailVerificationURLWithToken string, userContext supertokens.UserContext) { -// email = *user.Email -// emailVerifyLink = emailVerificationURLWithToken -// customCalled = true -// }, -// }, -// } -// testServer := supertokensInitForTest(t, session.Init(nil), Init(tplConfig)) -// defer testServer.Close() - -// querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") -// if err != nil { -// t.Error(err.Error()) -// } -// cdiVersion, err := querier.GetQuerierAPIVersion() -// if err != nil { -// t.Error(err.Error()) -// } -// if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { -// return -// } - -// resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) -// bodyBytes, err := ioutil.ReadAll(resp.Body) -// assert.NoError(t, err) - -// var response map[string]interface{} -// json.Unmarshal(bodyBytes, &response) - -// resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *passwordless.PasswordlessLoginEmailDataForTest.UserInputCode, testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) - -// cookies := resp.Cookies() -// resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) - -// bodyBytes, err = ioutil.ReadAll(resp.Body) -// assert.NoError(t, err) - -// json.Unmarshal(bodyBytes, &response) -// assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") - -// // Default handler not called -// assert.False(t, emailverification.EmailVerificationEmailSentForTest) -// assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) -// assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - -// // Custom handler called -// assert.Empty(t, email) -// assert.Empty(t, emailVerifyLink) -// assert.False(t, customCalled) -// } - -// func TestBackwardCompatibilityEmailVerifyForThirdpartyUser(t *testing.T) { -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() - -// customCalled := false -// email := "" -// emailVerifyLink := "" -// var thirdparty *struct { -// ID string `json:"id"` -// UserID string `json:"userId"` -// } - -// tplConfig := tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// }, -// EmailVerificationFeature: &tplmodels.TypeInputEmailVerificationFeature{ -// CreateAndSendCustomEmail: func(user tplmodels.User, emailVerificationURLWithToken string, userContext supertokens.UserContext) { -// email = *user.Email -// emailVerifyLink = emailVerificationURLWithToken -// thirdparty = user.ThirdParty -// customCalled = true -// }, -// }, -// Providers: []tpmodels.TypeProvider{customProviderForEmailVerification}, -// } -// testServer := supertokensInitForTest(t, session.Init(nil), Init(tplConfig)) -// defer testServer.Close() - -// signinupPostData := PostDataForCustomProvider{ -// ThirdPartyId: "custom", -// AuthCodeResponse: map[string]string{ -// "access_token": "saodiasjodai", -// }, -// RedirectUri: "http://127.0.0.1/callback", -// } - -// postBody, err := json.Marshal(signinupPostData) -// resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) -// assert.NoError(t, err) - -// cookies := resp.Cookies() -// resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) -// assert.NoError(t, err) -// assert.Equal(t, http.StatusOK, resp.StatusCode) - -// // Default handler not called -// assert.False(t, emailverification.EmailVerificationEmailSentForTest) -// assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) -// assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - -// // Custom handler called -// assert.Equal(t, email, "test@example.com") -// assert.NotEmpty(t, emailVerifyLink) -// assert.NotNil(t, thirdparty) -// assert.True(t, customCalled) -// } - -func TestCustomOverrideEmailVerifyForPasswordlessUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - emailVerifyLink := "" - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - sendEmail := *originalImplementation.SendEmail - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.EmailVerification != nil { - customCalled = true - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - return nil - } - return sendEmail(input, userContext) - } - return originalImplementation - }, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var response map[string]interface{} - json.Unmarshal(bodyBytes, &response) - - resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *passwordless.PasswordlessLoginEmailDataForTest.UserInputCode, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err = ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - json.Unmarshal(bodyBytes, &response) - assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") - - // Default handler not called - assert.False(t, emailverification.EmailVerificationEmailSentForTest) - assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) - assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, emailVerifyLink) - assert.False(t, customCalled) -} - -func TestCustomOverrideEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - email := "" - emailVerifyLink := "" - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - - Providers: []tpmodels.ProviderInput{customProviderForEmailVerification}, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { - sendEmail := *originalImplementation.SendEmail - *originalImplementation.SendEmail = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.EmailVerification != nil { - customCalled = true - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - return nil - } - return sendEmail(input, userContext) - } - return originalImplementation - }, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailverification.EmailVerificationEmailSentForTest) - assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) - assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - - // Custom handler called - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.True(t, customCalled) -} - -func TestSMTPOverrideEmailVerifyForPasswordlessUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - emailVerifyLink := "" - var userInputCode *string - - evSmtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.EmailVerification != nil { - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tplSmtpService := MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordlessLogin != nil { - userInputCode = input.PasswordlessLogin.UserInputCode - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - EmailDelivery: &emaildelivery.TypeInput{ - Service: tplSmtpService, - }, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Service: evSmtpService, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessEmailLoginRequest("test@example.com", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var response map[string]interface{} - json.Unmarshal(bodyBytes, &response) - - resp, err = unittesting.PasswordlessLoginWithCodeRequest(response["deviceId"].(string), response["preAuthSessionId"].(string), *userInputCode, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - sendRawEmailCalled = false // it would be true for the passwordless login, so reset it - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err = ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - json.Unmarshal(bodyBytes, &response) - assert.Equal(t, response["status"], "EMAIL_ALREADY_VERIFIED_ERROR") - - // Default handler not called - assert.False(t, emailverification.EmailVerificationEmailSentForTest) - assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) - assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - - // Custom handler not called - assert.Empty(t, email) - assert.Empty(t, emailVerifyLink) - assert.False(t, getContentCalled) - assert.False(t, sendRawEmailCalled) -} - -func TestSMTPOverrideEmailVerifyForThirdpartyUser(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawEmailCalled := false - email := "" - emailVerifyLink := "" - - smtpService := smtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: emaildelivery.SMTPSettings{ - Host: "", - From: emaildelivery.SMTPFrom{ - Name: "Test User", - Email: "", - }, - Port: 123, - Password: "", - }, - Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - (*originalImplementation.GetContent) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.EmailVerification != nil { - email = input.EmailVerification.User.Email - emailVerifyLink = input.EmailVerification.EmailVerifyLink - getContentCalled = true - } - return emaildelivery.EmailContent{}, nil - } - - (*originalImplementation.SendRawEmail) = func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - sendRawEmailCalled = true - return nil - } - - return originalImplementation - }, - }) - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ - Enabled: true, - }, - Providers: []tpmodels.ProviderInput{customProviderForEmailVerification}, - } - testServer := supertokensInitForTest( - t, - emailverification.Init(evmodels.TypeInput{ - Mode: evmodels.ModeOptional, - EmailDelivery: &emaildelivery.TypeInput{ - Service: smtpService, - }, - }), - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - signinupPostData := PostDataForCustomProvider{ - ThirdPartyId: "custom", - OAuthTokens: map[string]interface{}{ - "access_token": "saodiasjodai", - }, - } - - postBody, err := json.Marshal(signinupPostData) - resp, err := http.Post(testServer.URL+"/auth/signinup", "application/json", bytes.NewBuffer(postBody)) - assert.NoError(t, err) - - cookies := resp.Cookies() - resp, err = unittesting.EmailVerificationTokenRequest(cookies, testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - // Default handler not called - assert.False(t, emailverification.EmailVerificationEmailSentForTest) - assert.Empty(t, emailverification.EmailVerificationDataForTest.User.Email) - assert.Empty(t, emailverification.EmailVerificationDataForTest.EmailVerifyURLWithToken) - - assert.Equal(t, email, "test@example.com") - assert.NotEmpty(t, emailVerifyLink) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawEmailCalled, true) -} diff --git a/recipe/thirdpartypasswordless/tpl_sms_test.go b/recipe/thirdpartypasswordless/tpl_sms_test.go deleted file mode 100644 index 4073c82d..00000000 --- a/recipe/thirdpartypasswordless/tpl_sms_test.go +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "encoding/json" - "io/ioutil" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func TestSmsDefaultBackwardCompatibilityPasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessPhoneLoginRequest("+919876543210", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - assert.True(t, passwordless.PasswordlessLoginSmsSentForTest) - assert.Equal(t, passwordless.PasswordlessLoginSmsDataForTest.Phone, "+919876543210") - assert.NotNil(t, passwordless.PasswordlessLoginSmsDataForTest.UrlWithLinkCode) - assert.NotNil(t, passwordless.PasswordlessLoginSmsDataForTest.UserInputCode) - - // Test resend - ResetForTest() - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.True(t, passwordless.PasswordlessLoginSmsSentForTest) - assert.Equal(t, passwordless.PasswordlessLoginSmsDataForTest.Phone, "+919876543210") - assert.NotNil(t, passwordless.PasswordlessLoginSmsDataForTest.UrlWithLinkCode) - assert.NotNil(t, passwordless.PasswordlessLoginSmsDataForTest.UserInputCode) -} - -func TestSmsBackwardCompatibilityPasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - plessPhone := "" - var code, urlWithCode *string - var codeLife uint64 - - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - plessPhone = input.PasswordlessLogin.PhoneNumber - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - customCalled = true - return nil - } - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - SmsDelivery: &smsdelivery.TypeInput{ - Service: &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, - }, - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessPhoneLoginRequest("+919876543210", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginSmsSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginSmsDataForTest.Phone) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UrlWithLinkCode) - - // Custom handler called - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) - - // Test resend - customCalled = false - plessPhone = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) -} - -func TestSmsCustomOverridePasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - customCalled := false - plessPhone := "" - var code, urlWithCode *string - var codeLife uint64 - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - SmsDelivery: &smsdelivery.TypeInput{ - Override: func(originalImplementation smsdelivery.SmsDeliveryInterface) smsdelivery.SmsDeliveryInterface { - *originalImplementation.SendSms = func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin != nil { - customCalled = true - plessPhone = input.PasswordlessLogin.PhoneNumber - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - } - return nil - } - return originalImplementation - }, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessPhoneLoginRequest("+919876543210", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginSmsSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginSmsDataForTest.Phone) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UrlWithLinkCode) - - // Custom handler called - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) - - // Test resend - customCalled = false - plessPhone = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, resp.StatusCode, http.StatusOK) - - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.True(t, customCalled) -} - -func TestSmsTwilioOverridePasswordlessLogin(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - getContentCalled := false - sendRawSmsCalled := false - plessPhone := "" - var code, urlWithCode *string - var codeLife uint64 - - twilioService, err := MakeTwilioService(smsdelivery.TwilioServiceConfig{ - Settings: smsdelivery.TwilioSettings{ - AccountSid: "AC123", - AuthToken: "123", - MessagingServiceSid: "MS123", - }, - Override: func(originalImplementation smsdelivery.TwilioInterface) smsdelivery.TwilioInterface { - *originalImplementation.GetContent = func(input smsdelivery.SmsType, userContext supertokens.UserContext) (smsdelivery.SMSContent, error) { - if input.PasswordlessLogin != nil { - plessPhone = input.PasswordlessLogin.PhoneNumber - code = input.PasswordlessLogin.UserInputCode - urlWithCode = input.PasswordlessLogin.UrlWithLinkCode - codeLife = input.PasswordlessLogin.CodeLifetime - getContentCalled = true - } - return smsdelivery.SMSContent{}, nil - } - - *originalImplementation.SendRawSms = func(input smsdelivery.SMSContent, userContext supertokens.UserContext) error { - sendRawSmsCalled = true - return nil - } - - return originalImplementation - }, - }) - assert.NoError(t, err) - - tplConfig := tplmodels.TypeInput{ - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ - Enabled: true, - }, - SmsDelivery: &smsdelivery.TypeInput{ - Service: twilioService, - }, - } - testServer := supertokensInitForTest( - t, - session.Init(&sessmodels.TypeInput{ - GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { - return sessmodels.CookieTransferMethod - }, - }), - Init(tplConfig), - ) - defer testServer.Close() - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - if err != nil { - t.Error(err.Error()) - } - cdiVersion, err := querier.GetQuerierAPIVersion() - if err != nil { - t.Error(err.Error()) - } - if unittesting.MaxVersion("2.10", cdiVersion) == "2.10" { - return - } - - resp, err := unittesting.PasswordlessPhoneLoginRequest("+919876543210", testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - bodyBytes, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - body := map[string]string{} - - err = json.Unmarshal(bodyBytes, &body) - assert.NoError(t, err) - - // Default handler not called - assert.False(t, passwordless.PasswordlessLoginSmsSentForTest) - assert.Empty(t, passwordless.PasswordlessLoginSmsDataForTest.Phone) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UserInputCode) - assert.Nil(t, passwordless.PasswordlessLoginSmsDataForTest.UrlWithLinkCode) - - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawSmsCalled, true) - - // Test resend - getContentCalled = false - sendRawSmsCalled = false - plessPhone = "" - code = nil - urlWithCode = nil - codeLife = 0 - - resp, err = unittesting.PasswordlessLoginResendRequest(body["deviceId"], body["preAuthSessionId"], testServer.URL) - assert.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) - - assert.Equal(t, plessPhone, "+919876543210") - assert.NotNil(t, code) - assert.NotNil(t, urlWithCode) - assert.NotZero(t, codeLife) - assert.Equal(t, getContentCalled, true) - assert.Equal(t, sendRawSmsCalled, true) -} diff --git a/recipe/thirdpartypasswordless/tpl_userIdMapping_test.go b/recipe/thirdpartypasswordless/tpl_userIdMapping_test.go deleted file mode 100644 index 3843483e..00000000 --- a/recipe/thirdpartypasswordless/tpl_userIdMapping_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package thirdpartypasswordless - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func initForUserIdMappingTest(t *testing.T) { - - config := 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(tplmodels.TypeInput{ - ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ - Enabled: true, - }, - FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "clientID", - ClientSecret: "clientSecret", - }, - }, - }, - }, - }, - })}, - } - - err := supertokens.Init(config) - assert.NoError(t, err) -} - -func TestCreateUserIdMappingUsingEmail(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := ThirdPartyManuallyCreateOrUpdateUser("public", "google", "googleID", "test@example.com") - assert.NoError(t, err) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.OK.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - { // Using supertokens ID - userResp, err := GetUserByID(signUpResponse.OK.User.ID) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using external ID - userResp, err := GetUserByID(externalUserId) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using thirdparty info - userResp, err := GetUserByThirdPartyInfo("public", "google", "googleID") - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } -} - -func TestPlessCreateUserIdMappingUsingEmail(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := PasswordlessSignInUpByEmail("public", "test@example.com") - assert.NoError(t, err) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - { // Using supertokens ID - userResp, err := GetUserByID(signUpResponse.User.ID) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using external ID - userResp, err := GetUserByID(externalUserId) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using email - userResp, err := GetUsersByEmail("public", "test@example.com") - assert.NoError(t, err) - assert.NotNil(t, userResp) - assert.Equal(t, 1, len(userResp)) - for _, user := range userResp { - assert.Equal(t, externalUserId, user.ID) - } - } - - { // Using sign in - codeResp, err := CreateCodeWithEmail("public", "test@example.com", nil) - assert.NoError(t, err) - assert.NotNil(t, codeResp.OK) - - resp, err := ConsumeCodeWithUserInputCode("public", codeResp.OK.DeviceID, codeResp.OK.UserInputCode, codeResp.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, resp.OK) - - assert.Equal(t, externalUserId, resp.OK.User.ID) - } -} - -func TestPlessCreateUserIdMappingUsingPhone(t *testing.T) { - BeforeEach() - unittesting.StartUpST("localhost", "8080") - defer AfterEach() - - initForUserIdMappingTest(t) - - querier, err := supertokens.GetNewQuerierInstanceOrThrowError("") - assert.NoError(t, err) - - cdiVersion, err := querier.GetQuerierAPIVersion() - assert.NoError(t, err) - - if unittesting.MaxVersion(cdiVersion, "2.14") == "2.14" { - return - } - - signUpResponse, err := PasswordlessSignInUpByPhoneNumber("public", "+919876543210") - assert.NoError(t, err) - - externalUserId := "externalId" - externalUserIdInfo := "externalIdInfo" - createResp, err := supertokens.CreateUserIdMapping(signUpResponse.User.ID, externalUserId, &externalUserIdInfo, nil) - assert.NoError(t, err) - assert.NotNil(t, createResp.OK) - - { // Using supertokens ID - userResp, err := GetUserByID(signUpResponse.User.ID) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using external ID - userResp, err := GetUserByID(externalUserId) - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using email - userResp, err := GetUserByPhoneNumber("public", "+919876543210") - assert.NoError(t, err) - assert.Equal(t, externalUserId, userResp.ID) - } - - { // Using sign in - codeResp, err := CreateCodeWithPhoneNumber("public", "+919876543210", nil) - assert.NoError(t, err) - assert.NotNil(t, codeResp.OK) - - resp, err := ConsumeCodeWithUserInputCode("public", codeResp.OK.DeviceID, codeResp.OK.UserInputCode, codeResp.OK.PreAuthSessionID) - assert.NoError(t, err) - assert.NotNil(t, resp.OK) - - assert.Equal(t, externalUserId, resp.OK.User.ID) - } -} diff --git a/recipe/thirdpartypasswordless/users_test.go b/recipe/thirdpartypasswordless/users_test.go deleted file mode 100644 index 64f72331..00000000 --- a/recipe/thirdpartypasswordless/users_test.go +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -// import ( -// "net/http" -// "net/http/httptest" -// "reflect" -// "testing" -// "github.com/stretchr/testify/assert" -// "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" -// "github.com/supertokens/supertokens-golang/recipe/session" -// "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" -// "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" -// "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" -// "github.com/supertokens/supertokens-golang/supertokens" -// "github.com/supertokens/supertokens-golang/test/unittesting" -// ) - -// func TestGetUsersOldesFirst(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{ -// session.Init(&sessmodels.TypeInput{ -// GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { -// return sessmodels.CookieTransferMethod -// }, -// }), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.TypeProvider{ -// userTestCustomProvider, -// }, -// }), -// }, -// } -// "github.com/stretchr/testify/assert" -// "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" -// "github.com/supertokens/supertokens-golang/recipe/session" -// "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" -// "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" -// "github.com/supertokens/supertokens-golang/supertokens" -// "github.com/supertokens/supertokens-golang/test/unittesting" -// ) - -// func TestGetUsersOldesFirst(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{ -// session.Init(nil), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.ProviderInput{ -// userTestCustomProvider, -// }, -// }), -// }, -// } - -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() -// err := supertokens.Init(configValue) -// if err != nil { -// t.Error(err.Error()) -// } -// q, err := supertokens.GetNewQuerierInstanceOrThrowError("") -// if err != nil { -// t.Error(err.Error()) -// } -// apiV, err := q.GetQuerierAPIVersion() -// if err != nil { -// t.Error(err.Error()) -// } - -// if unittesting.MaxVersion(apiV, "2.11") == "2.11" { -// return -// } - -// mux := http.NewServeMux() -// testServer := httptest.NewServer(supertokens.Middleware(mux)) -// defer testServer.Close() - -// unittesting.SigninupCustomRequest(testServer.URL, "test@gmail.com", "testPass0") -// unittesting.SigninupCustomRequest(testServer.URL, "test1@gmail.com", "testPass1") -// unittesting.SigninupCustomRequest(testServer.URL, "test2@gmail.com", "testPass2") -// unittesting.SigninupCustomRequest(testServer.URL, "test3@gmail.com", "testPass3") -// unittesting.SigninupCustomRequest(testServer.URL, "test4@gmail.com", "testPass4") - -// userPaginationResult, err := supertokens.GetUsersOldestFirst(nil, nil, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 5, len(userPaginationResult.Users)) -// assert.Nil(t, userPaginationResult.NextPaginationToken) - -// customLimit := 1 -// userPaginationResult, err = supertokens.GetUsersOldestFirst(nil, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 1, len(userPaginationResult.Users)) -// assert.Equal(t, "test@gmail.com", userPaginationResult.Users[0].User["email"]) -// assert.Equal(t, "*string", reflect.TypeOf(userPaginationResult.NextPaginationToken).String()) - -// userPaginationResult, err = supertokens.GetUsersOldestFirst(userPaginationResult.NextPaginationToken, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 1, len(userPaginationResult.Users)) -// assert.Equal(t, "test1@gmail.com", userPaginationResult.Users[0].User["email"]) -// assert.Equal(t, "*string", reflect.TypeOf(userPaginationResult.NextPaginationToken).String()) - -// customLimit = 5 -// userPaginationResult, err = supertokens.GetUsersOldestFirst(userPaginationResult.NextPaginationToken, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 3, len(userPaginationResult.Users)) - -// customInvalidPaginationToken := "invalid-pagination-token" -// userPaginationResult, err = supertokens.GetUsersOldestFirst(&customInvalidPaginationToken, &customLimit, nil, nil) -// if err != nil { -// assert.Contains(t, err.Error(), "invalid pagination token") -// } else { -// t.Fail() -// } - -// customLimit = -1 -// userPaginationResult, err = supertokens.GetUsersOldestFirst(nil, &customLimit, nil, nil) -// if err != nil { -// assert.Contains(t, err.Error(), "limit must a positive integer with min value 1") -// } else { -// t.Fail() -// } -// } - -// func TestGetUsersNewestFirst(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{ -// session.Init(&sessmodels.TypeInput{ -// GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { -// return sessmodels.CookieTransferMethod -// }, -// }), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.TypeProvider{ -// userTestCustomProvider, -// }, -// }), -// }, -// } -// func TestGetUsersNewestFirst(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{ -// session.Init(nil), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.ProviderInput{ -// userTestCustomProvider, -// }, -// }), -// }, -// } - -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() -// err := supertokens.Init(configValue) -// if err != nil { -// t.Error(err.Error()) -// } -// q, err := supertokens.GetNewQuerierInstanceOrThrowError("") -// if err != nil { -// t.Error(err.Error()) -// } -// apiV, err := q.GetQuerierAPIVersion() -// if err != nil { -// t.Error(err.Error()) -// } - -// if unittesting.MaxVersion(apiV, "2.11") == "2.11" { -// return -// } - -// mux := http.NewServeMux() -// testServer := httptest.NewServer(supertokens.Middleware(mux)) -// defer testServer.Close() - -// unittesting.SigninupCustomRequest(testServer.URL, "test@gmail.com", "testPass0") -// unittesting.SigninupCustomRequest(testServer.URL, "test1@gmail.com", "testPass1") -// unittesting.SigninupCustomRequest(testServer.URL, "test2@gmail.com", "testPass2") -// unittesting.SigninupCustomRequest(testServer.URL, "test3@gmail.com", "testPass3") -// unittesting.SigninupCustomRequest(testServer.URL, "test4@gmail.com", "testPass4") - -// userPaginationResult, err := supertokens.GetUsersNewestFirst(nil, nil, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 5, len(userPaginationResult.Users)) -// assert.Nil(t, userPaginationResult.NextPaginationToken) - -// customLimit := 1 -// userPaginationResult, err = supertokens.GetUsersNewestFirst(nil, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 1, len(userPaginationResult.Users)) -// assert.Equal(t, "test4@gmail.com", userPaginationResult.Users[0].User["email"]) -// assert.Equal(t, "*string", reflect.TypeOf(userPaginationResult.NextPaginationToken).String()) - -// userPaginationResult, err = supertokens.GetUsersNewestFirst(userPaginationResult.NextPaginationToken, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 1, len(userPaginationResult.Users)) -// assert.Equal(t, "test3@gmail.com", userPaginationResult.Users[0].User["email"]) -// assert.Equal(t, "*string", reflect.TypeOf(userPaginationResult.NextPaginationToken).String()) - -// customLimit = 5 -// userPaginationResult, err = supertokens.GetUsersNewestFirst(userPaginationResult.NextPaginationToken, &customLimit, nil, nil) -// if err != nil { -// t.Error(err.Error()) -// } -// assert.Equal(t, 3, len(userPaginationResult.Users)) - -// customInvalidPaginationToken := "invalid-pagination-token" -// customLimit = 10 -// userPaginationResult, err = supertokens.GetUsersNewestFirst(&customInvalidPaginationToken, &customLimit, nil, nil) -// if err != nil { -// assert.Contains(t, err.Error(), "invalid pagination token") -// } else { -// t.Fail() -// } - -// customLimit = -1 -// userPaginationResult, err = supertokens.GetUsersNewestFirst(nil, &customLimit, nil, nil) -// if err != nil { -// assert.Contains(t, err.Error(), "limit must a positive integer with min value 1") -// } else { -// t.Fail() -// } -// } - -// func TestGetUserCount(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{ -// session.Init(&sessmodels.TypeInput{ -// GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { -// return sessmodels.CookieTransferMethod -// }, -// }), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.TypeProvider{ -// userTestCustomProvider, -// }, -// }), -// }, -// } -// func TestGetUserCount(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{ -// session.Init(nil), -// Init(tplmodels.TypeInput{ -// FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", -// ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ -// Enabled: true, -// CreateAndSendCustomEmail: func(email string, userInputCode, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error { -// return nil -// }, -// }, -// Providers: []tpmodels.ProviderInput{ -// userTestCustomProvider, -// }, -// }), -// }, -// } - -// BeforeEach() -// unittesting.StartUpST("localhost", "8080") -// defer AfterEach() -// err := supertokens.Init(configValue) -// if err != nil { -// t.Error(err.Error()) -// } -// q, err := supertokens.GetNewQuerierInstanceOrThrowError("") -// if err != nil { -// t.Error(err.Error()) -// } -// apiV, err := q.GetQuerierAPIVersion() -// if err != nil { -// t.Error(err.Error()) -// } - -// if unittesting.MaxVersion(apiV, "2.11") == "2.11" { -// return -// } - -// mux := http.NewServeMux() -// testServer := httptest.NewServer(supertokens.Middleware(mux)) -// defer testServer.Close() - -// userCount, err := supertokens.GetUserCount(nil) -// if err != nil { -// t.Error(err.Error()) -// } - -// assert.Equal(t, 0.0, userCount) - -// unittesting.SigninupCustomRequest(testServer.URL, "test@gmail.com", "testPass0") - -// userCount, err = supertokens.GetUserCount(nil) -// if err != nil { -// t.Error(err.Error()) -// } - -// assert.Equal(t, 1.0, userCount) - -// unittesting.SigninupCustomRequest(testServer.URL, "test1@gmail.com", "testPass1") -// unittesting.SigninupCustomRequest(testServer.URL, "test2@gmail.com", "testPass2") -// unittesting.SigninupCustomRequest(testServer.URL, "test3@gmail.com", "testPass3") -// unittesting.SigninupCustomRequest(testServer.URL, "test4@gmail.com", "testPass4") - -// userCount, err = supertokens.GetUserCount(nil) -// if err != nil { -// t.Error(err.Error()) -// } - -// assert.Equal(t, 5.0, userCount) -// } From 957f7eb941666f334863d6017bc9d775626420fb Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 10 Apr 2024 17:34:23 +0530 Subject: [PATCH 08/19] removes tpep recipe entirely --- recipe/dashboard/api/userdetails/userPut.go | 115 ----- recipe/dashboard/api/utils.go | 66 --- recipe/dashboard/userGet_test.go | 43 +- .../api/implementation.go | 168 ------- .../api/passwordlessAPIImplementation.go | 78 ---- .../api/thirdPartyAPIImplementation.go | 78 ---- .../backwardCompatibilityService/main.go | 42 -- .../emaildelivery/smtpService/main.go | 51 --- .../smtpService/plessServiceImplementation.go | 39 -- .../smtpService/serviceImplementation.go | 47 -- recipe/thirdpartypasswordless/main.go | 415 ----------------- recipe/thirdpartypasswordless/recipe.go | 223 ---------- .../recipeimplementation/main.go | 420 ------------------ .../passwordlessRecipeImplementation.go | 191 -------- .../thirdPartyRecipeImplementation.go | 140 ------ .../backwardCompatibilityService/main.go | 42 -- .../smsdelivery/supertokensService/main.go | 35 -- .../smsdelivery/twilioService/main.go | 39 -- recipe/thirdpartypasswordless/testingUtils.go | 295 ------------ .../tplmodels/apiInterface.go | 65 --- .../tplmodels/models.go | 70 --- .../tplmodels/recipeInterface.go | 92 ---- recipe/thirdpartypasswordless/utils.go | 93 ---- test/auth-react-server/main.go | 203 +++++---- 24 files changed, 137 insertions(+), 2913 deletions(-) delete mode 100644 recipe/thirdpartypasswordless/api/implementation.go delete mode 100644 recipe/thirdpartypasswordless/api/passwordlessAPIImplementation.go delete mode 100644 recipe/thirdpartypasswordless/api/thirdPartyAPIImplementation.go delete mode 100644 recipe/thirdpartypasswordless/emaildelivery/backwardCompatibilityService/main.go delete mode 100644 recipe/thirdpartypasswordless/emaildelivery/smtpService/main.go delete mode 100644 recipe/thirdpartypasswordless/emaildelivery/smtpService/plessServiceImplementation.go delete mode 100644 recipe/thirdpartypasswordless/emaildelivery/smtpService/serviceImplementation.go delete mode 100644 recipe/thirdpartypasswordless/main.go delete mode 100644 recipe/thirdpartypasswordless/recipe.go delete mode 100644 recipe/thirdpartypasswordless/recipeimplementation/main.go delete mode 100644 recipe/thirdpartypasswordless/recipeimplementation/passwordlessRecipeImplementation.go delete mode 100644 recipe/thirdpartypasswordless/recipeimplementation/thirdPartyRecipeImplementation.go delete mode 100644 recipe/thirdpartypasswordless/smsdelivery/backwardCompatibilityService/main.go delete mode 100644 recipe/thirdpartypasswordless/smsdelivery/supertokensService/main.go delete mode 100644 recipe/thirdpartypasswordless/smsdelivery/twilioService/main.go delete mode 100644 recipe/thirdpartypasswordless/testingUtils.go delete mode 100644 recipe/thirdpartypasswordless/tplmodels/apiInterface.go delete mode 100644 recipe/thirdpartypasswordless/tplmodels/models.go delete mode 100644 recipe/thirdpartypasswordless/tplmodels/recipeInterface.go delete mode 100644 recipe/thirdpartypasswordless/utils.go diff --git a/recipe/dashboard/api/userdetails/userPut.go b/recipe/dashboard/api/userdetails/userPut.go index 4320f06c..431461bc 100644 --- a/recipe/dashboard/api/userdetails/userPut.go +++ b/recipe/dashboard/api/userdetails/userPut.go @@ -25,7 +25,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/recipe/usermetadata" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -151,63 +150,6 @@ func updateEmailForRecipeId(recipeId string, userId string, email string, tenant }, nil } - if recipeId == "thirdpartypasswordless" { - isValidEmail := true - validationError := "" - - passwordlessConfig := thirdpartypasswordless.GetRecipeInstance().Config - - if passwordlessConfig.ContactMethodPhone.Enabled { - validationResult := passwordless.DefaultValidateEmailAddress(email, tenantId) - - if validationResult != nil { - isValidEmail = false - validationError = *validationResult - } - } else if passwordlessConfig.ContactMethodEmail.Enabled { - validationResult := passwordlessConfig.ContactMethodEmail.ValidateEmailAddress(email, tenantId) - - if validationResult != nil { - isValidEmail = false - validationError = *validationResult - } - } else { - validationResult := passwordlessConfig.ContactMethodEmailOrPhone.ValidateEmailAddress(email, tenantId) - - if validationResult != nil { - isValidEmail = false - validationError = *validationResult - } - } - - if !isValidEmail { - return updateEmailResponse{ - Status: "INVALID_EMAIL_ERROR", - Error: validationError, - }, nil - } - - updateResponse, updateErr := thirdpartypasswordless.UpdatePasswordlessUser(userId, &email, nil, userContext) - - if updateErr != nil { - return updateEmailResponse{}, updateErr - } - - if updateResponse.UnknownUserIdError != nil { - return updateEmailResponse{}, errors.New("Should never come here") - } - - if updateResponse.EmailAlreadyExistsError != nil { - return updateEmailResponse{ - Status: "EMAIL_ALREADY_EXISTS_ERROR", - }, nil - } - - return updateEmailResponse{ - Status: "OK", - }, nil - } - return updateEmailResponse{}, errors.New("Should never come here") } @@ -269,63 +211,6 @@ func updatePhoneForRecipeId(recipeId string, userId string, phone string, tenant }, nil } - if recipeId == "thirdpartypasswordless" { - isValidPhone := true - validationError := "" - - passwordlessConfig := thirdpartypasswordless.GetRecipeInstance().Config - - if passwordlessConfig.ContactMethodEmail.Enabled { - validationResult := passwordless.DefaultValidatePhoneNumber(phone, tenantId) - - if validationResult != nil { - isValidPhone = false - validationError = *validationResult - } - } else if passwordlessConfig.ContactMethodPhone.Enabled { - validationResult := passwordlessConfig.ContactMethodPhone.ValidatePhoneNumber(phone, tenantId) - - if validationResult != nil { - isValidPhone = false - validationError = *validationResult - } - } else { - validationResult := passwordlessConfig.ContactMethodEmailOrPhone.ValidatePhoneNumber(phone, tenantId) - - if validationResult != nil { - isValidPhone = false - validationError = *validationResult - } - } - - if !isValidPhone { - return updatePhoneResponse{ - Status: "INVALID_PHONE_ERROR", - Error: validationError, - }, nil - } - - updateResponse, updateErr := thirdpartypasswordless.UpdatePasswordlessUser(userId, nil, &phone, userContext) - - if updateErr != nil { - return updatePhoneResponse{}, updateErr - } - - if updateResponse.UnknownUserIdError != nil { - return updatePhoneResponse{}, errors.New("Should never come here") - } - - if updateResponse.EmailAlreadyExistsError != nil { - return updatePhoneResponse{ - Status: "PHONE_ALREADY_EXISTS_ERROR", - }, nil - } - - return updatePhoneResponse{ - Status: "OK", - }, nil - } - /** * If it comes here then the user is a not a passwordless user in which case the UI should not have allowed this */ diff --git a/recipe/dashboard/api/utils.go b/recipe/dashboard/api/utils.go index 5490a2bc..d20846ca 100644 --- a/recipe/dashboard/api/utils.go +++ b/recipe/dashboard/api/utils.go @@ -1,13 +1,10 @@ package api import ( - "reflect" - "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/passwordless" "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -44,7 +41,6 @@ func GetUserForRecipeId(userId string, recipeId string, userContext supertokens. } } else if recipeId == thirdparty.RECIPE_ID { response, error := thirdparty.GetUserByID(userId, userContext) - if error == nil && response != nil { userToReturn.Id = response.ID userToReturn.TimeJoined = response.TimeJoined @@ -57,31 +53,6 @@ func GetUserForRecipeId(userId string, recipeId string, userContext supertokens. } userToReturn.TenantIds = response.TenantIds } - - if reflect.DeepEqual(userToReturn, dashboardmodels.UserType{}) { - tpplessResponse, tpplessError := thirdpartypasswordless.GetUserById(userId, userContext) - - if tpplessError == nil && tpplessResponse != nil { - userToReturn.Id = tpplessResponse.ID - userToReturn.TimeJoined = tpplessResponse.TimeJoined - userToReturn.FirstName = "" - userToReturn.LastName = "" - - if tpplessResponse.Email != nil { - userToReturn.Email = *tpplessResponse.Email - } - - if tpplessResponse.PhoneNumber != nil { - userToReturn.Phone = *tpplessResponse.PhoneNumber - } - - userToReturn.ThirdParty = &dashboardmodels.ThirdParty{ - Id: tpplessResponse.ThirdParty.ID, - UserId: tpplessResponse.ThirdParty.UserID, - } - userToReturn.TenantIds = tpplessResponse.TenantIds - } - } } else if recipeId == passwordless.RECIPE_ID { response, error := passwordless.GetUserByID(userId, userContext) @@ -101,27 +72,6 @@ func GetUserForRecipeId(userId string, recipeId string, userContext supertokens. userToReturn.TenantIds = response.TenantIds } - - if reflect.DeepEqual(userToReturn, dashboardmodels.UserType{}) { - tppResponse, tppError := thirdpartypasswordless.GetUserByID(userId, userContext) - - if tppError == nil && tppResponse != nil { - userToReturn.Id = tppResponse.ID - userToReturn.TimeJoined = tppResponse.TimeJoined - userToReturn.FirstName = "" - userToReturn.LastName = "" - - if tppResponse.Email != nil { - userToReturn.Email = *tppResponse.Email - } - - if tppResponse.PhoneNumber != nil { - userToReturn.Phone = *tppResponse.PhoneNumber - } - - userToReturn.TenantIds = tppResponse.TenantIds - } - } } return userToReturn, recipeToReturn @@ -142,28 +92,12 @@ func IsRecipeInitialised(recipeId string) bool { if err == nil { isRecipeInitialised = true } - - if !isRecipeInitialised { - _, err := thirdpartypasswordless.GetRecipeInstanceOrThrowError() - - if err == nil { - isRecipeInitialised = true - } - } } else if recipeId == thirdparty.RECIPE_ID { _, err := thirdparty.GetRecipeInstanceOrThrowError() if err == nil { isRecipeInitialised = true } - - if !isRecipeInitialised { - _, err := thirdpartypasswordless.GetRecipeInstanceOrThrowError() - - if err == nil { - isRecipeInitialised = true - } - } } return isRecipeInitialised diff --git a/recipe/dashboard/userGet_test.go b/recipe/dashboard/userGet_test.go index 7f6b8b5c..c50dc010 100644 --- a/recipe/dashboard/userGet_test.go +++ b/recipe/dashboard/userGet_test.go @@ -11,11 +11,11 @@ import ( "github.com/supertokens/supertokens-golang/recipe/dashboard/api" "github.com/supertokens/supertokens-golang/recipe/dashboard/api/userdetails" "github.com/supertokens/supertokens-golang/recipe/emailpassword" + "github.com/supertokens/supertokens-golang/recipe/passwordless" "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" "github.com/stretchr/testify/assert" "github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels" @@ -85,6 +85,33 @@ func TestThatUserGetReturnsTenantIDsCorrectly(t *testing.T) { assert.Equal(t, response.User.TenantIds[0], "public") } +var customProvider1 = tpmodels.ProviderInput{ + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "custom", + AuthorizationEndpoint: "https://test.com/oauth/auth", + TokenEndpoint: "https://test.com/oauth/token", + + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "supertokens", + }, + }, + }, + + Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { + originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { + return tpmodels.TypeUserInfo{ + ThirdPartyUserId: "user", + Email: &tpmodels.EmailStruct{ + ID: "email@test.com", + IsVerified: true, + }, + }, nil + } + return originalImplementation + }, +} + func TestThatUserGetReturnsValidUserForThirdPartyUserWhenUsingThirdPartyPasswordless(t *testing.T) { config := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ @@ -96,14 +123,18 @@ func TestThatUserGetReturnsValidUserForThirdPartyUserWhenUsingThirdPartyPassword WebsiteDomain: "supertokens.io", }, RecipeList: []supertokens.Recipe{ - thirdpartypasswordless.Init(tplmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + customProvider1, + }, + }, + }), + passwordless.Init(plessmodels.TypeInput{ FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", ContactMethodEmailOrPhone: plessmodels.ContactMethodEmailOrPhoneConfig{ Enabled: true, }, - Providers: []tpmodels.ProviderInput{ - thirdpartypasswordless.SigninupCustomProvider1, - }, }), Init(&dashboardmodels.TypeInput{ ApiKey: "testapikey", diff --git a/recipe/thirdpartypasswordless/api/implementation.go b/recipe/thirdpartypasswordless/api/implementation.go deleted file mode 100644 index 2d7f7c13..00000000 --- a/recipe/thirdpartypasswordless/api/implementation.go +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - plessapi "github.com/supertokens/supertokens-golang/recipe/passwordless/api" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - tpapi "github.com/supertokens/supertokens-golang/recipe/thirdparty/api" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeAPIImplementation() tplmodels.APIInterface { - passwordlessImplementation := plessapi.MakeAPIImplementation() - thirdPartyImplementation := tpapi.MakeAPIImplementation() - - ogSignInUpPOST := *thirdPartyImplementation.SignInUpPOST - thirdPartySignInUpPOST := func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUpPOSTResponse, error) { - response, err := ogSignInUpPOST(provider, input, tenantId, options, userContext) - if err != nil { - return tplmodels.ThirdPartySignInUpPOSTResponse{}, err - } - if response.GeneralError != nil { - return tplmodels.ThirdPartySignInUpPOSTResponse{ - GeneralError: response.GeneralError, - }, nil - } else if response.NoEmailGivenByProviderError != nil { - return tplmodels.ThirdPartySignInUpPOSTResponse{ - NoEmailGivenByProviderError: &struct{}{}, - }, nil - } else { - return tplmodels.ThirdPartySignInUpPOSTResponse{ - OK: &struct { - CreatedNewUser bool - User tplmodels.User - Session *sessmodels.TypeSessionContainer - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: response.OK.CreatedNewUser, - User: tplmodels.User{ - ID: response.OK.User.ID, - TimeJoined: response.OK.User.TimeJoined, - Email: &response.OK.User.Email, - ThirdParty: &response.OK.User.ThirdParty, - }, - Session: response.OK.Session, - OAuthTokens: response.OK.OAuthTokens, - RawUserInfoFromProvider: response.OK.RawUserInfoFromProvider, - }, - }, nil - } - } - - ogAuthorisationUrlGET := *thirdPartyImplementation.AuthorisationUrlGET - authorisationUrlGET := func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - } - - ogAppleRedirectHandlerPOST := *thirdPartyImplementation.AppleRedirectHandlerPOST - appleRedirectHandlerPOST := func(formPostInfoFromProvider map[string]interface{}, options tpmodels.APIOptions, userContext supertokens.UserContext) error { - return ogAppleRedirectHandlerPOST(formPostInfoFromProvider, options, userContext) - } - - ogConsumeCodePOST := *passwordlessImplementation.ConsumeCodePOST - consumeCodePOST := func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ConsumeCodePOSTResponse, error) { - resp, err := ogConsumeCodePOST(userInput, linkCode, preAuthSessionID, tenantId, options, userContext) - if err != nil { - return tplmodels.ConsumeCodePOSTResponse{}, err - } - if resp.OK != nil { - return tplmodels.ConsumeCodePOSTResponse{ - OK: &struct { - CreatedNewUser bool - User tplmodels.User - Session sessmodels.SessionContainer - }{ - CreatedNewUser: resp.OK.CreatedNewUser, - Session: resp.OK.Session, - User: tplmodels.User{ - ID: resp.OK.User.ID, - TimeJoined: resp.OK.User.TimeJoined, - Email: resp.OK.User.Email, - PhoneNumber: resp.OK.User.PhoneNumber, - ThirdParty: nil, - }, - }, - }, nil - } else if resp.ExpiredUserInputCodeError != nil { - return tplmodels.ConsumeCodePOSTResponse{ - ExpiredUserInputCodeError: resp.ExpiredUserInputCodeError, - }, nil - } else if resp.IncorrectUserInputCodeError != nil { - return tplmodels.ConsumeCodePOSTResponse{ - IncorrectUserInputCodeError: resp.IncorrectUserInputCodeError, - }, nil - } else if resp.RestartFlowError != nil { - return tplmodels.ConsumeCodePOSTResponse{ - RestartFlowError: &struct{}{}, - }, nil - } else { - return tplmodels.ConsumeCodePOSTResponse{ - GeneralError: resp.GeneralError, - }, nil - } - } - - ogCreateCodePOST := *passwordlessImplementation.CreateCodePOST - createCodePOST := func(email *string, phoneNumber *string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.CreateCodePOSTResponse, error) { - return ogCreateCodePOST(email, phoneNumber, tenantId, options, userContext) - } - - ogEmailExistGET := *passwordlessImplementation.EmailExistsGET - passwordlessEmailExistsGET := func(email string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.EmailExistsGETResponse, error) { - return ogEmailExistGET(email, tenantId, options, userContext) - } - - ogPhoneNumberExistsGET := *passwordlessImplementation.PhoneNumberExistsGET - passwordlessPhoneNumberExistsGET := func(phoneNumber string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.PhoneNumberExistsGETResponse, error) { - return ogPhoneNumberExistsGET(phoneNumber, tenantId, options, userContext) - } - - ogResendCodePOST := *passwordlessImplementation.ResendCodePOST - resendCodePOST := func(deviceID string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ResendCodePOSTResponse, error) { - return ogResendCodePOST(deviceID, preAuthSessionID, tenantId, options, userContext) - } - - result := tplmodels.APIInterface{ - AuthorisationUrlGET: &authorisationUrlGET, - ThirdPartySignInUpPOST: &thirdPartySignInUpPOST, - AppleRedirectHandlerPOST: &appleRedirectHandlerPOST, - - CreateCodePOST: &createCodePOST, - ResendCodePOST: &resendCodePOST, - ConsumeCodePOST: &consumeCodePOST, - PasswordlessEmailExistsGET: &passwordlessEmailExistsGET, - PasswordlessPhoneNumberExistsGET: &passwordlessPhoneNumberExistsGET, - } - - modifiedPwdless := GetPasswordlessIterfaceImpl(result) - (*passwordlessImplementation.ConsumeCodePOST) = *modifiedPwdless.ConsumeCodePOST - (*passwordlessImplementation.CreateCodePOST) = *modifiedPwdless.CreateCodePOST - (*passwordlessImplementation.EmailExistsGET) = *modifiedPwdless.EmailExistsGET - (*passwordlessImplementation.PhoneNumberExistsGET) = *modifiedPwdless.PhoneNumberExistsGET - (*passwordlessImplementation.ResendCodePOST) = *modifiedPwdless.ResendCodePOST - - modifiedTP := GetThirdPartyIterfaceImpl(result) - (*thirdPartyImplementation.AuthorisationUrlGET) = *modifiedTP.AuthorisationUrlGET - (*thirdPartyImplementation.SignInUpPOST) = *modifiedTP.SignInUpPOST - (*thirdPartyImplementation.AppleRedirectHandlerPOST) = *modifiedTP.AppleRedirectHandlerPOST - - return result -} diff --git a/recipe/thirdpartypasswordless/api/passwordlessAPIImplementation.go b/recipe/thirdpartypasswordless/api/passwordlessAPIImplementation.go deleted file mode 100644 index 0cbecc9d..00000000 --- a/recipe/thirdpartypasswordless/api/passwordlessAPIImplementation.go +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func GetPasswordlessIterfaceImpl(apiImplmentation tplmodels.APIInterface) plessmodels.APIInterface { - - result := plessmodels.APIInterface{ - CreateCodePOST: apiImplmentation.CreateCodePOST, - ResendCodePOST: apiImplmentation.ResendCodePOST, - EmailExistsGET: apiImplmentation.PasswordlessEmailExistsGET, - PhoneNumberExistsGET: apiImplmentation.PasswordlessPhoneNumberExistsGET, - ConsumeCodePOST: nil, - } - - if apiImplmentation.ConsumeCodePOST != nil && (*apiImplmentation.ConsumeCodePOST) != nil { - consumeCodePOST := func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ConsumeCodePOSTResponse, error) { - result, err := (*apiImplmentation.ConsumeCodePOST)(userInput, linkCode, preAuthSessionID, tenantId, options, userContext) - if err != nil { - return plessmodels.ConsumeCodePOSTResponse{}, err - } - if result.OK != nil { - return plessmodels.ConsumeCodePOSTResponse{OK: &struct { - CreatedNewUser bool - User plessmodels.User - Session sessmodels.SessionContainer - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: plessmodels.User{ - ID: result.OK.User.ID, - Email: result.OK.User.Email, - PhoneNumber: result.OK.User.PhoneNumber, - TimeJoined: result.OK.User.TimeJoined, - }, - Session: result.OK.Session, - }}, nil - } else if result.ExpiredUserInputCodeError != nil { - return plessmodels.ConsumeCodePOSTResponse{ - ExpiredUserInputCodeError: result.ExpiredUserInputCodeError, - }, nil - } else if result.IncorrectUserInputCodeError != nil { - return plessmodels.ConsumeCodePOSTResponse{ - IncorrectUserInputCodeError: result.IncorrectUserInputCodeError, - }, nil - } else if result.RestartFlowError != nil { - return plessmodels.ConsumeCodePOSTResponse{ - RestartFlowError: &struct{}{}, - }, nil - } else { - return plessmodels.ConsumeCodePOSTResponse{ - GeneralError: result.GeneralError, - }, nil - } - } - result.ConsumeCodePOST = &consumeCodePOST - } - - return result -} diff --git a/recipe/thirdpartypasswordless/api/thirdPartyAPIImplementation.go b/recipe/thirdpartypasswordless/api/thirdPartyAPIImplementation.go deleted file mode 100644 index b5bf0341..00000000 --- a/recipe/thirdpartypasswordless/api/thirdPartyAPIImplementation.go +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package api - -import ( - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func GetThirdPartyIterfaceImpl(apiImplmentation tplmodels.APIInterface) tpmodels.APIInterface { - if apiImplmentation.ThirdPartySignInUpPOST == nil || (*apiImplmentation.ThirdPartySignInUpPOST) == nil { - return tpmodels.APIInterface{ - AuthorisationUrlGET: apiImplmentation.AuthorisationUrlGET, - AppleRedirectHandlerPOST: apiImplmentation.AppleRedirectHandlerPOST, - SignInUpPOST: nil, - } - } - - signInUpPOST := func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.SignInUpPOSTResponse, error) { - result, err := (*apiImplmentation.ThirdPartySignInUpPOST)(provider, input, tenantId, options, userContext) - if err != nil { - return tpmodels.SignInUpPOSTResponse{}, err - } - - if result.OK != nil { - return tpmodels.SignInUpPOSTResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - Session *sessmodels.TypeSessionContainer - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - TimeJoined: result.OK.User.TimeJoined, - Email: *result.OK.User.Email, - TenantIds: result.OK.User.TenantIds, - ThirdParty: *result.OK.User.ThirdParty, - }, - Session: result.OK.Session, - OAuthTokens: result.OK.OAuthTokens, - RawUserInfoFromProvider: result.OK.RawUserInfoFromProvider, - }, - }, nil - } else if result.NoEmailGivenByProviderError != nil { - return tpmodels.SignInUpPOSTResponse{ - NoEmailGivenByProviderError: &struct{}{}, - }, nil - } else { - return tpmodels.SignInUpPOSTResponse{ - GeneralError: result.GeneralError, - }, nil - } - } - - return tpmodels.APIInterface{ - AuthorisationUrlGET: apiImplmentation.AuthorisationUrlGET, - AppleRedirectHandlerPOST: apiImplmentation.AppleRedirectHandlerPOST, - SignInUpPOST: &signInUpPOST, - } -} diff --git a/recipe/thirdpartypasswordless/emaildelivery/backwardCompatibilityService/main.go b/recipe/thirdpartypasswordless/emaildelivery/backwardCompatibilityService/main.go deleted file mode 100644 index 196904c5..00000000 --- a/recipe/thirdpartypasswordless/emaildelivery/backwardCompatibilityService/main.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package backwardCompatibilityService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - passwordlessBackwardsCompatibilityService "github.com/supertokens/supertokens-golang/recipe/passwordless/emaildelivery/backwardCompatibilityService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeBackwardCompatibilityService(appInfo supertokens.NormalisedAppinfo, sendPasswordlessLoginEmail func(email string, userInputCode *string, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error) emaildelivery.EmailDeliveryInterface { - passwordlessService := passwordlessBackwardsCompatibilityService.MakeBackwardCompatibilityService(appInfo, sendPasswordlessLoginEmail) - - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin != nil { - return (*passwordlessService.SendEmail)(input, userContext) - - } else { - return errors.New("should never come here") - } - } - - return emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - } -} diff --git a/recipe/thirdpartypasswordless/emaildelivery/smtpService/main.go b/recipe/thirdpartypasswordless/emaildelivery/smtpService/main.go deleted file mode 100644 index 88eee5d6..00000000 --- a/recipe/thirdpartypasswordless/emaildelivery/smtpService/main.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package smtpService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - plesssmtpService "github.com/supertokens/supertokens-golang/recipe/passwordless/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeSMTPService(config emaildelivery.SMTPServiceConfig) *emaildelivery.EmailDeliveryInterface { - serviceImpl := makeServiceImplementation(config.Settings) - - if config.Override != nil { - serviceImpl = config.Override(serviceImpl) - } - - passwordlessServiceImpl := plesssmtpService.MakeSMTPService(emaildelivery.SMTPServiceConfig{ - Settings: config.Settings, - Override: makePasswordlessServiceImplementation(serviceImpl), - }) - - sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin != nil { - return (*passwordlessServiceImpl.SendEmail)(input, userContext) - - } else { - return errors.New("should never come here") - } - } - - return &emaildelivery.EmailDeliveryInterface{ - SendEmail: &sendEmail, - } -} diff --git a/recipe/thirdpartypasswordless/emaildelivery/smtpService/plessServiceImplementation.go b/recipe/thirdpartypasswordless/emaildelivery/smtpService/plessServiceImplementation.go deleted file mode 100644 index c11b4b65..00000000 --- a/recipe/thirdpartypasswordless/emaildelivery/smtpService/plessServiceImplementation.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package smtpService - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func makePasswordlessServiceImplementation(serviceImpl emaildelivery.SMTPInterface) func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - return func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface { - sendRawEmail := func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - return (*serviceImpl.SendRawEmail)(input, userContext) - } - - getContent := func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - return (*serviceImpl.GetContent)(input, userContext) - } - - return emaildelivery.SMTPInterface{ - SendRawEmail: &sendRawEmail, - GetContent: &getContent, - } - } -} diff --git a/recipe/thirdpartypasswordless/emaildelivery/smtpService/serviceImplementation.go b/recipe/thirdpartypasswordless/emaildelivery/smtpService/serviceImplementation.go deleted file mode 100644 index 90191e25..00000000 --- a/recipe/thirdpartypasswordless/emaildelivery/smtpService/serviceImplementation.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package smtpService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - plesssmtpService "github.com/supertokens/supertokens-golang/recipe/passwordless/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func makeServiceImplementation(settings emaildelivery.SMTPSettings) emaildelivery.SMTPInterface { - sendRawEmail := func(input emaildelivery.EmailContent, userContext supertokens.UserContext) error { - return emaildelivery.SendSMTPEmail(settings, input) - } - - plessServiceImpl := plesssmtpService.MakeServiceImplementation(settings) - - getContent := func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) { - if input.PasswordlessLogin != nil { - return (*plessServiceImpl.GetContent)(input, userContext) - - } else { - return emaildelivery.EmailContent{}, errors.New("should never come here") - } - } - - return emaildelivery.SMTPInterface{ - SendRawEmail: &sendRawEmail, - GetContent: &getContent, - } -} diff --git a/recipe/thirdpartypasswordless/main.go b/recipe/thirdpartypasswordless/main.go deleted file mode 100644 index ed7c6710..00000000 --- a/recipe/thirdpartypasswordless/main.go +++ /dev/null @@ -1,415 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/emaildelivery/smtpService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/smsdelivery/supertokensService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/smsdelivery/twilioService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func Init(config tplmodels.TypeInput) supertokens.Recipe { - return recipeInit(config) -} - -func ThirdPartyManuallyCreateOrUpdateUser(tenantId string, thirdPartyID string, thirdPartyUserID string, email string, userContext ...supertokens.UserContext) (tplmodels.ManuallyCreateOrUpdateUserResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tplmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ThirdPartyManuallyCreateOrUpdateUser)(thirdPartyID, thirdPartyUserID, email, tenantId, userContext[0]) -} - -func ThirdPartyGetProvider(tenantId string, thirdPartyID string, clientType *string, userContext ...supertokens.UserContext) (*tpmodels.TypeProvider, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ThirdPartyGetProvider)(thirdPartyID, clientType, tenantId, userContext[0]) -} - -func GetUserByThirdPartyInfo(tenantId string, thirdPartyID string, thirdPartyUserID string, userContext ...supertokens.UserContext) (*tplmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByThirdPartyInfo)(thirdPartyID, thirdPartyUserID, tenantId, userContext[0]) -} - -func GetUserById(userID string, userContext ...supertokens.UserContext) (*tplmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByID)(userID, userContext[0]) -} - -func GetUsersByEmail(tenantId string, email string, userContext ...supertokens.UserContext) ([]tplmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUsersByEmail)(email, tenantId, userContext[0]) -} - -func CreateCodeWithEmail(tenantId string, email string, userInputCode *string, userContext ...supertokens.UserContext) (plessmodels.CreateCodeResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.CreateCodeResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.CreateCode)(&email, nil, userInputCode, tenantId, userContext[0]) -} - -func CreateCodeWithPhoneNumber(tenantId string, phoneNumber string, userInputCode *string, userContext ...supertokens.UserContext) (plessmodels.CreateCodeResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.CreateCodeResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.CreateCode)(nil, &phoneNumber, userInputCode, tenantId, userContext[0]) -} - -func CreateNewCodeForDevice(tenantId string, deviceID string, userInputCode *string, userContext ...supertokens.UserContext) (plessmodels.ResendCodeResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.ResendCodeResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.CreateNewCodeForDevice)(deviceID, userInputCode, tenantId, userContext[0]) -} - -func ConsumeCodeWithUserInputCode(tenantId string, deviceID string, userInputCode string, preAuthSessionID string, userContext ...supertokens.UserContext) (tplmodels.ConsumeCodeResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tplmodels.ConsumeCodeResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ConsumeCode)(&plessmodels.UserInputCodeWithDeviceID{ - Code: userInputCode, - DeviceID: deviceID, - }, nil, preAuthSessionID, tenantId, userContext[0]) -} - -func ConsumeCodeWithLinkCode(tenantId string, linkCode string, preAuthSessionID string, userContext ...supertokens.UserContext) (tplmodels.ConsumeCodeResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return tplmodels.ConsumeCodeResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ConsumeCode)(nil, &linkCode, preAuthSessionID, tenantId, userContext[0]) -} - -func GetUserByID(userID string, userContext ...supertokens.UserContext) (*tplmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByID)(userID, userContext[0]) -} - -func GetUserByPhoneNumber(tenantId string, phoneNumber string, userContext ...supertokens.UserContext) (*tplmodels.User, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.GetUserByPhoneNumber)(phoneNumber, tenantId, userContext[0]) -} - -func UpdatePasswordlessUser(userID string, email *string, phoneNumber *string, userContext ...supertokens.UserContext) (plessmodels.UpdateUserResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.UpdateUserResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.UpdatePasswordlessUser)(userID, email, phoneNumber, userContext[0]) -} - -func DeleteEmailForPasswordlessUser(userID string, userContext ...supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.DeleteUserResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.DeleteEmailForPasswordlessUser)(userID, userContext[0]) -} - -func DeletePhoneNumberForUser(userID string, userContext ...supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return plessmodels.DeleteUserResponse{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.DeletePhoneNumberForUser)(userID, userContext[0]) -} - -func RevokeAllCodesByEmail(tenantId string, email string, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.RevokeAllCodes)(&email, nil, tenantId, userContext[0]) -} - -func RevokeAllCodesByPhoneNumber(tenantId string, phoneNumber string, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.RevokeAllCodes)(nil, &phoneNumber, tenantId, userContext[0]) -} - -func RevokeCode(tenantId string, codeID string, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.RevokeCode)(codeID, tenantId, userContext[0]) -} - -func ListCodesByEmail(tenantId string, email string, userContext ...supertokens.UserContext) ([]plessmodels.DeviceType, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return []plessmodels.DeviceType{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ListCodesByEmail)(email, tenantId, userContext[0]) -} - -func ListCodesByPhoneNumber(tenantId string, phoneNumber string, userContext ...supertokens.UserContext) ([]plessmodels.DeviceType, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return []plessmodels.DeviceType{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ListCodesByPhoneNumber)(phoneNumber, tenantId, userContext[0]) -} - -func ListCodesByDeviceID(tenantId string, deviceID string, userContext ...supertokens.UserContext) (*plessmodels.DeviceType, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ListCodesByDeviceID)(deviceID, tenantId, userContext[0]) -} - -func ListCodesByPreAuthSessionID(tenantId string, preAuthSessionID string, userContext ...supertokens.UserContext) (*plessmodels.DeviceType, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return nil, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.RecipeImpl.ListCodesByPreAuthSessionID)(preAuthSessionID, tenantId, userContext[0]) -} - -func CreateMagicLinkByEmail(tenantId string, email string, userContext ...supertokens.UserContext) (string, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return "", err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return instance.passwordlessRecipe.CreateMagicLink(&email, nil, tenantId, userContext[0]) -} - -func CreateMagicLinkByPhoneNumber(tenantId string, phoneNumber string, userContext ...supertokens.UserContext) (string, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return "", err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return instance.passwordlessRecipe.CreateMagicLink(nil, &phoneNumber, tenantId, userContext[0]) -} - -func PasswordlessSignInUpByEmail(tenantId string, email string, userContext ...supertokens.UserContext) (struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User -}, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - resp, err := instance.passwordlessRecipe.SignInUp(&email, nil, tenantId, userContext[0]) - if err != nil { - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{}, err - } - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{ - PreAuthSessionID: resp.PreAuthSessionID, - CreatedNewUser: resp.CreatedNewUser, - User: tplmodels.User{ - ID: resp.User.ID, - TimeJoined: resp.User.TimeJoined, - Email: resp.User.Email, - PhoneNumber: resp.User.PhoneNumber, - ThirdParty: nil, - }, - }, nil -} - -func PasswordlessSignInUpByPhoneNumber(tenantId string, phoneNumber string, userContext ...supertokens.UserContext) (struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User -}, error) { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{}, err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - resp, err := instance.passwordlessRecipe.SignInUp(nil, &phoneNumber, tenantId, userContext[0]) - if err != nil { - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{}, err - } - return struct { - PreAuthSessionID string - CreatedNewUser bool - User tplmodels.User - }{ - PreAuthSessionID: resp.PreAuthSessionID, - CreatedNewUser: resp.CreatedNewUser, - User: tplmodels.User{ - ID: resp.User.ID, - TimeJoined: resp.User.TimeJoined, - Email: resp.User.Email, - PhoneNumber: resp.User.PhoneNumber, - ThirdParty: nil, - }, - }, nil -} - -func SendEmail(input emaildelivery.EmailType, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.EmailDelivery.IngredientInterfaceImpl.SendEmail)(input, userContext[0]) -} - -func SendSms(input smsdelivery.SmsType, userContext ...supertokens.UserContext) error { - instance, err := GetRecipeInstanceOrThrowError() - if err != nil { - return err - } - if len(userContext) == 0 { - userContext = append(userContext, &map[string]interface{}{}) - } - return (*instance.SmsDelivery.IngredientInterfaceImpl.SendSms)(input, userContext[0]) -} - -func MakeSMTPService(config emaildelivery.SMTPServiceConfig) *emaildelivery.EmailDeliveryInterface { - return smtpService.MakeSMTPService(config) -} - -func MakeTwilioService(config smsdelivery.TwilioServiceConfig) (*smsdelivery.SmsDeliveryInterface, error) { - return twilioService.MakeTwilioService(config) -} - -func MakeSupertokensSMSService(apiKey string) *smsdelivery.SmsDeliveryInterface { - return supertokensService.MakeSupertokensSMSService(apiKey) -} diff --git a/recipe/thirdpartypasswordless/recipe.go b/recipe/thirdpartypasswordless/recipe.go deleted file mode 100644 index e4566516..00000000 --- a/recipe/thirdpartypasswordless/recipe.go +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "errors" - "net/http" - - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/api" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/recipeimplementation" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -const RECIPE_ID = "thirdpartypasswordless" - -type Recipe struct { - RecipeModule supertokens.RecipeModule - Config tplmodels.TypeNormalisedInput - passwordlessRecipe *passwordless.Recipe - thirdPartyRecipe *thirdparty.Recipe - RecipeImpl tplmodels.RecipeInterface - APIImpl tplmodels.APIInterface - EmailDelivery emaildelivery.Ingredient - SmsDelivery smsdelivery.Ingredient -} - -var singletonInstance *Recipe - -func MakeRecipe(recipeId string, appInfo supertokens.NormalisedAppinfo, config tplmodels.TypeInput, thirdPartyInstance *thirdparty.Recipe, passwordlessInstance *passwordless.Recipe, emailDeliveryIngredient *emaildelivery.Ingredient, smsDeliveryIngredient *smsdelivery.Ingredient, onSuperTokensAPIError func(err error, req *http.Request, res http.ResponseWriter)) (Recipe, error) { - r := &Recipe{} - r.RecipeModule = supertokens.MakeRecipeModule(recipeId, appInfo, r.handleAPIRequest, r.getAllCORSHeaders, r.getAPIsHandled, nil, r.handleError, onSuperTokensAPIError) - - verifiedConfig, err := validateAndNormaliseUserInput(r, appInfo, config) - if err != nil { - return Recipe{}, err - } - r.Config = verifiedConfig - { - passwordlessquerierInstance, err := supertokens.GetNewQuerierInstanceOrThrowError(passwordless.RECIPE_ID) - if err != nil { - return Recipe{}, err - } - thirdpartyquerierInstance, err := supertokens.GetNewQuerierInstanceOrThrowError(thirdparty.RECIPE_ID) - if err != nil { - return Recipe{}, err - } - - r.RecipeImpl = verifiedConfig.Override.Functions(recipeimplementation.MakeRecipeImplementation(*passwordlessquerierInstance, thirdpartyquerierInstance, verifiedConfig.Providers)) - } - r.APIImpl = verifiedConfig.Override.APIs(api.MakeAPIImplementation()) - - if emailDeliveryIngredient != nil { - r.EmailDelivery = *emailDeliveryIngredient - } else { - r.EmailDelivery = emaildelivery.MakeIngredient(verifiedConfig.GetEmailDeliveryConfig()) - } - - if smsDeliveryIngredient != nil { - r.SmsDelivery = *smsDeliveryIngredient - } else { - r.SmsDelivery = smsdelivery.MakeIngredient(verifiedConfig.GetSmsDeliveryConfig()) - } - - var passwordlessRecipe passwordless.Recipe - if passwordlessInstance == nil { - passwordlessConfig := plessmodels.TypeInput{ - ContactMethodPhone: verifiedConfig.ContactMethodPhone, - ContactMethodEmail: verifiedConfig.ContactMethodEmail, - ContactMethodEmailOrPhone: verifiedConfig.ContactMethodEmailOrPhone, - FlowType: verifiedConfig.FlowType, - GetCustomUserInputCode: verifiedConfig.GetCustomUserInputCode, - Override: &plessmodels.OverrideStruct{ - Functions: func(originalImplementation plessmodels.RecipeInterface) plessmodels.RecipeInterface { - return recipeimplementation.MakePasswordlessRecipeImplementation(r.RecipeImpl) - }, - APIs: func(originalImplementation plessmodels.APIInterface) plessmodels.APIInterface { - return api.GetPasswordlessIterfaceImpl(r.APIImpl) - }, - }, - } - passwordlessRecipe, err = passwordless.MakeRecipe(recipeId, appInfo, passwordlessConfig, &r.EmailDelivery, &r.SmsDelivery, onSuperTokensAPIError) - if err != nil { - return Recipe{}, err - } - r.passwordlessRecipe = &passwordlessRecipe - } else { - r.passwordlessRecipe = passwordlessInstance - } - - if thirdPartyInstance == nil { - thirdPartyConfig := &tpmodels.TypeInput{ - SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ - Providers: verifiedConfig.Providers, - }, - Override: &tpmodels.OverrideStruct{ - Functions: func(_ tpmodels.RecipeInterface) tpmodels.RecipeInterface { - return recipeimplementation.MakeThirdPartyRecipeImplementation(r.RecipeImpl) - }, - APIs: func(_ tpmodels.APIInterface) tpmodels.APIInterface { - return api.GetThirdPartyIterfaceImpl(r.APIImpl) - }, - }, - } - thirdPartyRecipeinstance, err := thirdparty.MakeRecipe(recipeId, appInfo, thirdPartyConfig, &r.EmailDelivery, onSuperTokensAPIError) - if err != nil { - return Recipe{}, err - } - r.thirdPartyRecipe = &thirdPartyRecipeinstance - } else { - r.thirdPartyRecipe = thirdPartyInstance - } - - return *r, nil -} - -func recipeInit(config tplmodels.TypeInput) supertokens.Recipe { - return func(appInfo supertokens.NormalisedAppinfo, onSuperTokensAPIError func(err error, req *http.Request, res http.ResponseWriter)) (*supertokens.RecipeModule, error) { - if singletonInstance == nil { - recipe, err := MakeRecipe(RECIPE_ID, appInfo, config, nil, nil, nil, nil, onSuperTokensAPIError) - if err != nil { - return nil, err - } - singletonInstance = &recipe - return &singletonInstance.RecipeModule, nil - } - return nil, errors.New("ThirdPartyPasswordless recipe has already been initialised. Please check your code for bugs.") - } -} - -func GetRecipeInstanceOrThrowError() (*Recipe, error) { - if singletonInstance != nil { - return singletonInstance, nil - } - return nil, errors.New("Initialisation not done. Did you forget to call the init function?") -} - -func GetRecipeInstance() *Recipe { - return singletonInstance -} - -// implement RecipeModule - -func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { - passwordlessAPIhandled, err := r.passwordlessRecipe.RecipeModule.GetAPIsHandled() - if err != nil { - return nil, err - } - apisHandled := passwordlessAPIhandled - if r.thirdPartyRecipe != nil { - thirdpartyAPIhandled, err := r.thirdPartyRecipe.RecipeModule.GetAPIsHandled() - if err != nil { - return nil, err - } - apisHandled = append(apisHandled, thirdpartyAPIhandled...) - } - return apisHandled, nil -} - -func (r *Recipe) handleAPIRequest(id string, tenantId string, req *http.Request, res http.ResponseWriter, theirHandler http.HandlerFunc, path supertokens.NormalisedURLPath, method string, userContext supertokens.UserContext) error { - ok, _, err := r.passwordlessRecipe.RecipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) - if err != nil { - return err - } - if ok != nil { - return r.passwordlessRecipe.RecipeModule.HandleAPIRequest(id, tenantId, req, res, theirHandler, path, method, userContext) - } - if r.thirdPartyRecipe != nil { - ok, _, err := r.thirdPartyRecipe.RecipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) - if err != nil { - return err - } - if ok != nil { - return r.thirdPartyRecipe.RecipeModule.HandleAPIRequest(id, tenantId, req, res, theirHandler, path, method, userContext) - } - } - return errors.New("should not come here") -} - -func (r *Recipe) getAllCORSHeaders() []string { - corsHeaders := r.passwordlessRecipe.RecipeModule.GetAllCORSHeaders() - if r.thirdPartyRecipe != nil { - corsHeaders = append(corsHeaders, r.thirdPartyRecipe.RecipeModule.GetAllCORSHeaders()...) - } - return corsHeaders -} - -func (r *Recipe) handleError(err error, req *http.Request, res http.ResponseWriter, userContext supertokens.UserContext) (bool, error) { - handleError, err := r.passwordlessRecipe.RecipeModule.HandleError(err, req, res, userContext) - if err != nil || handleError { - return handleError, err - } - if r.thirdPartyRecipe != nil { - handleError, err = r.thirdPartyRecipe.RecipeModule.HandleError(err, req, res, userContext) - if err != nil || handleError { - return handleError, err - } - } - return false, nil -} - -func ResetForTest() { - singletonInstance = nil -} diff --git a/recipe/thirdpartypasswordless/recipeimplementation/main.go b/recipe/thirdpartypasswordless/recipeimplementation/main.go deleted file mode 100644 index b1cb8f0e..00000000 --- a/recipe/thirdpartypasswordless/recipeimplementation/main.go +++ /dev/null @@ -1,420 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeRecipeImplementation(passwordlessQuerier supertokens.Querier, thirdPartyQuerier *supertokens.Querier, providers []tpmodels.ProviderInput) tplmodels.RecipeInterface { - result := tplmodels.RecipeInterface{} - - passwordlessImplementation := passwordless.MakeRecipeImplementation(passwordlessQuerier) - var thirdPartyImplementation *tpmodels.RecipeInterface - if thirdPartyQuerier != nil { - thirdPartyImplementationTemp := thirdparty.MakeRecipeImplementation(*thirdPartyQuerier, providers) - thirdPartyImplementation = &thirdPartyImplementationTemp - } - - var ogSignInUp func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) = nil - if thirdPartyImplementation != nil { - ogSignInUp = *thirdPartyImplementation.SignInUp - } - thirPartySignInUp := func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUp, error) { - if ogSignInUp == nil { - return tplmodels.ThirdPartySignInUp{}, errors.New("no thirdparty provider configured") - } - result, err := ogSignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) - if err != nil { - return tplmodels.ThirdPartySignInUp{}, err - } - return tplmodels.ThirdPartySignInUp{ - OK: &struct { - CreatedNewUser bool - User tplmodels.User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tplmodels.User{ - ID: result.OK.User.ID, - TimeJoined: result.OK.User.TimeJoined, - Email: &result.OK.User.Email, - ThirdParty: &result.OK.User.ThirdParty, - }, - }, - }, nil - } - - var ogManuallyCreateOrUpdateUser func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tpmodels.ManuallyCreateOrUpdateUserResponse, error) = nil - if thirdPartyImplementation != nil { - ogManuallyCreateOrUpdateUser = *thirdPartyImplementation.ManuallyCreateOrUpdateUser - } - - thirdPartyManuallyCreateOrUpdateUser := func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tplmodels.ManuallyCreateOrUpdateUserResponse, error) { - if ogManuallyCreateOrUpdateUser == nil { - return tplmodels.ManuallyCreateOrUpdateUserResponse{}, errors.New("no thirdparty provider configured") - } - result, err := ogManuallyCreateOrUpdateUser(thirdPartyID, thirdPartyUserID, email, tenantId, userContext) - if err != nil { - return tplmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - return tplmodels.ManuallyCreateOrUpdateUserResponse{ - OK: &struct { - CreatedNewUser bool - User tplmodels.User - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tplmodels.User{ - ID: result.OK.User.ID, - TimeJoined: result.OK.User.TimeJoined, - Email: &result.OK.User.Email, - ThirdParty: &result.OK.User.ThirdParty, - }, - }, - }, nil - } - - var ogGetProvider func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) = nil - if thirdPartyImplementation != nil { - ogGetProvider = *thirdPartyImplementation.GetProvider - } - - thirdPartyGetProvider := func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) { - if ogGetProvider == nil { - return nil, errors.New("no thirdparty provider configured") - } - return ogGetProvider(thirdPartyID, clientType, tenantId, userContext) - } - - ogPlessGetUserByID := *passwordlessImplementation.GetUserByID - var ogTPGetUserById func(userID string, userContext supertokens.UserContext) (*tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogTPGetUserById = *thirdPartyImplementation.GetUserByID - } - getUserByID := func(userID string, userContext supertokens.UserContext) (*tplmodels.User, error) { - user, err := ogPlessGetUserByID(userID, userContext) - if err != nil { - return nil, err - } - if user != nil { - return &tplmodels.User{ - ID: user.ID, - Email: user.Email, - PhoneNumber: user.PhoneNumber, - TimeJoined: user.TimeJoined, - TenantIds: user.TenantIds, - ThirdParty: nil, - }, nil - } - if ogTPGetUserById == nil { - return nil, nil - } - - userinfo, err := ogTPGetUserById(userID, userContext) - if err != nil { - return nil, err - } - - if userinfo != nil { - return &tplmodels.User{ - ID: userinfo.ID, - Email: &userinfo.Email, - PhoneNumber: nil, - TimeJoined: userinfo.TimeJoined, - TenantIds: userinfo.TenantIds, - ThirdParty: &userinfo.ThirdParty, - }, nil - } - return nil, nil - } - - ogPlessGetUserByEmail := *passwordlessImplementation.GetUserByEmail - var ogTPGetUsersByEmail func(email string, tenantId string, userContext supertokens.UserContext) ([]tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogTPGetUsersByEmail = *thirdPartyImplementation.GetUsersByEmail - } - getUsersByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]tplmodels.User, error) { - fromPless, err := ogPlessGetUserByEmail(email, tenantId, userContext) - if err != nil { - return []tplmodels.User{}, err - } - - fromTP := []tpmodels.User{} - if ogTPGetUsersByEmail != nil { - fromTP, err = ogTPGetUsersByEmail(email, tenantId, userContext) - if err != nil { - return []tplmodels.User{}, err - } - } - finalResult := []tplmodels.User{} - - if fromPless != nil { - finalResult = append(finalResult, tplmodels.User{ - ID: fromPless.ID, - TimeJoined: fromPless.TimeJoined, - Email: fromPless.Email, - PhoneNumber: fromPless.PhoneNumber, - ThirdParty: nil, - }) - } - - for _, tpUser := range fromTP { - finalResult = append(finalResult, tplmodels.User{ - ID: tpUser.ID, - TimeJoined: tpUser.TimeJoined, - Email: &tpUser.Email, - PhoneNumber: nil, - ThirdParty: &tpUser.ThirdParty, - }) - } - - return finalResult, nil - } - - var ogGetUserByThirdPartyInfo func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tpmodels.User, error) = nil - if thirdPartyImplementation != nil { - ogGetUserByThirdPartyInfo = *thirdPartyImplementation.GetUserByThirdPartyInfo - } - getUserByThirdPartyInfo := func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tplmodels.User, error) { - if ogGetUserByThirdPartyInfo == nil { - return nil, nil - } - - userinfo, err := ogGetUserByThirdPartyInfo(thirdPartyID, thirdPartyUserID, tenantId, userContext) - if err != nil { - return nil, err - } - - if userinfo != nil { - return &tplmodels.User{ - ID: userinfo.ID, - Email: &userinfo.Email, - PhoneNumber: nil, - TimeJoined: userinfo.TimeJoined, - TenantIds: userinfo.TenantIds, - ThirdParty: &userinfo.ThirdParty, - }, nil - } - return nil, nil - } - - ogCreateCode := *passwordlessImplementation.CreateCode - createCode := func(email *string, phoneNumber *string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.CreateCodeResponse, error) { - return ogCreateCode(email, phoneNumber, userInputCode, tenantId, userContext) - } - - ogConsumeCode := *passwordlessImplementation.ConsumeCode - consumeCode := func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (tplmodels.ConsumeCodeResponse, error) { - response, err := ogConsumeCode(userInput, linkCode, preAuthSessionID, tenantId, userContext) - if err != nil { - return tplmodels.ConsumeCodeResponse{}, err - } - - if response.ExpiredUserInputCodeError != nil { - return tplmodels.ConsumeCodeResponse{ - ExpiredUserInputCodeError: response.ExpiredUserInputCodeError, - }, nil - } else if response.IncorrectUserInputCodeError != nil { - return tplmodels.ConsumeCodeResponse{ - IncorrectUserInputCodeError: response.IncorrectUserInputCodeError, - }, nil - } else if response.RestartFlowError != nil { - return tplmodels.ConsumeCodeResponse{ - RestartFlowError: &struct{}{}, - }, nil - } - - return tplmodels.ConsumeCodeResponse{ - OK: &struct { - CreatedNewUser bool - User tplmodels.User - }{ - CreatedNewUser: response.OK.CreatedNewUser, - User: tplmodels.User{ - ID: response.OK.User.ID, - TimeJoined: response.OK.User.TimeJoined, - Email: response.OK.User.Email, - PhoneNumber: response.OK.User.PhoneNumber, - ThirdParty: nil, - }, - }, - }, nil - } - - ogCreateNewCodeForDevice := *passwordlessImplementation.CreateNewCodeForDevice - createNewCodeForDevice := func(deviceID string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.ResendCodeResponse, error) { - return ogCreateNewCodeForDevice(deviceID, userInputCode, tenantId, userContext) - } - - ogGetUserByPhoneNumber := *passwordlessImplementation.GetUserByPhoneNumber - getUserByPhoneNumber := func(phoneNumber string, tenantId string, userContext supertokens.UserContext) (*tplmodels.User, error) { - resp, err := ogGetUserByPhoneNumber(phoneNumber, tenantId, userContext) - if err != nil { - return &tplmodels.User{}, err - } - - if resp == nil { - return nil, nil - } - - return &tplmodels.User{ - ID: resp.ID, - TimeJoined: resp.TimeJoined, - Email: resp.Email, - PhoneNumber: resp.PhoneNumber, - ThirdParty: nil, - }, nil - } - - ogListCodesByDeviceID := *passwordlessImplementation.ListCodesByDeviceID - listCodesByDeviceID := func(deviceID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) { - return ogListCodesByDeviceID(deviceID, tenantId, userContext) - } - - ogListCodesByEmail := *passwordlessImplementation.ListCodesByEmail - listCodesByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) { - return ogListCodesByEmail(email, tenantId, userContext) - } - - ogListCodesByPhoneNumber := *passwordlessImplementation.ListCodesByPhoneNumber - listCodesByPhoneNumber := func(phoneNumber string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) { - return ogListCodesByPhoneNumber(phoneNumber, tenantId, userContext) - } - - ogListCodesByPreAuthSessionID := *passwordlessImplementation.ListCodesByPreAuthSessionID - listCodesByPreAuthSessionID := func(preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) { - return ogListCodesByPreAuthSessionID(preAuthSessionID, tenantId, userContext) - } - - ogRevokeAllCodes := *passwordlessImplementation.RevokeAllCodes - revokeAllCodes := func(email *string, phoneNumber *string, tenantId string, userContext supertokens.UserContext) error { - return ogRevokeAllCodes(email, phoneNumber, tenantId, userContext) - } - - ogRevokeCode := *passwordlessImplementation.RevokeCode - revokeCode := func(codeID string, tenantId string, userContext supertokens.UserContext) error { - return ogRevokeCode(codeID, tenantId, userContext) - } - - ogUpdateUser := *passwordlessImplementation.UpdateUser - updatePasswordlessUser := func(userID string, email *string, phoneNumber *string, userContext supertokens.UserContext) (plessmodels.UpdateUserResponse, error) { - user, err := (*result.GetUserByID)(userID, userContext) - if err != nil { - return plessmodels.UpdateUserResponse{}, err - } - - if user == nil { - return plessmodels.UpdateUserResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } else if user.ThirdParty != nil { - return plessmodels.UpdateUserResponse{}, errors.New("cannot update passwordless user info for those who signed up using third party login") - } - return ogUpdateUser(userID, email, phoneNumber, userContext) - } - - ogDeleteEmailForUser := *passwordlessImplementation.DeleteEmailForUser - deleteEmailForPasswordlessUser := func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - user, err := (*result.GetUserByID)(userID, userContext) - if err != nil { - return plessmodels.DeleteUserResponse{}, err - } - - if user == nil { - return plessmodels.DeleteUserResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } else if user.ThirdParty != nil { - return plessmodels.DeleteUserResponse{}, errors.New("cannot update passwordless user info for those who signed up using third party login") - } - return ogDeleteEmailForUser(userID, userContext) - } - - ogDeletePhoneNumberForUser := *passwordlessImplementation.DeletePhoneNumberForUser - deletePhoneNumberForPasswordlessUser := func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - user, err := (*result.GetUserByID)(userID, userContext) - if err != nil { - return plessmodels.DeleteUserResponse{}, err - } - - if user == nil { - return plessmodels.DeleteUserResponse{ - UnknownUserIdError: &struct{}{}, - }, nil - } else if user.ThirdParty != nil { - return plessmodels.DeleteUserResponse{}, errors.New("cannot update passwordless user info for those who signed up using third party login") - } - return ogDeletePhoneNumberForUser(userID, userContext) - } - - result.GetUserByID = &getUserByID - result.GetUsersByEmail = &getUsersByEmail - result.GetUserByThirdPartyInfo = &getUserByThirdPartyInfo - result.ThirdPartySignInUp = &thirPartySignInUp - result.ThirdPartyManuallyCreateOrUpdateUser = &thirdPartyManuallyCreateOrUpdateUser - result.ThirdPartyGetProvider = &thirdPartyGetProvider - result.ConsumeCode = &consumeCode - result.CreateCode = &createCode - result.CreateNewCodeForDevice = &createNewCodeForDevice - result.GetUserByPhoneNumber = &getUserByPhoneNumber - result.ListCodesByDeviceID = &listCodesByDeviceID - result.ListCodesByEmail = &listCodesByEmail - result.ListCodesByPhoneNumber = &listCodesByPhoneNumber - result.ListCodesByPreAuthSessionID = &listCodesByPreAuthSessionID - result.RevokeAllCodes = &revokeAllCodes - result.RevokeCode = &revokeCode - result.UpdatePasswordlessUser = &updatePasswordlessUser - result.DeleteEmailForPasswordlessUser = &deleteEmailForPasswordlessUser - result.DeletePhoneNumberForUser = &deletePhoneNumberForPasswordlessUser - - modifiedPwdless := MakePasswordlessRecipeImplementation(result) - (*passwordlessImplementation.ConsumeCode) = *modifiedPwdless.ConsumeCode - (*passwordlessImplementation.CreateCode) = *modifiedPwdless.CreateCode - (*passwordlessImplementation.CreateNewCodeForDevice) = *modifiedPwdless.CreateNewCodeForDevice - (*passwordlessImplementation.GetUserByEmail) = *modifiedPwdless.GetUserByEmail - (*passwordlessImplementation.GetUserByID) = *modifiedPwdless.GetUserByID - (*passwordlessImplementation.GetUserByPhoneNumber) = *modifiedPwdless.GetUserByPhoneNumber - (*passwordlessImplementation.ListCodesByDeviceID) = *modifiedPwdless.ListCodesByDeviceID - (*passwordlessImplementation.ListCodesByEmail) = *modifiedPwdless.ListCodesByEmail - (*passwordlessImplementation.ListCodesByPhoneNumber) = *modifiedPwdless.ListCodesByPhoneNumber - (*passwordlessImplementation.ListCodesByPreAuthSessionID) = *modifiedPwdless.ListCodesByPreAuthSessionID - (*passwordlessImplementation.RevokeAllCodes) = *modifiedPwdless.RevokeAllCodes - (*passwordlessImplementation.RevokeCode) = *modifiedPwdless.RevokeCode - (*passwordlessImplementation.UpdateUser) = *modifiedPwdless.UpdateUser - (*passwordlessImplementation.DeleteEmailForUser) = *modifiedPwdless.DeleteEmailForUser - (*passwordlessImplementation.DeletePhoneNumberForUser) = *modifiedPwdless.DeletePhoneNumberForUser - - if thirdPartyImplementation != nil { - modifiedTp := MakeThirdPartyRecipeImplementation(result) - (*thirdPartyImplementation.GetUserByID) = *modifiedTp.GetUserByID - (*thirdPartyImplementation.GetUserByThirdPartyInfo) = *modifiedTp.GetUserByThirdPartyInfo - (*thirdPartyImplementation.GetUsersByEmail) = *modifiedTp.GetUsersByEmail - (*thirdPartyImplementation.GetProvider) = *modifiedTp.GetProvider - (*thirdPartyImplementation.SignInUp) = *modifiedTp.SignInUp - (*thirdPartyImplementation.ManuallyCreateOrUpdateUser) = *modifiedTp.ManuallyCreateOrUpdateUser - (*thirdPartyImplementation.GetProvider) = *modifiedTp.GetProvider - } - - return result -} diff --git a/recipe/thirdpartypasswordless/recipeimplementation/passwordlessRecipeImplementation.go b/recipe/thirdpartypasswordless/recipeimplementation/passwordlessRecipeImplementation.go deleted file mode 100644 index 0fa14bd0..00000000 --- a/recipe/thirdpartypasswordless/recipeimplementation/passwordlessRecipeImplementation.go +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakePasswordlessRecipeImplementation(recipeImplementation tplmodels.RecipeInterface) plessmodels.RecipeInterface { - createCode := func(email *string, phoneNumber *string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.CreateCodeResponse, error) { - return (*recipeImplementation.CreateCode)(email, phoneNumber, userInputCode, tenantId, userContext) - } - - consumeCode := func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (plessmodels.ConsumeCodeResponse, error) { - resp, err := (*recipeImplementation.ConsumeCode)(userInput, linkCode, preAuthSessionID, tenantId, userContext) - - if err != nil { - return plessmodels.ConsumeCodeResponse{}, err - } - - if resp.ExpiredUserInputCodeError != nil { - return plessmodels.ConsumeCodeResponse{ - ExpiredUserInputCodeError: resp.ExpiredUserInputCodeError, - }, nil - } else if resp.IncorrectUserInputCodeError != nil { - return plessmodels.ConsumeCodeResponse{ - IncorrectUserInputCodeError: resp.IncorrectUserInputCodeError, - }, nil - } else if resp.RestartFlowError != nil { - return plessmodels.ConsumeCodeResponse{ - RestartFlowError: &struct{}{}, - }, nil - } else { - return plessmodels.ConsumeCodeResponse{ - OK: &struct { - CreatedNewUser bool - User plessmodels.User - }{ - CreatedNewUser: resp.OK.CreatedNewUser, - User: plessmodels.User{ - ID: resp.OK.User.ID, - Email: resp.OK.User.Email, - PhoneNumber: resp.OK.User.PhoneNumber, - TimeJoined: resp.OK.User.TimeJoined, - }, - }, - }, nil - } - } - - createNewCodeForDevice := func(deviceID string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.ResendCodeResponse, error) { - return (*recipeImplementation.CreateNewCodeForDevice)(deviceID, userInputCode, tenantId, userContext) - } - - getUserByEmail := func(email string, tenantId string, userContext supertokens.UserContext) (*plessmodels.User, error) { - resp, err := (*recipeImplementation.GetUsersByEmail)(email, tenantId, userContext) - if err != nil { - return nil, err - } - - for _, user := range resp { - if user.ThirdParty == nil { - return &plessmodels.User{ - ID: user.ID, - Email: user.Email, - PhoneNumber: user.PhoneNumber, - TimeJoined: user.TimeJoined, - }, nil - } - } - - return nil, nil - } - - getUserByID := func(userID string, userContext supertokens.UserContext) (*plessmodels.User, error) { - resp, err := (*recipeImplementation.GetUserByID)(userID, userContext) - - if err != nil { - return nil, err - } - - if resp == nil { - return nil, nil - } - - if resp.ThirdParty != nil { - // this is a thirdparty user - return nil, nil - } - - return &plessmodels.User{ - ID: resp.ID, - Email: resp.Email, - PhoneNumber: resp.PhoneNumber, - TimeJoined: resp.TimeJoined, - }, nil - } - - getUserByPhoneNumber := func(phoneNumber string, tenantId string, userContext supertokens.UserContext) (*plessmodels.User, error) { - resp, err := (*recipeImplementation.GetUserByPhoneNumber)(phoneNumber, tenantId, userContext) - - if err != nil { - return nil, err - } - - if resp == nil { - return nil, nil - } - - if resp.ThirdParty != nil { - // this is a thirdparty user - return nil, nil - } - - return &plessmodels.User{ - ID: resp.ID, - Email: resp.Email, - PhoneNumber: resp.PhoneNumber, - TimeJoined: resp.TimeJoined, - }, nil - } - - listCodesByDeviceID := func(deviceID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) { - return (*recipeImplementation.ListCodesByDeviceID)(deviceID, tenantId, userContext) - } - - listCodesByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) { - return (*recipeImplementation.ListCodesByEmail)(email, tenantId, userContext) - } - - listCodesByPhoneNumber := func(phoneNumber string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) { - return (*recipeImplementation.ListCodesByPhoneNumber)(phoneNumber, tenantId, userContext) - } - - listCodesByPreAuthSessionID := func(preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) { - return (*recipeImplementation.ListCodesByPreAuthSessionID)(preAuthSessionID, tenantId, userContext) - } - - revokeAllCodes := func(email *string, phoneNumber *string, tenantId string, userContext supertokens.UserContext) error { - return (*recipeImplementation.RevokeAllCodes)(email, phoneNumber, tenantId, userContext) - } - - revokeCode := func(codeID string, tenantId string, userContext supertokens.UserContext) error { - return (*recipeImplementation.RevokeCode)(codeID, tenantId, userContext) - } - - updateUser := func(userID string, email *string, phoneNumber *string, userContext supertokens.UserContext) (plessmodels.UpdateUserResponse, error) { - return (*recipeImplementation.UpdatePasswordlessUser)(userID, email, phoneNumber, userContext) - } - - deleteEmailForUser := func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - return (*recipeImplementation.DeleteEmailForPasswordlessUser)(userID, userContext) - } - - deletePhoneNumberForUser := func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) { - return (*recipeImplementation.DeletePhoneNumberForUser)(userID, userContext) - } - - return plessmodels.RecipeInterface{ - CreateCode: &createCode, - ConsumeCode: &consumeCode, - CreateNewCodeForDevice: &createNewCodeForDevice, - GetUserByEmail: &getUserByEmail, - GetUserByID: &getUserByID, - GetUserByPhoneNumber: &getUserByPhoneNumber, - ListCodesByDeviceID: &listCodesByDeviceID, - ListCodesByEmail: &listCodesByEmail, - ListCodesByPhoneNumber: &listCodesByPhoneNumber, - ListCodesByPreAuthSessionID: &listCodesByPreAuthSessionID, - RevokeAllCodes: &revokeAllCodes, - RevokeCode: &revokeCode, - UpdateUser: &updateUser, - DeleteEmailForUser: &deleteEmailForUser, - DeletePhoneNumberForUser: &deletePhoneNumberForUser, - } -} diff --git a/recipe/thirdpartypasswordless/recipeimplementation/thirdPartyRecipeImplementation.go b/recipe/thirdpartypasswordless/recipeimplementation/thirdPartyRecipeImplementation.go deleted file mode 100644 index 18f02919..00000000 --- a/recipe/thirdpartypasswordless/recipeimplementation/thirdPartyRecipeImplementation.go +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package recipeimplementation - -import ( - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeThirdPartyRecipeImplementation(recipeImplementation tplmodels.RecipeInterface) tpmodels.RecipeInterface { - - getUserByThirdPartyInfo := func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*tpmodels.User, error) { - user, err := (*recipeImplementation.GetUserByThirdPartyInfo)(thirdPartyID, thirdPartyUserID, tenantId, userContext) - if err != nil { - return nil, err - } - if user == nil || user.ThirdParty == nil { - return nil, nil - } - return &tpmodels.User{ - ID: user.ID, - Email: *user.Email, - TimeJoined: user.TimeJoined, - TenantIds: user.TenantIds, - ThirdParty: *user.ThirdParty, - }, nil - } - - signInUp := func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) { - result, err := (*recipeImplementation.ThirdPartySignInUp)(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext) - if err != nil { - return tpmodels.SignInUpResponse{}, err - } - - return tpmodels.SignInUpResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - Email: *result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - ThirdParty: *result.OK.User.ThirdParty, - }, - OAuthTokens: result.OK.OAuthTokens, - RawUserInfoFromProvider: result.OK.RawUserInfoFromProvider, - }, - }, nil - } - - manuallyCreateOrUpdateUser := func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (tpmodels.ManuallyCreateOrUpdateUserResponse, error) { - result, err := (*recipeImplementation.ThirdPartyManuallyCreateOrUpdateUser)(thirdPartyID, thirdPartyUserID, email, tenantId, userContext) - if err != nil { - return tpmodels.ManuallyCreateOrUpdateUserResponse{}, err - } - - return tpmodels.ManuallyCreateOrUpdateUserResponse{ - OK: &struct { - CreatedNewUser bool - User tpmodels.User - }{ - CreatedNewUser: result.OK.CreatedNewUser, - User: tpmodels.User{ - ID: result.OK.User.ID, - Email: *result.OK.User.Email, - TimeJoined: result.OK.User.TimeJoined, - ThirdParty: *result.OK.User.ThirdParty, - }, - }, - }, nil - } - - getUserByID := func(userID string, userContext supertokens.UserContext) (*tpmodels.User, error) { - user, err := (*recipeImplementation.GetUserByID)(userID, userContext) - if err != nil { - return nil, err - } - if user == nil || user.ThirdParty == nil { - return nil, nil - } - return &tpmodels.User{ - ID: user.ID, - Email: *user.Email, - TimeJoined: user.TimeJoined, - ThirdParty: *user.ThirdParty, - }, nil - } - - getUserByEmail := func(email string, tenantId string, userContext supertokens.UserContext) ([]tpmodels.User, error) { - users, err := (*recipeImplementation.GetUsersByEmail)(email, tenantId, userContext) - if err != nil { - return nil, err - } - - finalResult := []tpmodels.User{} - - for _, tpepUser := range users { - if tpepUser.ThirdParty != nil { - finalResult = append(finalResult, tpmodels.User{ - ID: tpepUser.ID, - TimeJoined: tpepUser.TimeJoined, - Email: *tpepUser.Email, - ThirdParty: *tpepUser.ThirdParty, - }) - } - } - return finalResult, nil - } - - getProvider := func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) { - return (*recipeImplementation.ThirdPartyGetProvider)(thirdPartyID, clientType, tenantId, userContext) - } - - return tpmodels.RecipeInterface{ - GetUserByID: &getUserByID, - GetUsersByEmail: &getUserByEmail, - GetUserByThirdPartyInfo: &getUserByThirdPartyInfo, - SignInUp: &signInUp, - ManuallyCreateOrUpdateUser: &manuallyCreateOrUpdateUser, - GetProvider: &getProvider, - } -} diff --git a/recipe/thirdpartypasswordless/smsdelivery/backwardCompatibilityService/main.go b/recipe/thirdpartypasswordless/smsdelivery/backwardCompatibilityService/main.go deleted file mode 100644 index f198ff40..00000000 --- a/recipe/thirdpartypasswordless/smsdelivery/backwardCompatibilityService/main.go +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package backwardCompatibilityService - -import ( - "errors" - - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/smsdelivery/backwardCompatibilityService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeBackwardCompatibilityService(createAndSendCustomSms func(phoneNumber string, userInputCode *string, urlWithLinkCode *string, codeLifetime uint64, preAuthSessionId string, userContext supertokens.UserContext) error) smsdelivery.SmsDeliveryInterface { - plessBackwardCompatibilityService := backwardCompatibilityService.MakeBackwardCompatibilityService(createAndSendCustomSms) - - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - if input.PasswordlessLogin != nil { - return (*plessBackwardCompatibilityService.SendSms)(input, userContext) - - } else { - return errors.New("should never come here") - } - } - - return smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - } -} diff --git a/recipe/thirdpartypasswordless/smsdelivery/supertokensService/main.go b/recipe/thirdpartypasswordless/smsdelivery/supertokensService/main.go deleted file mode 100644 index e9e14c36..00000000 --- a/recipe/thirdpartypasswordless/smsdelivery/supertokensService/main.go +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package supertokensService - -import ( - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/smsdelivery/supertokensService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeSupertokensSMSService(apiKey string) *smsdelivery.SmsDeliveryInterface { - plessService := supertokensService.MakeSupertokensSMSService(apiKey) - - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - return (*plessService.SendSms)(input, userContext) - } - - return &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - } -} diff --git a/recipe/thirdpartypasswordless/smsdelivery/twilioService/main.go b/recipe/thirdpartypasswordless/smsdelivery/twilioService/main.go deleted file mode 100644 index 941760c7..00000000 --- a/recipe/thirdpartypasswordless/smsdelivery/twilioService/main.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package twilioService - -import ( - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/smsdelivery/twilioService" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func MakeTwilioService(config smsdelivery.TwilioServiceConfig) (*smsdelivery.SmsDeliveryInterface, error) { - plessServiceImpl, err := twilioService.MakeTwilioService(config) - - if err != nil { - return nil, err - } - - sendSms := func(input smsdelivery.SmsType, userContext supertokens.UserContext) error { - return (*plessServiceImpl.SendSms)(input, userContext) - } - - return &smsdelivery.SmsDeliveryInterface{ - SendSms: &sendSms, - }, nil -} diff --git a/recipe/thirdpartypasswordless/testingUtils.go b/recipe/thirdpartypasswordless/testingUtils.go deleted file mode 100644 index 80a87d2f..00000000 --- a/recipe/thirdpartypasswordless/testingUtils.go +++ /dev/null @@ -1,295 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "errors" - "github.com/supertokens/supertokens-golang/recipe/session" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/supertokens/supertokens-golang/recipe/emailverification" - "github.com/supertokens/supertokens-golang/recipe/multitenancy" - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/thirdparty" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" - "github.com/supertokens/supertokens-golang/test/unittesting" -) - -func resetAll() { - supertokens.ResetForTest() - ResetForTest() - emailverification.ResetForTest() - thirdparty.ResetForTest() - passwordless.ResetForTest() - session.ResetForTest() - multitenancy.ResetForTest() -} - -func BeforeEach() { - unittesting.KillAllST() - resetAll() - unittesting.SetUpST() -} - -func AfterEach() { - unittesting.KillAllST() - resetAll() - unittesting.CleanST() -} - -var customProvider1 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - AuthorizationEndpointQueryParams: map[string]interface{}{ - "scope": "test", - "client_id": "supertokens", - }, - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: true, - }, - }, nil - - } - return originalImplementation - }, -} - -var mockThirdPartyProvider1 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "mock1", - }, -} - -var mockThirdPartyProvider2 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "mock2", - }, -} - -var SigninupCustomProvider1 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: true, - }, - }, nil - } - return originalImplementation - }, -} - -var signinupCustomProvider3 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - }, nil - } - return originalImplementation - }, -} - -var signinupCustomProvider4 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{}, errors.New("error from getUserInfo") - } - return originalImplementation - }, -} - -var signinupCustomProvider5 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: false, - }, - }, nil - } - return originalImplementation - }, -} - -var signinupCustomProvider6 = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - if oAuthTokens["access_token"] == nil { - return tpmodels.TypeUserInfo{}, nil - } - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "email@test.com", - IsVerified: true, - }, - }, nil - } - return originalImplementation - }, -} - -var userTestCustomProvider = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: oAuthTokens["id"].(string), - Email: &tpmodels.EmailStruct{ - ID: oAuthTokens["email"].(string), - IsVerified: true, - }, - }, nil - } - return originalImplementation - }, -} - -type PostDataForCustomProvider struct { - ThirdPartyId string `json:"thirdPartyId"` - OAuthTokens map[string]interface{} `json:"oAuthTokens"` - // RedirectUri string `json:"redirectURI"` -} - -var customProviderForEmailVerification = tpmodels.ProviderInput{ - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "custom", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: "supertokens", - }, - }, - AuthorizationEndpoint: "https://test.com/oauth/auth", - TokenEndpoint: "https://test.com/oauth/token", - }, - Override: func(originalImplementation *tpmodels.TypeProvider) *tpmodels.TypeProvider { - originalImplementation.GetUserInfo = func(oAuthTokens tpmodels.TypeOAuthTokens, userContext supertokens.UserContext) (tpmodels.TypeUserInfo, error) { - if oAuthTokens["access_token"] == nil { - return tpmodels.TypeUserInfo{}, nil - } - return tpmodels.TypeUserInfo{ - ThirdPartyUserId: "user", - Email: &tpmodels.EmailStruct{ - ID: "test@example.com", - IsVerified: false, - }, - }, nil - } - return originalImplementation - }, -} - -func supertokensInitForTest(t *testing.T, recipes ...supertokens.Recipe) *httptest.Server { - config := supertokens.TypeInput{ - Supertokens: &supertokens.ConnectionInfo{ - ConnectionURI: "http://localhost:8080", - }, - AppInfo: supertokens.AppInfo{ - APIDomain: "api.supertokens.io", - AppName: "SuperTokens", - WebsiteDomain: "supertokens.io", - }, - RecipeList: recipes, - } - - err := supertokens.Init(config) - assert.NoError(t, err) - - mux := http.NewServeMux() - testServer := httptest.NewServer(supertokens.Middleware(mux)) - return testServer -} diff --git a/recipe/thirdpartypasswordless/tplmodels/apiInterface.go b/recipe/thirdpartypasswordless/tplmodels/apiInterface.go deleted file mode 100644 index 21545554..00000000 --- a/recipe/thirdpartypasswordless/tplmodels/apiInterface.go +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tplmodels - -import ( - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -type APIInterface struct { - AuthorisationUrlGET *func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) - AppleRedirectHandlerPOST *func(formPostInfoFromProvider map[string]interface{}, options tpmodels.APIOptions, userContext supertokens.UserContext) error - ThirdPartySignInUpPOST *func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (ThirdPartySignInUpPOSTResponse, error) - - CreateCodePOST *func(email *string, phoneNumber *string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.CreateCodePOSTResponse, error) - ResendCodePOST *func(deviceID string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ResendCodePOSTResponse, error) - ConsumeCodePOST *func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (ConsumeCodePOSTResponse, error) - PasswordlessEmailExistsGET *func(email string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.EmailExistsGETResponse, error) - PasswordlessPhoneNumberExistsGET *func(email string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.PhoneNumberExistsGETResponse, error) -} - -type ConsumeCodePOSTResponse struct { - OK *struct { - CreatedNewUser bool - User User - Session sessmodels.SessionContainer - } - IncorrectUserInputCodeError *struct { - FailedCodeInputAttemptCount int - MaximumCodeInputAttempts int - } - ExpiredUserInputCodeError *struct { - FailedCodeInputAttemptCount int - MaximumCodeInputAttempts int - } - RestartFlowError *struct{} - GeneralError *supertokens.GeneralErrorResponse -} - -type ThirdPartySignInUpPOSTResponse struct { - OK *struct { - CreatedNewUser bool - User User - Session sessmodels.SessionContainer - OAuthTokens tpmodels.TypeOAuthTokens - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - } - NoEmailGivenByProviderError *struct{} - GeneralError *supertokens.GeneralErrorResponse -} diff --git a/recipe/thirdpartypasswordless/tplmodels/models.go b/recipe/thirdpartypasswordless/tplmodels/models.go deleted file mode 100644 index 30e157fe..00000000 --- a/recipe/thirdpartypasswordless/tplmodels/models.go +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tplmodels - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -type User struct { - ID string `json:"id"` - TimeJoined uint64 `json:"timeJoined"` - Email *string `json:"email"` - PhoneNumber *string `json:"phoneNumber"` - ThirdParty *struct { - ID string `json:"id"` - UserID string `json:"userId"` - } `json:"thirdParty"` - TenantIds []string `json:"tenantIds"` -} - -type TypeInput struct { - ContactMethodPhone plessmodels.ContactMethodPhoneConfig - ContactMethodEmail plessmodels.ContactMethodEmailConfig - ContactMethodEmailOrPhone plessmodels.ContactMethodEmailOrPhoneConfig - FlowType string - GetCustomUserInputCode func(tenantId string, userContext supertokens.UserContext) (string, error) - Providers []tpmodels.ProviderInput - Override *OverrideStruct - EmailDelivery *emaildelivery.TypeInput - SmsDelivery *smsdelivery.TypeInput -} - -type TypeNormalisedInput struct { - ContactMethodPhone plessmodels.ContactMethodPhoneConfig - ContactMethodEmail plessmodels.ContactMethodEmailConfig - ContactMethodEmailOrPhone plessmodels.ContactMethodEmailOrPhoneConfig - FlowType string - GetCustomUserInputCode func(tenantId string, userContext supertokens.UserContext) (string, error) - Providers []tpmodels.ProviderInput - Override OverrideStruct - GetEmailDeliveryConfig func() emaildelivery.TypeInputWithService - GetSmsDeliveryConfig func() smsdelivery.TypeInputWithService -} - -type OverrideStruct struct { - Functions func(originalImplementation RecipeInterface) RecipeInterface - APIs func(originalImplementation APIInterface) APIInterface -} - -type EmailStruct struct { - ID string `json:"id"` - IsVerified bool `json:"isVerified"` -} diff --git a/recipe/thirdpartypasswordless/tplmodels/recipeInterface.go b/recipe/thirdpartypasswordless/tplmodels/recipeInterface.go deleted file mode 100644 index 8f306b56..00000000 --- a/recipe/thirdpartypasswordless/tplmodels/recipeInterface.go +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package tplmodels - -import ( - "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -type RecipeInterface struct { - GetUserByID *func(userID string, userContext supertokens.UserContext) (*User, error) - GetUsersByEmail *func(email string, tenantId string, userContext supertokens.UserContext) ([]User, error) - GetUserByPhoneNumber *func(phoneNumber string, tenantId string, userContext supertokens.UserContext) (*User, error) - GetUserByThirdPartyInfo *func(thirdPartyID string, thirdPartyUserID string, tenantId string, userContext supertokens.UserContext) (*User, error) - - ThirdPartySignInUp *func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (ThirdPartySignInUp, error) - ThirdPartyManuallyCreateOrUpdateUser *func(thirdPartyID string, thirdPartyUserID string, email string, tenantId string, userContext supertokens.UserContext) (ManuallyCreateOrUpdateUserResponse, error) - ThirdPartyGetProvider *func(thirdPartyID string, clientType *string, tenantId string, userContext supertokens.UserContext) (*tpmodels.TypeProvider, error) - - CreateCode *func(email *string, phoneNumber *string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.CreateCodeResponse, error) - CreateNewCodeForDevice *func(deviceID string, userInputCode *string, tenantId string, userContext supertokens.UserContext) (plessmodels.ResendCodeResponse, error) - ConsumeCode *func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (ConsumeCodeResponse, error) - UpdatePasswordlessUser *func(userID string, email *string, phoneNumber *string, userContext supertokens.UserContext) (plessmodels.UpdateUserResponse, error) - DeleteEmailForPasswordlessUser *func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) - DeletePhoneNumberForUser *func(userID string, userContext supertokens.UserContext) (plessmodels.DeleteUserResponse, error) - RevokeAllCodes *func(email *string, phoneNumber *string, tenantId string, userContext supertokens.UserContext) error - RevokeCode *func(codeID string, tenantId string, userContext supertokens.UserContext) error - ListCodesByEmail *func(email string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) - ListCodesByPhoneNumber *func(phoneNumber string, tenantId string, userContext supertokens.UserContext) ([]plessmodels.DeviceType, error) - ListCodesByDeviceID *func(deviceID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) - ListCodesByPreAuthSessionID *func(preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (*plessmodels.DeviceType, error) -} - -type ConsumeCodeResponse struct { - OK *struct { - CreatedNewUser bool - User User - } - IncorrectUserInputCodeError *struct { - FailedCodeInputAttemptCount int - MaximumCodeInputAttempts int - } - ExpiredUserInputCodeError *struct { - FailedCodeInputAttemptCount int - MaximumCodeInputAttempts int - } - RestartFlowError *struct{} -} - -type ThirdPartySignInUp struct { - OK *struct { - CreatedNewUser bool - User User - OAuthTokens map[string]interface{} - RawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider - } -} - -type ManuallyCreateOrUpdateUserResponse struct { - OK *struct { - CreatedNewUser bool - User User - } -} - -type SignUpResponse struct { - OK *struct { - User User - } - EmailAlreadyExistsError *struct{} -} - -type SignInResponse struct { - OK *struct { - User User - } - WrongCredentialsError *struct{} -} diff --git a/recipe/thirdpartypasswordless/utils.go b/recipe/thirdpartypasswordless/utils.go deleted file mode 100644 index c0233af8..00000000 --- a/recipe/thirdpartypasswordless/utils.go +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. - * - * This software is licensed under the Apache License, Version 2.0 (the - * "License") as published by the Apache Software Foundation. - * - * You may not use this file except in compliance with the License. You may - * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -package thirdpartypasswordless - -import ( - "github.com/supertokens/supertokens-golang/ingredients/emaildelivery" - "github.com/supertokens/supertokens-golang/ingredients/smsdelivery" - "github.com/supertokens/supertokens-golang/recipe/passwordless" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/emaildelivery/backwardCompatibilityService" - smsBackwardCompatibilityService "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/smsdelivery/backwardCompatibilityService" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" - "github.com/supertokens/supertokens-golang/supertokens" -) - -func validateAndNormaliseUserInput(recipeInstance *Recipe, appInfo supertokens.NormalisedAppinfo, config tplmodels.TypeInput) (tplmodels.TypeNormalisedInput, error) { - typeNormalisedInput := makeTypeNormalisedInput(recipeInstance, config) - - typeNormalisedInput.GetEmailDeliveryConfig = func() emaildelivery.TypeInputWithService { - sendPasswordlessLoginEmail := passwordless.DefaultCreateAndSendCustomEmail(appInfo) - - emailService := backwardCompatibilityService.MakeBackwardCompatibilityService(appInfo, sendPasswordlessLoginEmail) - if config.EmailDelivery != nil && config.EmailDelivery.Service != nil { - emailService = *config.EmailDelivery.Service - } - result := emaildelivery.TypeInputWithService{ - Service: emailService, - } - if config.EmailDelivery != nil && config.EmailDelivery.Override != nil { - result.Override = config.EmailDelivery.Override - } - - return result - } - - typeNormalisedInput.GetSmsDeliveryConfig = func() smsdelivery.TypeInputWithService { - sendPasswordlessLoginSms := passwordless.DefaultCreateAndSendCustomTextMessage(appInfo) - - smsService := smsBackwardCompatibilityService.MakeBackwardCompatibilityService(sendPasswordlessLoginSms) - if config.SmsDelivery != nil && config.SmsDelivery.Service != nil { - smsService = *config.SmsDelivery.Service - } - result := smsdelivery.TypeInputWithService{ - Service: smsService, - } - if config.SmsDelivery != nil && config.SmsDelivery.Override != nil { - result.Override = config.SmsDelivery.Override - } - return result - } - - if config.Override != nil { - if config.Override.Functions != nil { - typeNormalisedInput.Override.Functions = config.Override.Functions - } - if config.Override.APIs != nil { - typeNormalisedInput.Override.APIs = config.Override.APIs - } - } - - return typeNormalisedInput, nil -} - -func makeTypeNormalisedInput(recipeInstance *Recipe, inputConfig tplmodels.TypeInput) tplmodels.TypeNormalisedInput { - return tplmodels.TypeNormalisedInput{ - Providers: inputConfig.Providers, - ContactMethodPhone: inputConfig.ContactMethodPhone, - ContactMethodEmail: inputConfig.ContactMethodEmail, - ContactMethodEmailOrPhone: inputConfig.ContactMethodEmailOrPhone, - FlowType: inputConfig.FlowType, - GetCustomUserInputCode: inputConfig.GetCustomUserInputCode, - Override: tplmodels.OverrideStruct{ - Functions: func(originalImplementation tplmodels.RecipeInterface) tplmodels.RecipeInterface { - return originalImplementation - }, - APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - return originalImplementation - }, - }, - } -} diff --git a/test/auth-react-server/main.go b/test/auth-react-server/main.go index ef4418bc..60139127 100644 --- a/test/auth-react-server/main.go +++ b/test/auth-react-server/main.go @@ -44,8 +44,6 @@ import ( "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless" - "github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels" "github.com/supertokens/supertokens-golang/recipe/userroles" "github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims" "github.com/supertokens/supertokens-golang/supertokens" @@ -92,7 +90,6 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { passwordless.ResetForTest() session.ResetForTest() thirdparty.ResetForTest() - thirdpartypasswordless.ResetForTest() userroles.ResetForTest() multitenancy.ResetForTest() @@ -530,111 +527,111 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { }, }, }), - thirdpartypasswordless.Init(tplmodels.TypeInput{ - ContactMethodPhone: passwordlessConfig.ContactMethodPhone, - ContactMethodEmail: passwordlessConfig.ContactMethodEmail, - ContactMethodEmailOrPhone: passwordlessConfig.ContactMethodEmailOrPhone, - FlowType: passwordlessConfig.FlowType, - GetCustomUserInputCode: passwordlessConfig.GetCustomUserInputCode, - EmailDelivery: passwordlessConfig.EmailDelivery, - SmsDelivery: passwordlessConfig.SmsDelivery, - Providers: []tpmodels.ProviderInput{ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("GOOGLE_CLIENT_ID"), - ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), - }, - }, - }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("GITHUB_CLIENT_ID"), - ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), - }, - }, - }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "facebook", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), - ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), - }, - }, - }, - }, - customAuth0Provider(), - }, - Override: &tplmodels.OverrideStruct{ - APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - ogConsumeCodePOST := *originalImplementation.ConsumeCodePOST - ogCreateCodePOST := *originalImplementation.CreateCodePOST - ogResendCodePOST := *originalImplementation.ResendCodePOST - ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET - ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST + // thirdpartypasswordless.Init(tplmodels.TypeInput{ + // ContactMethodPhone: passwordlessConfig.ContactMethodPhone, + // ContactMethodEmail: passwordlessConfig.ContactMethodEmail, + // ContactMethodEmailOrPhone: passwordlessConfig.ContactMethodEmailOrPhone, + // FlowType: passwordlessConfig.FlowType, + // GetCustomUserInputCode: passwordlessConfig.GetCustomUserInputCode, + // EmailDelivery: passwordlessConfig.EmailDelivery, + // SmsDelivery: passwordlessConfig.SmsDelivery, + // Providers: []tpmodels.ProviderInput{ + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "google", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("GOOGLE_CLIENT_ID"), + // ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "github", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("GITHUB_CLIENT_ID"), + // ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // { + // Config: tpmodels.ProviderConfig{ + // ThirdPartyId: "facebook", + // Clients: []tpmodels.ProviderClientConfig{ + // { + // ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), + // ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), + // }, + // }, + // }, + // }, + // customAuth0Provider(), + // }, + // Override: &tplmodels.OverrideStruct{ + // APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { + // ogConsumeCodePOST := *originalImplementation.ConsumeCodePOST + // ogCreateCodePOST := *originalImplementation.CreateCodePOST + // ogResendCodePOST := *originalImplementation.ResendCodePOST + // ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET + // ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST - (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) - if gr != nil { - return tpmodels.AuthorisationUrlGETResponse{ - GeneralError: gr, - }, nil - } - return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - } + // (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) + // if gr != nil { + // return tpmodels.AuthorisationUrlGETResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) + // } - (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUpPOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) - if gr != nil { - return tplmodels.ThirdPartySignInUpPOSTResponse{ - GeneralError: gr, - }, nil - } - return ogSignInUpPOST(provider, input, tenantId, options, userContext) - } + // (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUpPOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) + // if gr != nil { + // return tplmodels.ThirdPartySignInUpPOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogSignInUpPOST(provider, input, tenantId, options, userContext) + // } - (*originalImplementation.ConsumeCodePOST) = func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ConsumeCodePOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API consume code", false) - if gr != nil { - return tplmodels.ConsumeCodePOSTResponse{ - GeneralError: gr, - }, nil - } - return ogConsumeCodePOST(userInput, linkCode, preAuthSessionID, tenantId, options, userContext) - } + // (*originalImplementation.ConsumeCodePOST) = func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ConsumeCodePOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API consume code", false) + // if gr != nil { + // return tplmodels.ConsumeCodePOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogConsumeCodePOST(userInput, linkCode, preAuthSessionID, tenantId, options, userContext) + // } - (*originalImplementation.CreateCodePOST) = func(email, phoneNumber *string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.CreateCodePOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API create code", false) - if gr != nil { - return plessmodels.CreateCodePOSTResponse{ - GeneralError: gr, - }, nil - } - return ogCreateCodePOST(email, phoneNumber, tenantId, options, userContext) - } + // (*originalImplementation.CreateCodePOST) = func(email, phoneNumber *string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.CreateCodePOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API create code", false) + // if gr != nil { + // return plessmodels.CreateCodePOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogCreateCodePOST(email, phoneNumber, tenantId, options, userContext) + // } - (*originalImplementation.ResendCodePOST) = func(deviceID, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ResendCodePOSTResponse, error) { - gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API resend code", false) - if gr != nil { - return plessmodels.ResendCodePOSTResponse{ - GeneralError: gr, - }, nil - } - return ogResendCodePOST(deviceID, preAuthSessionID, tenantId, options, userContext) - } - return originalImplementation - }, - }, - }), + // (*originalImplementation.ResendCodePOST) = func(deviceID, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ResendCodePOSTResponse, error) { + // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API resend code", false) + // if gr != nil { + // return plessmodels.ResendCodePOSTResponse{ + // GeneralError: gr, + // }, nil + // } + // return ogResendCodePOST(deviceID, preAuthSessionID, tenantId, options, userContext) + // } + // return originalImplementation + // }, + // }, + // }), userroles.Init(nil), }, }) From cb383a93c812973cc02626a0a993a5210128bd7e Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Fri, 12 Apr 2024 12:48:50 +0530 Subject: [PATCH 09/19] makes change to middleware routing logic --- supertokens/supertokens.go | 120 +++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/supertokens/supertokens.go b/supertokens/supertokens.go index b3bc166e..b5d5f825 100644 --- a/supertokens/supertokens.go +++ b/supertokens/supertokens.go @@ -181,41 +181,69 @@ func (s *superTokens) middleware(theirHandler http.Handler) http.Handler { requestRID = "" } if requestRID != "" { - var matchedRecipe *RecipeModule + var matchedRecipes []RecipeModule = []RecipeModule{} for _, recipeModule := range s.RecipeModules { LogDebugMessage("middleware: Checking recipe ID for match: " + recipeModule.GetRecipeID()) if recipeModule.GetRecipeID() == requestRID { - matchedRecipe = &recipeModule - break + matchedRecipes = append(matchedRecipes, recipeModule) + } else if requestRID == "thirdpartyemailpassword" { + if recipeModule.GetRecipeID() == "thirdparty" || + recipeModule.GetRecipeID() == "emailpassword" { + matchedRecipes = append(matchedRecipes, recipeModule) + } + } else if requestRID == "thirdpartypasswordless" { + if recipeModule.GetRecipeID() == "thirdparty" || + recipeModule.GetRecipeID() == "passwordless" { + matchedRecipes = append(matchedRecipes, recipeModule) + } } } - if matchedRecipe == nil { - LogDebugMessage("middleware: Not handling because no recipe matched") - theirHandler.ServeHTTP(dw, r) + if len(matchedRecipes) == 0 { + LogDebugMessage("middleware: Not handling because no recipe matched. Trying without rid") + s.middlewareHelperHandleWithoutRid(path, method, userContext, theirHandler, dw, r) return } - LogDebugMessage("middleware: Matched with recipe ID: " + matchedRecipe.GetRecipeID()) + for _, matchedRecipe := range matchedRecipes { + LogDebugMessage("middleware: Matched with recipe IDs: " + matchedRecipe.GetRecipeID()) + } - id, tenantId, err := matchedRecipe.ReturnAPIIdIfCanHandleRequest(path, method, userContext) + var id *string = nil + var finalTenantId *string = nil + var finalMatchedRecipe *RecipeModule = nil - if err != nil { - err = s.errorHandler(err, r, dw, userContext) - if err != nil && !dw.IsDone() { - s.OnSuperTokensAPIError(err, r, dw) + for _, matchedRecipe := range matchedRecipes { + currId, currTenantId, err := matchedRecipe.ReturnAPIIdIfCanHandleRequest(path, method, userContext) + if err != nil { + err = s.errorHandler(err, r, dw, userContext) + if err != nil && !dw.IsDone() { + s.OnSuperTokensAPIError(err, r, dw) + } + return + } + + if currId != nil { + if id != nil { + if !dw.IsDone() { + s.OnSuperTokensAPIError(errors.New("Two recipes have matched the same API path and method! This is a bug in the SDK. Please contact support."), r, dw) + } + return + } else { + id = currId + finalTenantId = &currTenantId + finalMatchedRecipe = &matchedRecipe + } } - return } - if id == nil { - LogDebugMessage("middleware: Not handling because recipe doesn't handle request path or method. Request path: " + path.GetAsStringDangerous() + ", request method: " + method) - theirHandler.ServeHTTP(dw, r) + if id == nil || finalTenantId == nil || finalMatchedRecipe == nil { + s.middlewareHelperHandleWithoutRid(path, method, userContext, theirHandler, dw, r) return } LogDebugMessage("middleware: Request being handled by recipe. ID is: " + *id) - tenantId, err = GetTenantIdFuncFromUsingMultitenancyRecipe(tenantId, userContext) + var tenantId, err = GetTenantIdFuncFromUsingMultitenancyRecipe(*finalTenantId, userContext) if err != nil { err = s.errorHandler(err, r, dw, userContext) if err != nil && !dw.IsDone() { @@ -224,7 +252,7 @@ func (s *superTokens) middleware(theirHandler http.Handler) http.Handler { return } - apiErr := matchedRecipe.HandleAPIRequest(*id, tenantId, r, dw, theirHandler.ServeHTTP, path, method, userContext) + apiErr := finalMatchedRecipe.HandleAPIRequest(*id, tenantId, r, dw, theirHandler.ServeHTTP, path, method, userContext) if apiErr != nil { apiErr = s.errorHandler(apiErr, r, dw, userContext) if apiErr != nil && !dw.IsDone() { @@ -234,36 +262,40 @@ func (s *superTokens) middleware(theirHandler http.Handler) http.Handler { } LogDebugMessage("middleware: Ended") } else { - for _, recipeModule := range s.RecipeModules { - id, tenantId, err := recipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) - LogDebugMessage("middleware: Checking recipe ID for match: " + recipeModule.GetRecipeID()) - if err != nil { - err = s.errorHandler(err, r, dw, userContext) - if err != nil && !dw.IsDone() { - s.OnSuperTokensAPIError(err, r, dw) - } - return - } + s.middlewareHelperHandleWithoutRid(path, method, userContext, theirHandler, dw, r) + } + }) +} - if id != nil { - LogDebugMessage("middleware: Request being handled by recipe. ID is: " + *id) - err := recipeModule.HandleAPIRequest(*id, tenantId, r, dw, theirHandler.ServeHTTP, path, method, userContext) - if err != nil { - err = s.errorHandler(err, r, dw, userContext) - if err != nil && !dw.IsDone() { - s.OnSuperTokensAPIError(err, r, dw) - } - } else { - LogDebugMessage("middleware: Ended") - } - return - } +func (s *superTokens) middlewareHelperHandleWithoutRid(path NormalisedURLPath, method string, userContext *map[string]interface{}, theirHandler http.Handler, dw DoneWriter, r *http.Request) { + for _, recipeModule := range s.RecipeModules { + id, tenantId, err := recipeModule.ReturnAPIIdIfCanHandleRequest(path, method, userContext) + LogDebugMessage("middleware: Checking recipe ID for match: " + recipeModule.GetRecipeID()) + if err != nil { + err = s.errorHandler(err, r, dw, userContext) + if err != nil && !dw.IsDone() { + s.OnSuperTokensAPIError(err, r, dw) } + return + } - LogDebugMessage("middleware: Not handling because no recipe matched") - theirHandler.ServeHTTP(dw, r) + if id != nil { + LogDebugMessage("middleware: Request being handled by recipe. ID is: " + *id) + err := recipeModule.HandleAPIRequest(*id, tenantId, r, dw, theirHandler.ServeHTTP, path, method, userContext) + if err != nil { + err = s.errorHandler(err, r, dw, userContext) + if err != nil && !dw.IsDone() { + s.OnSuperTokensAPIError(err, r, dw) + } + } else { + LogDebugMessage("middleware: Ended") + } + return } - }) + } + + LogDebugMessage("middleware: Not handling because no recipe matched") + theirHandler.ServeHTTP(dw, r) } func (s *superTokens) getAllCORSHeaders() []string { From c079e94e969478fae6ecb18e67ea5ff9ea83ac20 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Sun, 14 Apr 2024 11:45:06 +0530 Subject: [PATCH 10/19] makes remaining changes --- CHANGELOG.md | 24 + recipe/emailpassword/api/implementation.go | 1 - recipe/emailpassword/api/utils.go | 5 +- recipe/emailpassword/authFlow_test.go | 107 ++++ recipe/emailpassword/constants/constants.go | 3 +- .../emailExistsAndVerificationCheck_test.go | 212 ++++++++ recipe/emailpassword/main.go | 1 - recipe/emailpassword/passwordReset_test.go | 4 +- recipe/emailpassword/recipe.go | 11 +- .../emailverification/api/implementation.go | 1 - recipe/emailverification/api/utils.go | 5 +- .../emailverification_email_test.go | 8 + recipe/emailverification/main.go | 7 +- recipe/passwordless/api/implementation.go | 2 - recipe/passwordless/api/utils.go | 5 +- recipe/passwordless/api_test.go | 500 +++++++++++++++++- recipe/passwordless/constants.go | 12 +- recipe/passwordless/recipe.go | 23 +- recipe/passwordless/recipeFucntions_test.go | 2 +- .../authorisationUrlFeature_test.go | 83 +++ test/unittesting/testingutils.go | 36 ++ 21 files changed, 1019 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f031e8e..dd52ad7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## Breaking change + +- Removed ThirdPartyEmailPassword and ThirdPartyPasswordless recipes. Instead, you should use ThirdParty + EmailPassword or ThirdParty + Passwordless recipes separately in your recipe list. +- Removed `rid` query param from: + - email verification links + - passwordless magic links + - password reset links + +## Changes + +- If `rid` header is present in an API call, the routing no only only depends on that. If the SDK cannot resolve a request handler based on the `rid`, request path and method, it will try to resolve a request handler only based on the request path and method (therefore ignoring the `rid` header). +- New API handlers are: + - `GET /emailpassword/email/exists` => email password, does email exist API (used to be `GET /signup/email/exists` with `rid` of `emailpassword` or `thirdpartyemailpassword` which is now deprecated) + - `GET /passwordless/email/exists` => email password, does email exist API (used to be `GET /signup/email/exists` with `rid` of `passwordless` or `thirdpartypasswordless` which is now deprecated) + - `GET /passwordless/phonenumber/exists` => email password, does email exist API (used to be `GET /signup/phonenumber/exists` which is now deprecated) +- Support for FDI 2.0 + +## Migration guide + +- If you were using `ThirdPartyEmailPassword`, you should now init `ThirdParty` and `EmailPassword` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [EmailPassword](https://supertokens.com/docs/emailpassword/introduction) for more information. + +- If you were using `ThirdPartyPasswordless`, you should now init `ThirdParty` and `Passwordless` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [Passwordless](https://supertokens.com/docs/passwordless/introduction) for more information. + + ## [0.17.5] - 2024-03-14 - Adds a type uint64 to the `accessTokenCookiesExpiryDurationMillis` local variable in `recipe/session/utils.go`. It also removes the redundant `uint64` type forcing needed because of the untyped variable. - Fixes the passing of `tenantId` in `getAllSessionHandlesForUser` and `revokeAllSessionsForUser` based on `fetchAcrossAllTenants` and `revokeAcrossAllTenants` inputs respectively. diff --git a/recipe/emailpassword/api/implementation.go b/recipe/emailpassword/api/implementation.go index 209fd5dd..09186496 100644 --- a/recipe/emailpassword/api/implementation.go +++ b/recipe/emailpassword/api/implementation.go @@ -68,7 +68,6 @@ func MakeAPIImplementation() epmodels.APIInterface { passwordResetLink, err := GetPasswordResetLink( options.AppInfo, - options.RecipeID, response.OK.Token, tenantId, options.Req, diff --git a/recipe/emailpassword/api/utils.go b/recipe/emailpassword/api/utils.go index fa6db009..a96faf94 100644 --- a/recipe/emailpassword/api/utils.go +++ b/recipe/emailpassword/api/utils.go @@ -126,17 +126,16 @@ func validateFormOrThrowError(configFormFields []epmodels.NormalisedFormField, i return nil } -func GetPasswordResetLink(appInfo supertokens.NormalisedAppinfo, recipeID string, token string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { +func GetPasswordResetLink(appInfo supertokens.NormalisedAppinfo, token string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { websiteDomain, err := appInfo.GetOrigin(request, userContext) if err != nil { return "", err } return fmt.Sprintf( - "%s%s/reset-password?token=%s&rid=%s&tenantId=%s", + "%s%s/reset-password?token=%s&tenantId=%s", websiteDomain.GetAsStringDangerous(), appInfo.WebsiteBasePath.GetAsStringDangerous(), token, - recipeID, tenantId, ), nil } diff --git a/recipe/emailpassword/authFlow_test.go b/recipe/emailpassword/authFlow_test.go index 720d973f..3dfe088d 100644 --- a/recipe/emailpassword/authFlow_test.go +++ b/recipe/emailpassword/authFlow_test.go @@ -32,10 +32,117 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" + "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestRightRidButRecipeMissingReturns404(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{ + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + }, + } + + 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() + + res, err := unittesting.SignInRequest("random@gmail.com", "validpass123", testServer.URL) + + if err != nil { + t.Error(err.Error()) + } + + assert.NoError(t, err) + assert.Equal(t, 404, res.StatusCode) +} + +func TestSignInWorksWithThirdPartyEmailPasswordRid(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{ + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + 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() + + res, err := unittesting.SignInRequestWithThirdpartyemailpasswordRid("random@gmail.com", "validpass123", testServer.URL) + + if err != nil { + t.Error(err.Error()) + } + + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) +} + // SigninFeature Tests func TestDisablingAPIDefaultSigninDoesNotWork(t *testing.T) { configValue := supertokens.TypeInput{ diff --git a/recipe/emailpassword/constants/constants.go b/recipe/emailpassword/constants/constants.go index 185be214..c27d8506 100644 --- a/recipe/emailpassword/constants/constants.go +++ b/recipe/emailpassword/constants/constants.go @@ -20,5 +20,6 @@ const ( SignInAPI = "/signin" GeneratePasswordResetTokenAPI = "/user/password/reset/token" PasswordResetAPI = "/user/password/reset" - SignupEmailExistsAPI = "/signup/email/exists" + SignupEmailExistsAPIOld = "/signup/email/exists" + SignupEmailExistsAPI = "/emailpassword/email/exists" ) diff --git a/recipe/emailpassword/emailExistsAndVerificationCheck_test.go b/recipe/emailpassword/emailExistsAndVerificationCheck_test.go index 346f29e1..08a84657 100644 --- a/recipe/emailpassword/emailExistsAndVerificationCheck_test.go +++ b/recipe/emailpassword/emailExistsAndVerificationCheck_test.go @@ -35,12 +35,139 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels" "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" + "github.com/supertokens/supertokens-golang/recipe/passwordless" + "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestEmailExistsPicksRightRecipeDependingOnRid(t *testing.T) { + passwordlessEmailExists := false + emailpasswordEmailExists := false + 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{ + Override: &epmodels.OverrideStruct{ + APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface { + oEmailExists := *originalImplementation.EmailExistsGET + (*originalImplementation.EmailExistsGET) = func(email, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) { + emailpasswordEmailExists = true + return oEmailExists(email, tenantId, options, userContext) + } + + return originalImplementation + }, + }, + }), + passwordless.Init(plessmodels.TypeInput{ + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + FlowType: "USER_INPUT_CODE", + Override: &plessmodels.OverrideStruct{ + APIs: func(originalImplementation plessmodels.APIInterface) plessmodels.APIInterface { + oEmailExists := *originalImplementation.EmailExistsGET + (*originalImplementation.EmailExistsGET) = func(email, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.EmailExistsGETResponse, error) { + passwordlessEmailExists = true + return oEmailExists(email, tenantId, options, userContext) + } + + return originalImplementation + }, + }, + }), + 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() + + { + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + q := req.URL.Query() + q.Add("email", "random@email.com") + req.Header.Add("rid", "emailpassword") + req.URL.RawQuery = q.Encode() + assert.NoError(t, err) + res, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) + assert.True(t, emailpasswordEmailExists) + assert.False(t, passwordlessEmailExists) + } + + { + emailpasswordEmailExists = false + passwordlessEmailExists = false + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + q := req.URL.Query() + q.Add("email", "random@email.com") + req.Header.Add("rid", "passwordless") + req.URL.RawQuery = q.Encode() + assert.NoError(t, err) + res, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) + assert.False(t, emailpasswordEmailExists) + assert.True(t, passwordlessEmailExists) + } + + { + emailpasswordEmailExists = false + passwordlessEmailExists = false + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + q := req.URL.Query() + q.Add("email", "random@email.com") + req.Header.Add("rid", "thirdpartypasswordless") + req.URL.RawQuery = q.Encode() + assert.NoError(t, err) + res, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) + assert.False(t, emailpasswordEmailExists) + assert.True(t, passwordlessEmailExists) + } + + { + emailpasswordEmailExists = false + passwordlessEmailExists = false + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/signup/email/exists", nil) + q := req.URL.Query() + q.Add("email", "random@email.com") + req.Header.Add("rid", "thirdpartyemailpassword") + req.URL.RawQuery = q.Encode() + assert.NoError(t, err) + res, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) + assert.True(t, emailpasswordEmailExists) + assert.False(t, passwordlessEmailExists) + } +} + // Email exists tests func TestEmailExistGetStopsWorkingWhenDisabled(t *testing.T) { configValue := supertokens.TypeInput{ @@ -172,6 +299,91 @@ func TestGoodInputsEmailExists(t *testing.T) { } +func TestGoodInputsEmailExistsNewPath(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), + 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() + + passwordVal := "validPass123" + + emailVal := "random@email.com" + + formFields := map[string][]map[string]string{ + "formFields": { + { + "id": "email", + "value": emailVal, + }, + { + "id": "password", + "value": passwordVal, + }, + }, + } + + 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)) + + assert.Equal(t, 200, resp.StatusCode) + + assert.NoError(t, err) + data, _ := io.ReadAll(resp.Body) + resp.Body.Close() + var response map[string]interface{} + _ = json.Unmarshal(data, &response) + + assert.Equal(t, "OK", response["status"]) + + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/emailpassword/email/exists", nil) + q := req.URL.Query() + q.Add("email", "random@email.com") + req.URL.RawQuery = q.Encode() + assert.NoError(t, err) + res, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, 200, res.StatusCode) + + data2, err := io.ReadAll(res.Body) + assert.NoError(t, err) + res.Body.Close() + var response2 map[string]interface{} + _ = json.Unmarshal(data2, &response2) + + assert.Equal(t, "OK", response2["status"]) + assert.Equal(t, true, response2["exists"]) + +} + func TestGoodInputsEmailDoesNotExists(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/recipe/emailpassword/main.go b/recipe/emailpassword/main.go index e157d16a..45ae26b8 100644 --- a/recipe/emailpassword/main.go +++ b/recipe/emailpassword/main.go @@ -140,7 +140,6 @@ func CreateResetPasswordLink(tenantId string, userID string, userContext ...supe link, err := api.GetPasswordResetLink( instance.RecipeModule.GetAppInfo(), - instance.RecipeModule.GetRecipeID(), tokenResponse.OK.Token, tenantId, supertokens.GetRequestFromUserContext(userContext[0]), diff --git a/recipe/emailpassword/passwordReset_test.go b/recipe/emailpassword/passwordReset_test.go index 45d7d39d..abec9ce8 100644 --- a/recipe/emailpassword/passwordReset_test.go +++ b/recipe/emailpassword/passwordReset_test.go @@ -128,7 +128,7 @@ func TestEmailValidationCheckInGenerateTokenAPI(t *testing.T) { assert.Equal(t, 200, resp.StatusCode) assert.Equal(t, "https://supertokens.io/auth/reset-password", resetURL) assert.NotEmpty(t, tokenInfo) - assert.True(t, strings.HasPrefix(ridInfo, "emailpassword")) + assert.True(t, strings.HasPrefix(ridInfo, "")) } func TestPasswordValidation(t *testing.T) { @@ -556,5 +556,5 @@ func TestPasswordResetLinkUsesOriginFunctionIfProvided(t *testing.T) { assert.Equal(t, 200, resp.StatusCode) assert.Equal(t, "http://localhost:2000/auth/reset-password", resetURL) assert.NotEmpty(t, tokenInfo) - assert.True(t, strings.HasPrefix(ridInfo, "emailpassword")) + assert.True(t, strings.HasPrefix(ridInfo, "")) } diff --git a/recipe/emailpassword/recipe.go b/recipe/emailpassword/recipe.go index 0d501ccc..3fa20df4 100644 --- a/recipe/emailpassword/recipe.go +++ b/recipe/emailpassword/recipe.go @@ -120,6 +120,10 @@ func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { if err != nil { return nil, err } + signupEmailExistsAPIOld, err := supertokens.NewNormalisedURLPath(constants.SignupEmailExistsAPIOld) + if err != nil { + return nil, err + } signupEmailExistsAPI, err := supertokens.NewNormalisedURLPath(constants.SignupEmailExistsAPI) if err != nil { return nil, err @@ -144,6 +148,11 @@ func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { PathWithoutAPIBasePath: passwordResetAPI, ID: constants.PasswordResetAPI, Disabled: r.APIImpl.PasswordResetPOST == nil, + }, { + Method: http.MethodGet, + PathWithoutAPIBasePath: signupEmailExistsAPIOld, + ID: constants.SignupEmailExistsAPIOld, + Disabled: r.APIImpl.EmailExistsGET == nil, }, { Method: http.MethodGet, PathWithoutAPIBasePath: signupEmailExistsAPI, @@ -171,7 +180,7 @@ func (r *Recipe) handleAPIRequest(id string, tenantId string, req *http.Request, return api.GeneratePasswordResetToken(r.APIImpl, tenantId, options, userContext) } else if id == constants.PasswordResetAPI { return api.PasswordReset(r.APIImpl, tenantId, options, userContext) - } else if id == constants.SignupEmailExistsAPI { + } else if id == constants.SignupEmailExistsAPIOld || id == constants.SignupEmailExistsAPI { return api.EmailExists(r.APIImpl, tenantId, options, userContext) } return defaultErrors.New("should never come here") diff --git a/recipe/emailverification/api/implementation.go b/recipe/emailverification/api/implementation.go index 5c144b13..f0493742 100644 --- a/recipe/emailverification/api/implementation.go +++ b/recipe/emailverification/api/implementation.go @@ -126,7 +126,6 @@ func MakeAPIImplementation() evmodels.APIInterface { emailVerificationURL, err := GetEmailVerifyLink( options.AppInfo, response.OK.Token, - options.RecipeID, sessionContainer.GetTenantIdWithContext(userContext), options.Req, userContext, diff --git a/recipe/emailverification/api/utils.go b/recipe/emailverification/api/utils.go index b18490c4..c9a4190e 100644 --- a/recipe/emailverification/api/utils.go +++ b/recipe/emailverification/api/utils.go @@ -7,17 +7,16 @@ import ( "github.com/supertokens/supertokens-golang/supertokens" ) -func GetEmailVerifyLink(appInfo supertokens.NormalisedAppinfo, token string, recipeID string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { +func GetEmailVerifyLink(appInfo supertokens.NormalisedAppinfo, token string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { websiteDomain, err := appInfo.GetOrigin(request, userContext) if err != nil { return "", err } return fmt.Sprintf( - "%s%s/verify-email?token=%s&rid=%s&tenantId=%s", + "%s%s/verify-email?token=%s&tenantId=%s", websiteDomain.GetAsStringDangerous(), appInfo.WebsiteBasePath.GetAsStringDangerous(), token, - recipeID, tenantId, ), nil } diff --git a/recipe/emailverification/emailverification_email_test.go b/recipe/emailverification/emailverification_email_test.go index ae210578..57d26e90 100644 --- a/recipe/emailverification/emailverification_email_test.go +++ b/recipe/emailverification/emailverification_email_test.go @@ -18,6 +18,7 @@ package emailverification import ( "net/http" + "net/url" "testing" "github.com/stretchr/testify/assert" @@ -81,6 +82,7 @@ func TestBackwardCompatibilityServiceWithoutCustomFunction(t *testing.T) { func TestBackwardCompatibilityServiceWithOverride(t *testing.T) { funcCalled := false overrideCalled := false + ridInfo := "" configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ ConnectionURI: "http://localhost:8080", @@ -96,6 +98,11 @@ func TestBackwardCompatibilityServiceWithOverride(t *testing.T) { EmailDelivery: &emaildelivery.TypeInput{ Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface { (*originalImplementation.SendEmail) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { + u, err := url.Parse(input.EmailVerification.EmailVerifyLink) + if err != nil { + return err + } + ridInfo = u.Query().Get("rid") overrideCalled = true return nil } @@ -134,6 +141,7 @@ func TestBackwardCompatibilityServiceWithOverride(t *testing.T) { assert.Equal(t, EmailVerificationEmailSentForTest, false) assert.Equal(t, funcCalled, false) assert.Equal(t, overrideCalled, true) + assert.Equal(t, ridInfo, "") } func TestSMTPServiceOverride(t *testing.T) { diff --git a/recipe/emailverification/main.go b/recipe/emailverification/main.go index 61b68c0a..6a7d15b0 100644 --- a/recipe/emailverification/main.go +++ b/recipe/emailverification/main.go @@ -158,10 +158,7 @@ func CreateEmailVerificationLink(tenantId string, userID string, email *string, if err != nil { return evmodels.CreateEmailVerificationLinkResponse{}, err } - instance, err := getRecipeInstanceOrThrowError() - if err != nil { - return evmodels.CreateEmailVerificationLinkResponse{}, err - } + if len(userContext) == 0 { userContext = append(userContext, &map[string]interface{}{}) } @@ -176,7 +173,7 @@ func CreateEmailVerificationLink(tenantId string, userID string, email *string, }, nil } - link, err := api.GetEmailVerifyLink(st.AppInfo, emailVerificationTokenResponse.OK.Token, instance.RecipeModule.GetRecipeID(), tenantId, supertokens.GetRequestFromUserContext(userContext[0]), userContext[0]) + link, err := api.GetEmailVerifyLink(st.AppInfo, emailVerificationTokenResponse.OK.Token, tenantId, supertokens.GetRequestFromUserContext(userContext[0]), userContext[0]) if err != nil { return evmodels.CreateEmailVerificationLinkResponse{}, err diff --git a/recipe/passwordless/api/implementation.go b/recipe/passwordless/api/implementation.go index 8cf22001..4e07372b 100644 --- a/recipe/passwordless/api/implementation.go +++ b/recipe/passwordless/api/implementation.go @@ -101,7 +101,6 @@ func MakeAPIImplementation() plessmodels.APIInterface { if flowType == "MAGIC_LINK" || flowType == "USER_INPUT_CODE_AND_MAGIC_LINK" { link, err := GetMagicLink( options.AppInfo, - options.RecipeID, response.OK.PreAuthSessionID, response.OK.LinkCode, tenantId, @@ -283,7 +282,6 @@ func MakeAPIImplementation() plessmodels.APIInterface { if flowType == "MAGIC_LINK" || flowType == "USER_INPUT_CODE_AND_MAGIC_LINK" { link, err := GetMagicLink( options.AppInfo, - options.RecipeID, response.OK.PreAuthSessionID, response.OK.LinkCode, tenantId, diff --git a/recipe/passwordless/api/utils.go b/recipe/passwordless/api/utils.go index 95d002dd..77055497 100644 --- a/recipe/passwordless/api/utils.go +++ b/recipe/passwordless/api/utils.go @@ -7,16 +7,15 @@ import ( "github.com/supertokens/supertokens-golang/supertokens" ) -func GetMagicLink(appInfo supertokens.NormalisedAppinfo, recipeID string, preAuthSessionID string, linkCode string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { +func GetMagicLink(appInfo supertokens.NormalisedAppinfo, preAuthSessionID string, linkCode string, tenantId string, request *http.Request, userContext supertokens.UserContext) (string, error) { websiteDomain, err := appInfo.GetOrigin(request, userContext) if err != nil { return "", err } return fmt.Sprintf( - "%s%s/verify?rid=%s&preAuthSessionId=%s&tenantId=%s#%s", + "%s%s/verify?preAuthSessionId=%s&tenantId=%s#%s", websiteDomain.GetAsStringDangerous(), appInfo.WebsiteBasePath.GetAsStringDangerous(), - recipeID, preAuthSessionID, tenantId, linkCode, diff --git a/recipe/passwordless/api_test.go b/recipe/passwordless/api_test.go index e223cc6e..f0a6c92a 100644 --- a/recipe/passwordless/api_test.go +++ b/recipe/passwordless/api_test.go @@ -31,10 +31,321 @@ import ( "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" + "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestCreateCodeAPIWithRidAsThirdpartypasswordless(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + validEmail := map[string]interface{}{ + "email": "test@example.com", + } + + validEmailBody, err := json.Marshal(validEmail) + if err != nil { + t.Error(err.Error()) + } + + client := &http.Client{} + req, _ := http.NewRequest("POST", testServer.URL+"/auth/signinup/code", bytes.NewBuffer(validEmailBody)) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "thirdpartypasswordless") + + validEmailResp, err := client.Do(req) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, validEmailResp.StatusCode) + + validEmailDataInBytes, err := io.ReadAll(validEmailResp.Body) + if err != nil { + t.Error(err.Error()) + } + validEmailResp.Body.Close() + + var validEmailResult map[string]interface{} + err = json.Unmarshal(validEmailDataInBytes, &validEmailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", validEmailResult["status"]) + assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validEmailResult["flowType"]) + assert.Equal(t, 4, len(validEmailResult)) +} + +func TestCreateCodeAPIWithRidAsRandom(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + validEmail := map[string]interface{}{ + "email": "test@example.com", + } + + validEmailBody, err := json.Marshal(validEmail) + if err != nil { + t.Error(err.Error()) + } + + client := &http.Client{} + req, _ := http.NewRequest("POST", testServer.URL+"/auth/signinup/code", bytes.NewBuffer(validEmailBody)) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "random") + + validEmailResp, err := client.Do(req) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, validEmailResp.StatusCode) + + validEmailDataInBytes, err := io.ReadAll(validEmailResp.Body) + if err != nil { + t.Error(err.Error()) + } + validEmailResp.Body.Close() + + var validEmailResult map[string]interface{} + err = json.Unmarshal(validEmailDataInBytes, &validEmailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", validEmailResult["status"]) + assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validEmailResult["flowType"]) + assert.Equal(t, 4, len(validEmailResult)) +} + +func TestCreateCodeAPIWithWrongRid(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + validEmail := map[string]interface{}{ + "email": "test@example.com", + } + + validEmailBody, err := json.Marshal(validEmail) + if err != nil { + t.Error(err.Error()) + } + + client := &http.Client{} + req, _ := http.NewRequest("POST", testServer.URL+"/auth/signinup/code", bytes.NewBuffer(validEmailBody)) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "emailpassword") + + validEmailResp, err := client.Do(req) + + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, validEmailResp.StatusCode) + + validEmailDataInBytes, err := io.ReadAll(validEmailResp.Body) + if err != nil { + t.Error(err.Error()) + } + validEmailResp.Body.Close() + + var validEmailResult map[string]interface{} + err = json.Unmarshal(validEmailDataInBytes, &validEmailResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", validEmailResult["status"]) + assert.Equal(t, "USER_INPUT_CODE_AND_MAGIC_LINK", validEmailResult["flowType"]) + assert.Equal(t, 4, len(validEmailResult)) +} + func TestWithEmailExistAPI(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ @@ -118,6 +429,89 @@ func TestWithEmailExistAPI(t *testing.T) { assert.True(t, emailExistsResponse["exists"].(bool)) } +func TestWithEmailExistAPINewPath(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodEmail: plessmodels.ContactMethodEmailConfig{ + Enabled: true, + }, + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/passwordless/email/exists", nil) + query := req.URL.Query() + query.Add("email", "test@example.com") + req.URL.RawQuery = query.Encode() + assert.NoError(t, err) + emailDoesNotExistResp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailDoesNotExistResp.StatusCode) + + emailDoesNotExistResponse := *unittesting.HttpResponseToConsumableInformation(emailDoesNotExistResp.Body) + + assert.Equal(t, "OK", emailDoesNotExistResponse["status"]) + assert.False(t, emailDoesNotExistResponse["exists"].(bool)) + + codeInfo, err := CreateCodeWithEmail("public", "test@example.com", nil) + assert.NoError(t, err) + + ConsumeCodeWithLinkCode("public", codeInfo.OK.LinkCode, codeInfo.OK.PreAuthSessionID) + + req, err = http.NewRequest(http.MethodGet, testServer.URL+"/auth/passwordless/email/exists", nil) + query = req.URL.Query() + query.Add("email", "test@example.com") + req.URL.RawQuery = query.Encode() + assert.NoError(t, err) + emailExistsResp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, emailExistsResp.StatusCode) + + emailExistsResponse := *unittesting.HttpResponseToConsumableInformation(emailExistsResp.Body) + + assert.Equal(t, "OK", emailExistsResponse["status"]) + assert.True(t, emailExistsResponse["exists"].(bool)) +} + func TestMagicLinkFormatInCreateCodeAPI(t *testing.T) { var magicLinkURL *url.URL sendEmail := func(input emaildelivery.EmailType, userContext supertokens.UserContext) error { @@ -195,7 +589,7 @@ func TestMagicLinkFormatInCreateCodeAPI(t *testing.T) { assert.Equal(t, "OK", validCreateCodeResponse["status"]) assert.Equal(t, "supertokens.io", magicLinkURL.Hostname()) assert.Equal(t, "/auth/verify", magicLinkURL.Path) - assert.Equal(t, "passwordless", magicLinkURL.Query().Get("rid")) + assert.Equal(t, "", magicLinkURL.Query().Get("rid")) assert.Equal(t, validCreateCodeResponse["preAuthSessionId"], magicLinkURL.Query().Get("preAuthSessionId")) } @@ -2030,6 +2424,110 @@ func TestPhoneNumberExistsAPI(t *testing.T) { assert.Equal(t, true, phoneResult1["exists"]) } +func TestPhoneNumberExistsAPINewPath(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{ + session.Init(&sessmodels.TypeInput{ + GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod { + return sessmodels.CookieTransferMethod + }, + }), + Init(plessmodels.TypeInput{ + FlowType: "USER_INPUT_CODE_AND_MAGIC_LINK", + ContactMethodPhone: plessmodels.ContactMethodPhoneConfig{ + Enabled: true, + }, + }), + }, + } + BeforeEach() + unittesting.SetKeyValueInConfig("passwordless_code_lifetime", "1000") + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(configValue) + if err != nil { + t.Error(err.Error()) + } + q, err := supertokens.GetNewQuerierInstanceOrThrowError("") + if err != nil { + t.Error(err.Error()) + } + apiV, err := q.GetQuerierAPIVersion() + if err != nil { + t.Error(err.Error()) + } + + if unittesting.MaxVersion(apiV, "2.11") == "2.11" { + return + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/passwordless/phonenumber/exists", nil) + query := req.URL.Query() + query.Add("phoneNumber", "+1234567890") + req.URL.RawQuery = query.Encode() + assert.NoError(t, err) + phoneResp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, phoneResp.StatusCode) + + phoneDataInBytes, err := io.ReadAll(phoneResp.Body) + if err != nil { + t.Error(err.Error()) + } + phoneResp.Body.Close() + + var phoneResult map[string]interface{} + err = json.Unmarshal(phoneDataInBytes, &phoneResult) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", phoneResult["status"]) + assert.Equal(t, false, phoneResult["exists"]) + + codeInfo, err := CreateCodeWithPhoneNumber("public", "+1234567890", nil) + assert.NoError(t, err) + + _, err = ConsumeCodeWithLinkCode("public", codeInfo.OK.LinkCode, codeInfo.OK.PreAuthSessionID) + assert.NoError(t, err) + + req1, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/passwordless/phonenumber/exists", nil) + query1 := req.URL.Query() + query1.Add("phoneNumber", "+1234567890") + req1.URL.RawQuery = query1.Encode() + assert.NoError(t, err) + phoneResp1, err := http.DefaultClient.Do(req1) + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, phoneResp1.StatusCode) + + phoneDataInBytes1, err := io.ReadAll(phoneResp1.Body) + if err != nil { + t.Error(err.Error()) + } + phoneResp1.Body.Close() + + var phoneResult1 map[string]interface{} + err = json.Unmarshal(phoneDataInBytes1, &phoneResult1) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "OK", phoneResult1["status"]) + assert.Equal(t, true, phoneResult1["exists"]) +} + func TestResendCodeAPI(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/recipe/passwordless/constants.go b/recipe/passwordless/constants.go index 9e004626..9be6b7a9 100644 --- a/recipe/passwordless/constants.go +++ b/recipe/passwordless/constants.go @@ -16,9 +16,11 @@ package passwordless const ( - createCodeAPI = "/signinup/code" - resendCodeAPI = "/signinup/code/resend" - consumeCodeAPI = "/signinup/code/consume" - doesEmailExistAPI = "/signup/email/exists" - doesPhoneNumberExistAPI = "/signup/phonenumber/exists" + createCodeAPI = "/signinup/code" + resendCodeAPI = "/signinup/code/resend" + consumeCodeAPI = "/signinup/code/consume" + doesEmailExistAPIOld = "/signup/email/exists" + doesPhoneNumberExistAPIOld = "/signup/phonenumber/exists" + doesEmailExistAPI = "/passwordless/email/exists" + doesPhoneNumberExistAPI = "/passwordless/phonenumber/exists" ) diff --git a/recipe/passwordless/recipe.go b/recipe/passwordless/recipe.go index 244a80d3..5fe8cd3a 100644 --- a/recipe/passwordless/recipe.go +++ b/recipe/passwordless/recipe.go @@ -118,10 +118,18 @@ func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { if err != nil { return nil, err } + doesEmailExistsAPINormalisedOld, err := supertokens.NewNormalisedURLPath(doesEmailExistAPIOld) + if err != nil { + return nil, err + } doesEmailExistsAPINormalised, err := supertokens.NewNormalisedURLPath(doesEmailExistAPI) if err != nil { return nil, err } + doesPhoneNumberExistsAPINormalisedOld, err := supertokens.NewNormalisedURLPath(doesPhoneNumberExistAPIOld) + if err != nil { + return nil, err + } doesPhoneNumberExistsAPINormalised, err := supertokens.NewNormalisedURLPath(doesPhoneNumberExistAPI) if err != nil { return nil, err @@ -141,11 +149,21 @@ func (r *Recipe) getAPIsHandled() ([]supertokens.APIHandled, error) { PathWithoutAPIBasePath: createCodeAPINormalised, ID: createCodeAPI, Disabled: r.APIImpl.CreateCodePOST == nil, + }, { + Method: http.MethodGet, + PathWithoutAPIBasePath: doesEmailExistsAPINormalisedOld, + ID: doesEmailExistAPIOld, + Disabled: r.APIImpl.EmailExistsGET == nil, }, { Method: http.MethodGet, PathWithoutAPIBasePath: doesEmailExistsAPINormalised, ID: doesEmailExistAPI, Disabled: r.APIImpl.EmailExistsGET == nil, + }, { + Method: http.MethodGet, + PathWithoutAPIBasePath: doesPhoneNumberExistsAPINormalisedOld, + ID: doesPhoneNumberExistAPIOld, + Disabled: r.APIImpl.PhoneNumberExistsGET == nil, }, { Method: http.MethodGet, PathWithoutAPIBasePath: doesPhoneNumberExistsAPINormalised, @@ -175,9 +193,9 @@ func (r *Recipe) handleAPIRequest(id string, tenantId string, req *http.Request, return api.ConsumeCode(r.APIImpl, tenantId, options, userContext) } else if id == createCodeAPI { return api.CreateCode(r.APIImpl, tenantId, options, userContext) - } else if id == doesEmailExistAPI { + } else if id == doesEmailExistAPIOld || id == doesEmailExistAPI { return api.DoesEmailExist(r.APIImpl, tenantId, options, userContext) - } else if id == doesPhoneNumberExistAPI { + } else if id == doesPhoneNumberExistAPIOld || id == doesPhoneNumberExistAPI { return api.DoesPhoneNumberExist(r.APIImpl, tenantId, options, userContext) } else { return api.ResendCode(r.APIImpl, tenantId, options, userContext) @@ -212,7 +230,6 @@ func (r *Recipe) CreateMagicLink(email *string, phoneNumber *string, tenantId st } link, err := api.GetMagicLink( stInstance.AppInfo, - r.RecipeModule.GetRecipeID(), response.OK.PreAuthSessionID, response.OK.LinkCode, tenantId, diff --git a/recipe/passwordless/recipeFucntions_test.go b/recipe/passwordless/recipeFucntions_test.go index 99ae9f6d..acda5fb6 100644 --- a/recipe/passwordless/recipeFucntions_test.go +++ b/recipe/passwordless/recipeFucntions_test.go @@ -1044,7 +1044,7 @@ func TestCreatingMagicLink(t *testing.T) { assert.Equal(t, "supertokens.io", res.Host) assert.Equal(t, "/auth/verify", res.Path) - assert.Equal(t, "passwordless", res.Query().Get("rid")) + assert.Equal(t, "", res.Query().Get("rid")) } func TestSignInUp(t *testing.T) { diff --git a/recipe/thirdparty/authorisationUrlFeature_test.go b/recipe/thirdparty/authorisationUrlFeature_test.go index 68c06561..d2eb2f67 100644 --- a/recipe/thirdparty/authorisationUrlFeature_test.go +++ b/recipe/thirdparty/authorisationUrlFeature_test.go @@ -25,11 +25,94 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/supertokens/supertokens-golang/test/unittesting" ) +func TestReqWithThirdPartyEmailPasswordRecipe(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{ + emailpassword.Init(nil), + Init( + &tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }, + ), + }, + } + + 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() + + client := &http.Client{} + req, _ := http.NewRequest("GET", testServer.URL+"/auth/authorisationurl?thirdPartyId=google", nil) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "thirdpartyemailpassword") + + resp, err := client.Do(req) + + if err != nil { + t.Error(err.Error()) + } + + 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.Equal(t, "OK", data["status"]) + + fetchedUrl, err := url.Parse(data["urlWithQueryParams"].(string)) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "supertokens.io", fetchedUrl.Host) + assert.Equal(t, "/dev/oauth/redirect-to-provider", fetchedUrl.Path) +} + func TestUsingDevOAuthKeysWillUseDevAuthUrl(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/test/unittesting/testingutils.go b/test/unittesting/testingutils.go index 33f87547..f45c7d35 100644 --- a/test/unittesting/testingutils.go +++ b/test/unittesting/testingutils.go @@ -566,6 +566,42 @@ func SignInRequest(email string, password string, testUrl string) (*http.Respons return resp, nil } +func SignInRequestWithThirdpartyemailpasswordRid(email string, password string, testUrl string) (*http.Response, error) { + formFields := map[string][]map[string]string{ + "formFields": { + { + "id": "email", + "value": email, + }, + { + "id": "password", + "value": password, + }, + }, + } + + postBody, err := json.Marshal(formFields) + if err != nil { + fmt.Println(err.Error()) + return nil, err + } + + client := &http.Client{} + req, _ := http.NewRequest("POST", testUrl+"/auth/signin", bytes.NewBuffer(postBody)) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "thirdpartyemailpassword") + + resp, err := client.Do(req) + + if err != nil { + fmt.Println(err.Error()) + return nil, err + } + + return resp, nil +} + func SignInRequestWithTenantId(tenantId string, email string, password string, testUrl string) (*http.Response, error) { formFields := map[string][]map[string]string{ "formFields": { From b9b22b798f266ff5e43a51d5dcb54bcae1be1cc3 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 24 Apr 2024 16:34:36 +0530 Subject: [PATCH 11/19] fixes example apps --- examples/with-chi-oso/main.go | 187 +++++++++++----------- examples/with-chi-oso/service/service.go | 4 +- examples/with-chi/main.go | 189 +++++++++++----------- examples/with-fiber/main.go | 187 +++++++++++----------- examples/with-gin/config/config.go | 12 +- examples/with-go-zero/main.go | 190 ++++++++++++----------- examples/with-http/main.go | 190 ++++++++++++----------- examples/with-labstack-echo/main.go | 190 ++++++++++++----------- examples/with-mux/main.go | 190 ++++++++++++----------- examples/with-twirp/cmd/server/main.go | 190 ++++++++++++----------- 10 files changed, 773 insertions(+), 756 deletions(-) diff --git a/examples/with-chi-oso/main.go b/examples/with-chi-oso/main.go index 36509060..a3b06cf3 100644 --- a/examples/with-chi-oso/main.go +++ b/examples/with-chi-oso/main.go @@ -12,9 +12,8 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -37,111 +36,113 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-chi-oso/service/service.go b/examples/with-chi-oso/service/service.go index a8c2e8ec..3f752e8f 100644 --- a/examples/with-chi-oso/service/service.go +++ b/examples/with-chi-oso/service/service.go @@ -9,7 +9,7 @@ import ( "github.com/osohq/go-oso" "github.com/supertokens/supertokens-golang/examples/with-chi-oso/models" "github.com/supertokens/supertokens-golang/recipe/session" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -92,7 +92,7 @@ func (s *service) Repo(w http.ResponseWriter, r *http.Request) { w.Write([]byte(err.Error())) return } - userByID, err := thirdpartyemailpassword.GetUserById(sessionContainer.GetUserID()) + userByID, err := thirdparty.GetUserByID(sessionContainer.GetUserID()) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) diff --git a/examples/with-chi/main.go b/examples/with-chi/main.go index fd2f1c4b..8065f747 100644 --- a/examples/with-chi/main.go +++ b/examples/with-chi/main.go @@ -7,12 +7,12 @@ import ( "github.com/go-chi/chi/v5" "github.com/go-chi/cors" "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -30,7 +30,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -39,116 +39,119 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, }, }, }), + emailpassword.Init(nil), session.Init(nil), dashboard.Init(nil), }, diff --git a/examples/with-fiber/main.go b/examples/with-fiber/main.go index 2a2b1f9a..72f6f437 100644 --- a/examples/with-fiber/main.go +++ b/examples/with-fiber/main.go @@ -13,9 +13,8 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -33,7 +32,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -41,110 +40,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-gin/config/config.go b/examples/with-gin/config/config.go index 8722e0c9..59af48b3 100644 --- a/examples/with-gin/config/config.go +++ b/examples/with-gin/config/config.go @@ -1,16 +1,16 @@ package config import ( - "github.com/supertokens/supertokens-golang/recipe/dashboard" "log" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/spf13/viper" "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -49,8 +49,10 @@ func Init() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ - Providers: providers, + thirdparty.Init(&tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: providers, + }, }), session.Init(nil), dashboard.Init(nil), diff --git a/examples/with-go-zero/main.go b/examples/with-go-zero/main.go index 0d0b4113..8f8c0aee 100644 --- a/examples/with-go-zero/main.go +++ b/examples/with-go-zero/main.go @@ -2,17 +2,17 @@ package main import ( "encoding/json" - "github.com/supertokens/supertokens-golang/recipe/dashboard" "log" "net/http" "strings" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/zeromicro/go-zero/rest" ) @@ -31,7 +31,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -39,110 +39,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-http/main.go b/examples/with-http/main.go index 6a5e40d1..7b513221 100644 --- a/examples/with-http/main.go +++ b/examples/with-http/main.go @@ -2,16 +2,16 @@ package main import ( "encoding/json" - "github.com/supertokens/supertokens-golang/recipe/dashboard" "net/http" "strings" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -29,7 +29,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -38,110 +38,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-labstack-echo/main.go b/examples/with-labstack-echo/main.go index a080f934..a8f1e9f3 100644 --- a/examples/with-labstack-echo/main.go +++ b/examples/with-labstack-echo/main.go @@ -3,18 +3,18 @@ package main import ( "encoding/json" "errors" - "github.com/supertokens/supertokens-golang/recipe/dashboard" "net/http" "strings" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/labstack/echo/v4" "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -32,7 +32,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -41,110 +41,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-mux/main.go b/examples/with-mux/main.go index c388e022..b79fee89 100644 --- a/examples/with-mux/main.go +++ b/examples/with-mux/main.go @@ -2,17 +2,17 @@ package main import ( "encoding/json" - "github.com/supertokens/supertokens-golang/recipe/dashboard" "net/http" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/supertokens/supertokens-golang/recipe/emailverification" "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" ) @@ -30,7 +30,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -39,110 +39,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, diff --git a/examples/with-twirp/cmd/server/main.go b/examples/with-twirp/cmd/server/main.go index 0c27b65a..8f59037a 100644 --- a/examples/with-twirp/cmd/server/main.go +++ b/examples/with-twirp/cmd/server/main.go @@ -14,11 +14,12 @@ package main import ( - "github.com/supertokens/supertokens-golang/recipe/dashboard" "log" "net/http" "os" + "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/gorilla/handlers" "github.com/supertokens/supertokens-golang/examples/with-twirp/haberdasher" "github.com/supertokens/supertokens-golang/examples/with-twirp/internal/haberdasherserver" @@ -28,9 +29,8 @@ import ( "github.com/supertokens/supertokens-golang/recipe/emailverification/evmodels" "github.com/supertokens/supertokens-golang/recipe/session" "github.com/supertokens/supertokens-golang/recipe/session/sessmodels" + "github.com/supertokens/supertokens-golang/recipe/thirdparty" "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword" - "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels" "github.com/supertokens/supertokens-golang/supertokens" "github.com/twitchtv/twirp" ) @@ -49,7 +49,7 @@ func main() { emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, }), - thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ + thirdparty.Init(&tpmodels.TypeInput{ /* We use different credentials for different platforms when required. For example the redirect URI for Github is different for Web and mobile. In such a case we can provide multiple providers with different client Ids. @@ -58,110 +58,112 @@ func main() { request. In the absence of a clientId in the request the SDK uses the default provider, indicated by `isDefault: true`. When adding multiple providers for the same type (Google, Github etc), make sure to set `isDefault: true`. */ - Providers: []tpmodels.ProviderInput{ - // We have provided you with development keys which you can use for testsing. - // IMPORTANT: Please replace them with your own OAuth keys for production use. - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // we use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", - ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + // We have provided you with development keys which you can use for testsing. + // IMPORTANT: Please replace them with your own OAuth keys for production use. + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // we use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-c7mgk8p0h27c4428prfuo3lg7ould5o7.apps.googleusercontent.com", + ClientSecret: "", // this is empty because we follow Authorization code grant flow via PKCE for mobile apps (Google doesn't issue a client secret for mobile apps). + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "github", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "467101b197249757c71f", - ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "8a9152860ce869b64c44", - ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "github", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "467101b197249757c71f", + ClientSecret: "e97051221f4b6426e8fe8d51486396703012f5bd", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "8a9152860ce869b64c44", + ClientSecret: "00e841f10f288363cd3786b1b1f538f05cfdbda2", + }, }, }, }, - }, - /* - For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms - need to configure a Service ID on the Apple developer dashboard and use that as client ID. - In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS - the frontend for the demo app sends the clientId in the request which is then used by the SDK. - */ - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "apple", - Clients: []tpmodels.ProviderClientConfig{ - { - // For Android and website apps - ClientType: "web", - ClientID: "4398792-io.supertokens.example.service", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + /* + For Apple signin, iOS apps always use the bundle identifier as the client ID when communicating with Apple. Android, Web and other platforms + need to configure a Service ID on the Apple developer dashboard and use that as client ID. + In the example below 4398792-io.supertokens.example.service is the client ID for Web. Android etc and thus we mark it as default. For iOS + the frontend for the demo app sends the clientId in the request which is then used by the SDK. + */ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "apple", + Clients: []tpmodels.ProviderClientConfig{ + { + // For Android and website apps + ClientType: "web", + ClientID: "4398792-io.supertokens.example.service", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, - }, - { - // For iOS Apps - ClientType: "ios", - ClientID: "4398792-io.supertokens.example", - AdditionalConfig: map[string]interface{}{ - "keyId": "7M48Y4RYDL", - "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", - "teamId": "YWQCXGJRJL", + { + // For iOS Apps + ClientType: "ios", + ClientID: "4398792-io.supertokens.example", + AdditionalConfig: map[string]interface{}{ + "keyId": "7M48Y4RYDL", + "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + "teamId": "YWQCXGJRJL", + }, }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "discord", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "4398792-907871294886928395", - ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "discord", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "4398792-907871294886928395", + ClientSecret: "His4yXGEovVp5TZkZhEAt0ZXGh8uOVDm", + }, }, }, }, - }, - { - Config: tpmodels.ProviderConfig{ - ThirdPartyId: "google-workspaces", - Clients: []tpmodels.ProviderClientConfig{ - { - ClientType: "web", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", - }, - { - // We use this for mobile apps - ClientType: "mobile", - ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", - ClientSecret: "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", + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google-workspaces", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientType: "web", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, + { + // We use this for mobile apps + ClientType: "mobile", + ClientID: "1060725074195-kmeum4crr01uirfl2op9kd5acmi9jutn.apps.googleusercontent.com", + ClientSecret: "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", + }, }, }, }, From eacec9d3c56ac14d5871cdfc3c91b56e017ab705 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Wed, 1 May 2024 00:04:05 +0530 Subject: [PATCH 12/19] modifies readme --- CHANGELOG.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3883481..cce481fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,16 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] -## [0.18.0] - 2024-04-30 - -### Changes -- `session.CreateNewSession` now defaults to the value of the `st-auth-mode` header (if available) if the configured `config.GetTokenTransferMethod` returns `any`. -- Enable smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to change the signing key type of a session. - -### Breaking changes -- Make session required during signout. - -## Breaking change +### Breaking change - Removed ThirdPartyEmailPassword and ThirdPartyPasswordless recipes. Instead, you should use ThirdParty + EmailPassword or ThirdParty + Passwordless recipes separately in your recipe list. - Removed `rid` query param from: @@ -24,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - passwordless magic links - password reset links -## Changes +### Changes - If `rid` header is present in an API call, the routing no only only depends on that. If the SDK cannot resolve a request handler based on the `rid`, request path and method, it will try to resolve a request handler only based on the request path and method (therefore ignoring the `rid` header). - New API handlers are: @@ -33,12 +24,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GET /passwordless/phonenumber/exists` => email password, does email exist API (used to be `GET /signup/phonenumber/exists` which is now deprecated) - Support for FDI 2.0 -## Migration guide +### Migration guide - If you were using `ThirdPartyEmailPassword`, you should now init `ThirdParty` and `EmailPassword` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [EmailPassword](https://supertokens.com/docs/emailpassword/introduction) for more information. - If you were using `ThirdPartyPasswordless`, you should now init `ThirdParty` and `Passwordless` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [Passwordless](https://supertokens.com/docs/passwordless/introduction) for more information. +## [0.18.0] - 2024-04-30 + +### Changes +- `session.CreateNewSession` now defaults to the value of the `st-auth-mode` header (if available) if the configured `config.GetTokenTransferMethod` returns `any`. +- Enable smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to change the signing key type of a session. + +### Breaking changes +- Make session required during signout. ## [0.17.5] - 2024-03-14 - Adds a type uint64 to the `accessTokenCookiesExpiryDurationMillis` local variable in `recipe/session/utils.go`. It also removes the redundant `uint64` type forcing needed because of the untyped variable. From 4180c5c039de75bddacb8aee98ea03dbad1af109 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Mon, 13 May 2024 12:07:20 +0530 Subject: [PATCH 13/19] fixes bug related to pointer being used in a loop --- .../authorisationUrlFeature_test.go | 82 +++++++++++++++++++ supertokens/supertokens.go | 6 +- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/recipe/thirdparty/authorisationUrlFeature_test.go b/recipe/thirdparty/authorisationUrlFeature_test.go index d2eb2f67..4e0c0ac1 100644 --- a/recipe/thirdparty/authorisationUrlFeature_test.go +++ b/recipe/thirdparty/authorisationUrlFeature_test.go @@ -113,6 +113,88 @@ func TestReqWithThirdPartyEmailPasswordRecipe(t *testing.T) { assert.Equal(t, "/dev/oauth/redirect-to-provider", fetchedUrl.Path) } +func TestReqWithThirdPartyEmailPasswordRecipe2(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( + &tpmodels.TypeInput{ + SignInAndUpFeature: tpmodels.TypeInputSignInAndUp{ + Providers: []tpmodels.ProviderInput{ + { + Config: tpmodels.ProviderConfig{ + ThirdPartyId: "google", + Clients: []tpmodels.ProviderClientConfig{ + { + ClientID: "4398792-test-id", + ClientSecret: "test-secret", + }, + }, + }, + }, + }, + }, + }, + ), + emailpassword.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() + + client := &http.Client{} + req, _ := http.NewRequest("GET", testServer.URL+"/auth/authorisationurl?thirdPartyId=google", nil) + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("rid", "thirdpartyemailpassword") + + resp, err := client.Do(req) + + if err != nil { + t.Error(err.Error()) + } + + 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.Equal(t, "OK", data["status"]) + + fetchedUrl, err := url.Parse(data["urlWithQueryParams"].(string)) + if err != nil { + t.Error(err.Error()) + } + + assert.Equal(t, "supertokens.io", fetchedUrl.Host) + assert.Equal(t, "/dev/oauth/redirect-to-provider", fetchedUrl.Path) +} + func TestUsingDevOAuthKeysWillUseDevAuthUrl(t *testing.T) { configValue := supertokens.TypeInput{ Supertokens: &supertokens.ConnectionInfo{ diff --git a/supertokens/supertokens.go b/supertokens/supertokens.go index b5d5f825..630d782f 100644 --- a/supertokens/supertokens.go +++ b/supertokens/supertokens.go @@ -210,7 +210,7 @@ func (s *superTokens) middleware(theirHandler http.Handler) http.Handler { var id *string = nil var finalTenantId *string = nil - var finalMatchedRecipe *RecipeModule = nil + var finalMatchedRecipe RecipeModule = RecipeModule{} for _, matchedRecipe := range matchedRecipes { currId, currTenantId, err := matchedRecipe.ReturnAPIIdIfCanHandleRequest(path, method, userContext) @@ -231,12 +231,12 @@ func (s *superTokens) middleware(theirHandler http.Handler) http.Handler { } else { id = currId finalTenantId = &currTenantId - finalMatchedRecipe = &matchedRecipe + finalMatchedRecipe = matchedRecipe } } } - if id == nil || finalTenantId == nil || finalMatchedRecipe == nil { + if id == nil || finalTenantId == nil { s.middlewareHelperHandleWithoutRid(path, method, userContext, theirHandler, dw, r) return } From b5b21baddeda30ae2a74c636b90c2827ec1e82ff Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 16 May 2024 21:37:18 +0530 Subject: [PATCH 14/19] updates example app --- examples/with-gin/config/config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/with-gin/config/config.go b/examples/with-gin/config/config.go index 59af48b3..f8dfcd4d 100644 --- a/examples/with-gin/config/config.go +++ b/examples/with-gin/config/config.go @@ -4,6 +4,7 @@ import ( "log" "github.com/supertokens/supertokens-golang/recipe/dashboard" + "github.com/supertokens/supertokens-golang/recipe/emailpassword" "github.com/spf13/viper" "github.com/supertokens/supertokens-golang/recipe/emailverification" @@ -54,6 +55,7 @@ func Init() { Providers: providers, }, }), + emailpassword.Init(nil), session.Init(nil), dashboard.Init(nil), // thirdparty.Init(thirdpartyConfig), From d915704a72d6c41976936ec065d554eca6cf2025 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 23 May 2024 12:20:56 +0530 Subject: [PATCH 15/19] changes to changelog --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8435b515..934d3ece 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - If you were using `ThirdPartyPasswordless`, you should now init `ThirdParty` and `Passwordless` recipes separately. The config for the individual recipes are mostly the same, except the syntax may be different. Check our recipe guides for [ThirdParty](https://supertokens.com/docs/thirdparty/introduction) and [Passwordless](https://supertokens.com/docs/passwordless/introduction) for more information. +- The way to get user information has changed: + - If you are using `thirdpartyemailpassword.GetUsersByEmail`: + Before: + ```go + userInfo, err := thirdpartyemailpassword.GetUsersByEmail("public", "test@example.com") + ``` + + After: + ```go + thirdPartyUserInfo, err := thirdparty.GetUsersByEmail("public", "test@example.com") + if err != nil { + // TODO: Handle error + } + + emailPasswordUserInfo, err := emailpassword.GetUserByEmail("public", "test@example.com") + if err != nil { + // TODO: Handle error + } + + if emailPasswordUserInfo != nil { + fmt.Println(emailPasswordUserInfo) + } + if len(thirdPartyUserInfo) > 0 { + fmt.Println(thirdPartyUserInfo) + } + ``` + + - If you are using `thirdpartyemailpassword.GetUserById`: + Before: + ```go + userInfo, err := thirdpartyemailpassword.GetUserById(userID) + ``` + + After: + ```go + userInfo, err := thirdparty.GetUserByID(userID) + if err != nil { + // TODO: Handle error + } + if userInfo == nil { + emailPasswordUserInfo, err := emailpassword.GetUserByID(userID) + if err != nil { + // TODO: Handle error + } + fmt.Println(emailPasswordUserInfo) + } else { + fmt.Println(userInfo) + } + ``` + ## [0.19.0] - 2024-05-01 - Added `OlderCookieDomain` config option in the session recipe. This will allow users to clear cookies from the older domain when the `CookieDomain` is changed. From d335af0af28d369bd4f4224323aa0a24468baf2b Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 23 May 2024 12:22:55 +0530 Subject: [PATCH 16/19] changes to changelog --- CHANGELOG.md | 78 +++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 934d3ece..352bc4ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,53 +32,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The way to get user information has changed: - If you are using `thirdpartyemailpassword.GetUsersByEmail`: - Before: - ```go - userInfo, err := thirdpartyemailpassword.GetUsersByEmail("public", "test@example.com") - ``` + + Before: + ```go + userInfo, err := thirdpartyemailpassword.GetUsersByEmail("public", "test@example.com") + ``` - After: - ```go - thirdPartyUserInfo, err := thirdparty.GetUsersByEmail("public", "test@example.com") - if err != nil { - // TODO: Handle error - } + After: + ```go + thirdPartyUserInfo, err := thirdparty.GetUsersByEmail("public", "test@example.com") + if err != nil { + // TODO: Handle error + } - emailPasswordUserInfo, err := emailpassword.GetUserByEmail("public", "test@example.com") - if err != nil { - // TODO: Handle error - } + emailPasswordUserInfo, err := emailpassword.GetUserByEmail("public", "test@example.com") + if err != nil { + // TODO: Handle error + } - if emailPasswordUserInfo != nil { - fmt.Println(emailPasswordUserInfo) - } - if len(thirdPartyUserInfo) > 0 { - fmt.Println(thirdPartyUserInfo) - } - ``` + if emailPasswordUserInfo != nil { + fmt.Println(emailPasswordUserInfo) + } + if len(thirdPartyUserInfo) > 0 { + fmt.Println(thirdPartyUserInfo) + } + ``` - If you are using `thirdpartyemailpassword.GetUserById`: - Before: - ```go - userInfo, err := thirdpartyemailpassword.GetUserById(userID) - ``` + + Before: + ```go + userInfo, err := thirdpartyemailpassword.GetUserById(userID) + ``` - After: - ```go - userInfo, err := thirdparty.GetUserByID(userID) - if err != nil { - // TODO: Handle error - } - if userInfo == nil { - emailPasswordUserInfo, err := emailpassword.GetUserByID(userID) + After: + ```go + userInfo, err := thirdparty.GetUserByID(userID) if err != nil { // TODO: Handle error } - fmt.Println(emailPasswordUserInfo) - } else { - fmt.Println(userInfo) - } - ``` + if userInfo == nil { + emailPasswordUserInfo, err := emailpassword.GetUserByID(userID) + if err != nil { + // TODO: Handle error + } + fmt.Println(emailPasswordUserInfo) + } else { + fmt.Println(userInfo) + } + ``` ## [0.19.0] - 2024-05-01 From c49832d626b6a9a8265dfac89eac2f4a563ae6a1 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 23 May 2024 12:26:11 +0530 Subject: [PATCH 17/19] changes to changelog --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 352bc4ca..b53d3bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 fmt.Println(userInfo) } ``` + - If you are using `thirdpartypasswordless.GetUsersByEmail`: + + Before: + ```go + userInfo, err := thirdpartypasswordless.GetUsersByEmail("public", "test@example.com") + ``` + + After: + ```go + thirdPartyUserInfo, err := thirdparty.GetUsersByEmail("public", "test@example.com") + if err != nil { + return + } + + passwordlessUserInfo, err := passwordless.GetUserByEmail("public", "test@example.com") + if err != nil { + return + } + + if passwordlessUserInfo != nil { + fmt.Println(passwordlessUserInfo) + } + if len(thirdPartyUserInfo) > 0 { + fmt.Println(thirdPartyUserInfo) + } + ``` + + - If you are using `thirdpartypasswordless.GetUserById`: + + Before: + ```go + userInfo, err := thirdpartypasswordless.GetUserById(userID) + ``` + + After: + ```go + userInfo, err := thirdparty.GetUserByID(userID) + if err != nil { + // TODO: Handle error + } + if userInfo == nil { + passwordlessUserInfo, err := passwordless.GetUserByID(userID) + if err != nil { + // TODO: Handle error + } + fmt.Println(passwordlessUserInfo) + } else { + fmt.Println(userInfo) + } + ``` ## [0.19.0] - 2024-05-01 From e780bb125e72278ea42d54a65cea21f57f65e1b3 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 23 May 2024 12:27:59 +0530 Subject: [PATCH 18/19] bumps version --- CHANGELOG.md | 2 ++ supertokens/constants.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b53d3bd2..975801cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [0.20.0] - 2024-05-23 + ### Breaking change - Removed ThirdPartyEmailPassword and ThirdPartyPasswordless recipes. Instead, you should use ThirdParty + EmailPassword or ThirdParty + Passwordless recipes separately in your recipe list. diff --git a/supertokens/constants.go b/supertokens/constants.go index a62dfa7f..879aa905 100644 --- a/supertokens/constants.go +++ b/supertokens/constants.go @@ -21,7 +21,7 @@ const ( ) // VERSION current version of the lib -const VERSION = "0.19.0" +const VERSION = "0.20.0" var ( cdiSupported = []string{"3.0"} From afd9b0ff437f5c51e428d8ab949311014e9a1c42 Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Thu, 23 May 2024 15:17:23 +0530 Subject: [PATCH 19/19] removes unnecessary commented code in auth-react server --- test/auth-react-server/main.go | 233 --------------------------------- 1 file changed, 233 deletions(-) diff --git a/test/auth-react-server/main.go b/test/auth-react-server/main.go index 60139127..531ae598 100644 --- a/test/auth-react-server/main.go +++ b/test/auth-react-server/main.go @@ -326,134 +326,6 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { }, }, }), - // thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ - // EmailDelivery: &emaildelivery.TypeInput{ - // Service: &emaildelivery.EmailDeliveryInterface{ - // SendEmail: &sendPasswordResetEmail, - // }, - // }, - // Override: &tpepmodels.OverrideStruct{ - // APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface { - // ogPasswordResetPOST := *originalImplementation.PasswordResetPOST - // ogGeneratePasswordResetTokenPOST := *originalImplementation.GeneratePasswordResetTokenPOST - // ogEmailExistsGET := *originalImplementation.EmailPasswordEmailExistsGET - // ogSignUpPOST := *originalImplementation.EmailPasswordSignUpPOST - // ogSignInPOST := *originalImplementation.EmailPasswordSignInPOST - // ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET - // ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST - - // (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) - // if gr != nil { - // return tpmodels.AuthorisationUrlGETResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - // } - - // (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.ThirdPartySignInUpPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) - // if gr != nil { - // return tpepmodels.ThirdPartySignInUpPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogSignInUpPOST(provider, input, tenantId, options, userContext) - // } - - // (*originalImplementation.PasswordResetPOST) = func(formFields []epmodels.TypeFormField, token string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.ResetPasswordPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password consume", false) - // if gr != nil { - // return epmodels.ResetPasswordPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogPasswordResetPOST(formFields, token, tenantId, options, userContext) - // } - - // (*originalImplementation.GeneratePasswordResetTokenPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.GeneratePasswordResetTokenPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API reset password", false) - // if gr != nil { - // return epmodels.GeneratePasswordResetTokenPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogGeneratePasswordResetTokenPOST(formFields, tenantId, options, userContext) - // } - - // (*originalImplementation.EmailPasswordEmailExistsGET) = func(email string, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.EmailExistsGETResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API email exists", true) - // if gr != nil { - // return epmodels.EmailExistsGETResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogEmailExistsGET(email, tenantId, options, userContext) - // } - - // (*originalImplementation.EmailPasswordSignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignUpPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign up", false) - // if gr != nil { - // return tpepmodels.SignUpPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogSignUpPOST(formFields, tenantId, options, userContext) - // } - - // (*originalImplementation.EmailPasswordSignInPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (tpepmodels.SignInPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in", false) - // if gr != nil { - // return tpepmodels.SignInPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogSignInPOST(formFields, tenantId, options, userContext) - // } - // return originalImplementation - // }, - // }, - // SignUpFeature: &epmodels.TypeInputSignUp{ - // FormFields: formFields, - // }, - // Providers: []tpmodels.ProviderInput{ - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "google", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("GOOGLE_CLIENT_ID"), - // ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "github", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("GITHUB_CLIENT_ID"), - // ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "facebook", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), - // ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // customAuth0Provider(), - // }, - // }), session.Init(&sessmodels.TypeInput{ Override: &sessmodels.OverrideStruct{ APIs: func(originalImplementation sessmodels.APIInterface) sessmodels.APIInterface { @@ -527,111 +399,6 @@ func callSTInit(passwordlessConfig *plessmodels.TypeInput) { }, }, }), - // thirdpartypasswordless.Init(tplmodels.TypeInput{ - // ContactMethodPhone: passwordlessConfig.ContactMethodPhone, - // ContactMethodEmail: passwordlessConfig.ContactMethodEmail, - // ContactMethodEmailOrPhone: passwordlessConfig.ContactMethodEmailOrPhone, - // FlowType: passwordlessConfig.FlowType, - // GetCustomUserInputCode: passwordlessConfig.GetCustomUserInputCode, - // EmailDelivery: passwordlessConfig.EmailDelivery, - // SmsDelivery: passwordlessConfig.SmsDelivery, - // Providers: []tpmodels.ProviderInput{ - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "google", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("GOOGLE_CLIENT_ID"), - // ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "github", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("GITHUB_CLIENT_ID"), - // ClientSecret: os.Getenv("GITHUB_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // { - // Config: tpmodels.ProviderConfig{ - // ThirdPartyId: "facebook", - // Clients: []tpmodels.ProviderClientConfig{ - // { - // ClientID: os.Getenv("FACEBOOK_CLIENT_ID"), - // ClientSecret: os.Getenv("FACEBOOK_CLIENT_SECRET"), - // }, - // }, - // }, - // }, - // customAuth0Provider(), - // }, - // Override: &tplmodels.OverrideStruct{ - // APIs: func(originalImplementation tplmodels.APIInterface) tplmodels.APIInterface { - // ogConsumeCodePOST := *originalImplementation.ConsumeCodePOST - // ogCreateCodePOST := *originalImplementation.CreateCodePOST - // ogResendCodePOST := *originalImplementation.ResendCodePOST - // ogAuthorisationUrlGET := *originalImplementation.AuthorisationUrlGET - // ogSignInUpPOST := *originalImplementation.ThirdPartySignInUpPOST - - // (*originalImplementation.AuthorisationUrlGET) = func(provider *tpmodels.TypeProvider, redirectURIOnProviderDashboard string, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tpmodels.AuthorisationUrlGETResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API authorisation url get", true) - // if gr != nil { - // return tpmodels.AuthorisationUrlGETResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogAuthorisationUrlGET(provider, redirectURIOnProviderDashboard, tenantId, options, userContext) - // } - - // (*originalImplementation.ThirdPartySignInUpPOST) = func(provider *tpmodels.TypeProvider, input tpmodels.TypeSignInUpInput, tenantId string, options tpmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ThirdPartySignInUpPOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API sign in up", false) - // if gr != nil { - // return tplmodels.ThirdPartySignInUpPOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogSignInUpPOST(provider, input, tenantId, options, userContext) - // } - - // (*originalImplementation.ConsumeCodePOST) = func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (tplmodels.ConsumeCodePOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API consume code", false) - // if gr != nil { - // return tplmodels.ConsumeCodePOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogConsumeCodePOST(userInput, linkCode, preAuthSessionID, tenantId, options, userContext) - // } - - // (*originalImplementation.CreateCodePOST) = func(email, phoneNumber *string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.CreateCodePOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API create code", false) - // if gr != nil { - // return plessmodels.CreateCodePOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogCreateCodePOST(email, phoneNumber, tenantId, options, userContext) - // } - - // (*originalImplementation.ResendCodePOST) = func(deviceID, preAuthSessionID string, tenantId string, options plessmodels.APIOptions, userContext supertokens.UserContext) (plessmodels.ResendCodePOSTResponse, error) { - // gr := returnGeneralErrorIfNeeded(*options.Req, "general error from API resend code", false) - // if gr != nil { - // return plessmodels.ResendCodePOSTResponse{ - // GeneralError: gr, - // }, nil - // } - // return ogResendCodePOST(deviceID, preAuthSessionID, tenantId, options, userContext) - // } - // return originalImplementation - // }, - // }, - // }), userroles.Init(nil), }, })