Skip to content

Commit

Permalink
adds more tests and linkAccounts recipe function
Browse files Browse the repository at this point in the history
  • Loading branch information
rishabhpoddar committed Dec 13, 2023
1 parent d7c94be commit 9b7223c
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 2 deletions.
59 changes: 59 additions & 0 deletions recipe/emailpassword/accountlinkingRecipeImplementation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,65 @@ func TestCanMakePrimaryUser(t *testing.T) {
assert.True(t, response.OK.WasAlreadyAPrimaryUser)
}

func TestMakePrimaryFailCauseAlreadyLinkedToAnotherAccount(t *testing.T) {
BeforeEach()
unittesting.StartUpST("localhost", "8080")
defer AfterEach()
telemetry := false
supertokens.Init(supertokens.TypeInput{
Supertokens: &supertokens.ConnectionInfo{
ConnectionURI: "http://localhost:8080",
},
AppInfo: supertokens.AppInfo{
AppName: "Testing",
Origin: "http://localhost:3000",
APIDomain: "http://localhost:3001",
},
Telemetry: &telemetry,
RecipeList: []supertokens.Recipe{
Init(nil),
},
})

epuser, err := SignUp("public", "test@gmail.com", "pass123")
if err != nil {
t.Error(err)
return
}

user1 := convertEpUserToSuperTokensUser(epuser.OK.User)
assert.False(t, user1.IsPrimaryUser)

epuser2, err := SignUp("public", "test2@gmail.com", "pass123")
if err != nil {
t.Error(err)
return
}

user2 := convertEpUserToSuperTokensUser(epuser2.OK.User)

assert.False(t, user2.IsPrimaryUser)

_, err = supertokens.CreatePrimaryUser(user1.LoginMethods[0].RecipeUserID)
if err != nil {
t.Error(err)
return
}
_, err = supertokens.LinkAccounts(user2.LoginMethods[0].RecipeUserID, user1.ID)
if err != nil {
t.Error(err)
return
}

createPrimaryUserResponse, err := supertokens.CreatePrimaryUser(user2.LoginMethods[0].RecipeUserID)
if err != nil {
t.Error(err)
return
}
assert.Nil(t, createPrimaryUserResponse.OK)
assert.Equal(t, createPrimaryUserResponse.RecipeUserIdAlreadyLinkedWithPrimaryUserIdError.PrimaryUserId, user1.ID)
}

