diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b3ebd8d..e313ba84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [0.16.2] - 2023-10-17 + +- Fixes an issue where tenant ids returned for a user from the user get API of the dashboard recipe would always be nil for thirdpartyemailpassword and thirdpartypasswordless recipes + ## [0.16.1] - 2023-10-03 ### Changes diff --git a/recipe/dashboard/api/userdetails/userGet.go b/recipe/dashboard/api/userdetails/userGet.go index 5952c5c6..4f0e66d5 100644 --- a/recipe/dashboard/api/userdetails/userGet.go +++ b/recipe/dashboard/api/userdetails/userGet.go @@ -24,37 +24,37 @@ import ( "github.com/supertokens/supertokens-golang/supertokens" ) -type userGetResponse struct { +type UserGetResponse struct { Status string `json:"status"` RecipeId string `json:"recipeId,omitempty"` User dashboardmodels.UserType `json:"user,omitempty"` } -func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, options dashboardmodels.APIOptions, userContext supertokens.UserContext) (userGetResponse, error) { +func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, options dashboardmodels.APIOptions, userContext supertokens.UserContext) (UserGetResponse, error) { req := options.Req userId := req.URL.Query().Get("userId") recipeId := req.URL.Query().Get("recipeId") if userId == "" { - return userGetResponse{}, supertokens.BadInputError{ + return UserGetResponse{}, supertokens.BadInputError{ Msg: "Missing required parameter 'userId'", } } if recipeId == "" { - return userGetResponse{}, supertokens.BadInputError{ + return UserGetResponse{}, supertokens.BadInputError{ Msg: "Missing required parameter 'recipeId'", } } if !api.IsValidRecipeId(recipeId) { - return userGetResponse{}, supertokens.BadInputError{ + return UserGetResponse{}, supertokens.BadInputError{ Msg: "Invalid recipe id", } } if !api.IsRecipeInitialised(recipeId) { - return userGetResponse{ + return UserGetResponse{ Status: "RECIPE_NOT_INITIALISED", }, nil } @@ -62,7 +62,7 @@ func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, op userForRecipeId, _ := api.GetUserForRecipeId(userId, recipeId, userContext) if reflect.DeepEqual(userForRecipeId, dashboardmodels.UserType{}) { - return userGetResponse{ + return UserGetResponse{ Status: "NO_USER_FOUND_ERROR", }, nil } @@ -74,7 +74,7 @@ func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, op userForRecipeId.FirstName = "FEATURE_NOT_ENABLED" userForRecipeId.LastName = "FEATURE_NOT_ENABLED" - return userGetResponse{ + return UserGetResponse{ Status: "OK", RecipeId: recipeId, User: userForRecipeId, @@ -84,7 +84,7 @@ func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, op metadata, metadataerr := usermetadata.GetUserMetadata(userId, userContext) if metadataerr != nil { - return userGetResponse{}, metadataerr + return UserGetResponse{}, metadataerr } // first and last name should be an empty string if they dont exist in metadata @@ -99,7 +99,7 @@ func UserGet(apiImplementation dashboardmodels.APIInterface, tenantId string, op userForRecipeId.LastName = metadata["last_name"].(string) } - return userGetResponse{ + return UserGetResponse{ Status: "OK", RecipeId: recipeId, User: userForRecipeId, diff --git a/recipe/dashboard/userGet_test.go b/recipe/dashboard/userGet_test.go new file mode 100644 index 00000000..28a2c8f2 --- /dev/null +++ b/recipe/dashboard/userGet_test.go @@ -0,0 +1,81 @@ +package dashboard + +import ( + "encoding/json" + "github.com/supertokens/supertokens-golang/recipe/dashboard/api/userdetails" + "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 +*/ +func TestThatUserGetReturnsTenantIDsCorrectly(t *testing.T) { + config := supertokens.TypeInput{ + OnSuperTokensAPIError: func(err error, req *http.Request, res http.ResponseWriter) { + print(err) + }, + Supertokens: &supertokens.ConnectionInfo{ + ConnectionURI: "http://localhost:8080", + }, + AppInfo: supertokens.AppInfo{ + APIDomain: "api.supertokens.io", + AppName: "SuperTokens", + WebsiteDomain: "supertokens.io", + }, + RecipeList: []supertokens.Recipe{ + thirdpartyemailpassword.Init(nil), + Init(&dashboardmodels.TypeInput{ + ApiKey: "testapikey", + }), + }, + } + + BeforeEach() + unittesting.StartUpST("localhost", "8080") + defer AfterEach() + err := supertokens.Init(config) + if err != nil { + t.Error(err.Error()) + } + + mux := http.NewServeMux() + testServer := httptest.NewServer(supertokens.Middleware(mux)) + defer testServer.Close() + + signupResponse, err := thirdpartyemailpassword.EmailPasswordSignUp("public", "testing@supertokens.com", "abcd1234") + if err != nil { + t.Error(err.Error()) + } + + assert.NotNil(t, signupResponse.OK) + + userId := signupResponse.OK.User.ID + + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/auth/dashboard/api/user?userId="+userId+"&recipeId=emailpassword", strings.NewReader(`{}`)) + req.Header.Set("Authorization", "Bearer testapikey") + res, err := http.DefaultClient.Do(req) + + if err != nil { + t.Error(err.Error()) + } + + var response userdetails.UserGetResponse + body, _ := io.ReadAll(res.Body) + json.Unmarshal(body, &response) + + assert.True(t, len(response.User.TenantIds) > 0) + assert.Equal(t, response.User.TenantIds[0], "public") +} diff --git a/recipe/thirdpartyemailpassword/recipeimplementation/main.go b/recipe/thirdpartyemailpassword/recipeimplementation/main.go index 627c165f..f5a2a3d7 100644 --- a/recipe/thirdpartyemailpassword/recipeimplementation/main.go +++ b/recipe/thirdpartyemailpassword/recipeimplementation/main.go @@ -173,6 +173,7 @@ func MakeRecipeImplementation(emailPasswordQuerier supertokens.Querier, thirdPar ID: user.ID, Email: user.Email, TimeJoined: user.TimeJoined, + TenantIds: user.TenantIds, ThirdParty: nil, }, nil } @@ -191,6 +192,7 @@ func MakeRecipeImplementation(emailPasswordQuerier supertokens.Querier, thirdPar Email: userinfo.Email, TimeJoined: userinfo.TimeJoined, ThirdParty: &userinfo.ThirdParty, + TenantIds: userinfo.TenantIds, }, nil } return nil, nil diff --git a/recipe/thirdpartypasswordless/recipeimplementation/main.go b/recipe/thirdpartypasswordless/recipeimplementation/main.go index d2d94a6d..b1cb8f0e 100644 --- a/recipe/thirdpartypasswordless/recipeimplementation/main.go +++ b/recipe/thirdpartypasswordless/recipeimplementation/main.go @@ -123,6 +123,7 @@ func MakeRecipeImplementation(passwordlessQuerier supertokens.Querier, thirdPart Email: user.Email, PhoneNumber: user.PhoneNumber, TimeJoined: user.TimeJoined, + TenantIds: user.TenantIds, ThirdParty: nil, }, nil } diff --git a/supertokens/constants.go b/supertokens/constants.go index 69416d4d..7c4ba93c 100644 --- a/supertokens/constants.go +++ b/supertokens/constants.go @@ -21,7 +21,7 @@ const ( ) // VERSION current version of the lib -const VERSION = "0.16.1" +const VERSION = "0.16.2" var ( cdiSupported = []string{"3.0"}