func (suite *AccountsTestSuite) TestConfirmEmailWithAutologinFlag() { var ( testOauthUser *oauth.User testUser *accounts.User testConfirmation *accounts.Confirmation err error ) // Insert a test user testOauthUser, err = suite.service.GetOauthService().CreateUser( roles.User, "harold@finch", "test_password", ) assert.NoError(suite.T(), err, "Failed to insert a test oauth user") testUser, err = accounts.NewUser( suite.accounts[0], testOauthUser, "", //facebook ID false, // confirmed &accounts.UserRequest{ FirstName: "Harold", LastName: "Finch", }, ) assert.NoError(suite.T(), err, "Failed to create a new user object") err = suite.db.Create(testUser).Error assert.NoError(suite.T(), err, "Failed to insert a test user") testUser.Account = suite.accounts[0] // Insert a test confirmation testConfirmation, err = accounts.NewConfirmation( testUser, suite.cnf.AppSpecific.ConfirmationLifetime, ) assert.NoError(suite.T(), err, "Failed to create a new confirmation object") err = suite.db.Create(testConfirmation).Error assert.NoError(suite.T(), err, "Failed to insert a test confirmation") testConfirmation.User = testUser // Prepare a request r, err := http.NewRequest( "GET", fmt.Sprintf( "http://1.2.3.4/v1/confirmations/%s?autologin=true", testConfirmation.Reference, ), nil, ) assert.NoError(suite.T(), err, "Request setup should not get an error") r.Header.Set( "Authorization", fmt.Sprintf( "Basic %s", b64.StdEncoding.EncodeToString([]byte("test_client_1:test_secret")), ), ) // Check the routing match := new(mux.RouteMatch) suite.router.Match(r, match) if assert.NotNil(suite.T(), match.Route) { assert.Equal(suite.T(), "confirm_email", match.Route.GetName()) } // Count before var ( countBefore int accessTokensCountBefore int refreshTokensCountBefore int ) suite.db.Model(new(accounts.Confirmation)).Count(&countBefore) suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountBefore) suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountBefore) // And serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Count after var ( countAfter int accessTokensCountAfter int refreshTokensCountAfter int ) suite.db.Model(new(accounts.Confirmation)).Count(&countAfter) suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountAfter) suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountAfter) assert.Equal(suite.T(), countBefore-1, countAfter) assert.Equal(suite.T(), accessTokensCountBefore+1, accessTokensCountAfter) assert.Equal(suite.T(), refreshTokensCountBefore+1, refreshTokensCountAfter) // Fetch the updated user user := new(accounts.User) notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound() assert.False(suite.T(), notFound) // Confirmation should have been soft deleteted assert.True(suite.T(), suite.db.Last(new(accounts.Confirmation)).RecordNotFound()) // And correct data was saved assert.True(suite.T(), user.Confirmed) // Fetch login data accessToken, refreshToken := new(oauth.AccessToken), new(oauth.RefreshToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). Last(refreshToken).RecordNotFound()) // Check the response expectedEmbeddedTokenResponse, err := oauth.NewAccessTokenResponse( accessToken, refreshToken, suite.cnf.Oauth.AccessTokenLifetime, tokentypes.Bearer, ) assert.NoError(suite.T(), err, "Failed to create expected response object") expected, err := accounts.NewConfirmationResponse(testConfirmation) expected.SetEmbedded( "access-token", jsonhal.Embedded(expectedEmbeddedTokenResponse), ) assert.NoError(suite.T(), err, "Failed to create expected response object") testutil.TestResponseObject(suite.T(), w, expected, 200) }
// Handles requests to confirm user's email // GET /v1/confirmations/{reference:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}} func (s *Service) confirmEmailHandler(w http.ResponseWriter, r *http.Request) { // Get the authenticated account from the request context authenticatedAccount, err := GetAuthenticatedAccount(r) if err != nil { response.UnauthorizedError(w, err.Error()) return } // Get the reference from request URI vars := mux.Vars(r) reference := vars["reference"] // Fetch the confirmation we want to work with (by reference from email link) confirmation, err := s.FindConfirmationByReference(reference) if err != nil { response.Error(w, err.Error(), http.StatusNotFound) return } // Confirm the user if err = s.ConfirmUser(confirmation); err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Create confirmation response confirmationResponse, err := NewConfirmationResponse(confirmation) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Was autologin flag passed in the query string autoLogin, _ := strconv.ParseBool(r.URL.Query().Get("autologin")) // If autologin == true, login the user and embed access token in the response object if autoLogin { // Login the user accessToken, refreshToken, err := s.GetOauthService().Login( authenticatedAccount.OauthClient, confirmation.User.OauthUser, "read_write", ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Create access token response accessTokenResponse, err := oauth.NewAccessTokenResponse( accessToken, refreshToken, s.cnf.Oauth.AccessTokenLifetime, tokentypes.Bearer, ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Set embedded access token confirmationResponse.SetEmbedded( "access-token", jsonhal.Embedded(accessTokenResponse), ) } // Write the response response.WriteJSON(w, confirmationResponse, 200) }