// TODO: remove this function
func convertEpUserToSuperTokensUser(epuser epmodels.User) supertokens.User {
rUId, err := supertokens.NewRecipeUserID(epuser.ID)
Expand Down
2 changes: 1 addition & 1 deletion supertokens/accountlinkingRecipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func makeAccountLinkingRecipe(recipeId string, appInfo NormalisedAppinfo, config
if err != nil {
return AccountLinkingRecipe{}, err
}
recipeImplementation := makeRecipeImplementation(*querierInstance)
recipeImplementation := makeRecipeImplementation(*querierInstance, verifiedConfig)
r.RecipeImpl = verifiedConfig.Override.Functions(recipeImplementation)

recipeModuleInstance := MakeRecipeModule(recipeId, appInfo, r.handleAPIRequest, r.getAllCORSHeaders, r.getAPIsHandled, nil, r.handleError, onSuperTokensAPIError)
Expand Down
100 changes: 99 additions & 1 deletion supertokens/accountlinkingRecipeImplementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ package supertokens

import (
"encoding/json"
"errors"
"strconv"
"strings"
)

func makeRecipeImplementation(querier Querier) AccountLinkingRecipeInterface {
func makeRecipeImplementation(querier Querier, config AccountLinkingTypeNormalisedInput) AccountLinkingRecipeInterface {

getUsers := func(tenantID string, timeJoinedOrder string, paginationToken *string, limit *int, includeRecipeIds *[]string, searchParams map[string]string, userContext UserContext) (UserPaginationResult, error) {
requestBody := map[string]string{}
Expand Down Expand Up @@ -182,11 +183,108 @@ func makeRecipeImplementation(querier Querier) AccountLinkingRecipeInterface {
}
}

linkAccounts := func(recipeUserId RecipeUserID, primaryUserId string, userContext UserContext) (LinkAccountResponse, error) {
requestBody := map[string]interface{}{
"recipeUserId": recipeUserId.GetAsString(),
"primaryUserId": primaryUserId,
}
resp, err := querier.SendPostRequest("/recipe/accountlinking/user/link", requestBody, userContext)

if err != nil {
return LinkAccountResponse{}, err
}

if resp["status"].(string) == "OK" {
var user = User{}
temporaryVariable, err := json.Marshal(resp["user"])
if err != nil {
return LinkAccountResponse{}, err
}
err = json.Unmarshal(temporaryVariable, &user)
if err != nil {
return LinkAccountResponse{}, err
}
response := LinkAccountResponse{
OK: &struct {
AccountsAlreadyLinked bool
User User
}{
AccountsAlreadyLinked: resp["accountsAlreadyLinked"].(bool),
User: user,
},
}

// TODO: call verifyEmailForRecipeUserIfLinkedAccountsAreVerified

updatedUser, err := GetUser(user.ID, userContext)
if err != nil {
return LinkAccountResponse{}, err
}
if updatedUser == nil {
return LinkAccountResponse{}, errors.New("this should never be thrown")
}
response.OK.User = *updatedUser
var loginMethod *LoginMethods = nil
for _, method := range response.OK.User.LoginMethods {
if method.RecipeUserID.GetAsString() == recipeUserId.GetAsString() {
loginMethod = &method
break
}
}

if loginMethod == nil {
return LinkAccountResponse{}, errors.New("this should never be thrown")
}

err = config.OnAccountLinked(response.OK.User, loginMethod.RecipeLevelUser, userContext)
if err != nil {
return LinkAccountResponse{}, err
}

return response, nil
} else if resp["status"].(string) == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" {
var user = User{}
temporaryVariable, err := json.Marshal(resp["user"])
if err != nil {
return LinkAccountResponse{}, err
}
err = json.Unmarshal(temporaryVariable, &user)
if err != nil {
return LinkAccountResponse{}, err
}

return LinkAccountResponse{
RecipeUserIdAlreadyLinkedWithAnotherPrimaryUserIdError: &struct {
PrimaryUserId string
User User
}{
PrimaryUserId: resp["primaryUserId"].(string),
User: user,
},
}, nil
} else if resp["status"].(string) == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" {
return LinkAccountResponse{
AccountInfoAlreadyAssociatedWithAnotherPrimaryUserIdError: &struct {
PrimaryUserId string
Description string
}{
PrimaryUserId: resp["primaryUserId"].(string),
Description: resp["description"].(string),
},
}, nil
} else {
return LinkAccountResponse{
InputUserIsNotAPrimaryUserError: &struct{}{},
}, nil
}
}

// TODO:...
return AccountLinkingRecipeInterface{
GetUsersWithSearchParams: &getUsers,
GetUser: &getUser,
CanCreatePrimaryUser: &canCreatePrimaryUser,
CreatePrimaryUser: &createPrimaryUser,
LinkAccounts: &linkAccounts,
}
}
13 changes: 13 additions & 0 deletions supertokens/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,16 @@ func CreatePrimaryUser(recipeUserId RecipeUserID, userContext ...UserContext) (C

return (*accountLinkingInstance.RecipeImpl.CreatePrimaryUser)(recipeUserId, userContext[0])
}

func LinkAccounts(recipeUserId RecipeUserID, primaryUserId string, userContext ...UserContext) (LinkAccountResponse, error) {
accountLinkingInstance, err := getAccountLinkingRecipeInstanceOrThrowError()
if err != nil {
return LinkAccountResponse{}, err
}

if len(userContext) == 0 {
userContext = append(userContext, &map[string]interface{}{})
}

return (*accountLinkingInstance.RecipeImpl.LinkAccounts)(recipeUserId, primaryUserId, userContext[0])
}

0 comments on commit 9b7223c

Please sign in to comment.