From 11b7aa859c4b5108207b1395a91ddbc988ccf00b Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 24 Mar 2017 16:42:05 -0400 Subject: Implement POST /users/email/verify/send endpoint for APIv4 (#5825) --- api4/user.go | 40 +++++++++++++++++++++++++++++++++------- api4/user_test.go | 31 +++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 13 deletions(-) (limited to 'api4') diff --git a/api4/user.go b/api4/user.go index b22bc75f6..c04fa0d77 100644 --- a/api4/user.go +++ b/api4/user.go @@ -35,7 +35,8 @@ func InitUser() { BaseRoutes.User.Handle("/password", ApiSessionRequired(updatePassword)).Methods("PUT") BaseRoutes.Users.Handle("/password/reset", ApiHandler(resetPassword)).Methods("POST") BaseRoutes.Users.Handle("/password/reset/send", ApiHandler(sendPasswordReset)).Methods("POST") - BaseRoutes.User.Handle("/email/verify", ApiHandler(verify)).Methods("POST") + BaseRoutes.Users.Handle("/email/verify", ApiHandler(verifyUserEmail)).Methods("POST") + BaseRoutes.Users.Handle("/email/verify/send", ApiHandler(sendVerificationEmail)).Methods("POST") BaseRoutes.Users.Handle("/login", ApiHandler(login)).Methods("POST") BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST") @@ -797,18 +798,18 @@ func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) { } } -func verify(c *Context, w http.ResponseWriter, r *http.Request) { +func verifyUserEmail(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) - userId := props["uid"] + userId := props["user_id"] if len(userId) != 26 { - c.SetInvalidParam("uid") + c.SetInvalidParam("user_id") return } - hashedId := props["hid"] + hashedId := props["hash_id"] if len(hashedId) == 0 { - c.SetInvalidParam("hid") + c.SetInvalidParam("hash_id") return } @@ -823,7 +824,32 @@ func verify(c *Context, w http.ResponseWriter, r *http.Request) { } } - c.Err = model.NewLocAppError("verifyEmail", "api.user.verify_email.bad_link.app_error", nil, "") + c.Err = model.NewLocAppError("verifyUserEmail", "api.user.verify_email.bad_link.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } + +func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.MapFromJson(r.Body) + + email := props["email"] + if len(email) == 0 { + c.SetInvalidParam("email") + return + } + + user, err := app.GetUserForLogin(email, false) + if err != nil { + // Don't want to leak whether the email is valid or not + ReturnStatusOK(w) + return + } + + if _, err := app.GetStatus(user.Id); err != nil { + go app.SendVerifyEmail(user.Id, user.Email, user.Locale, c.GetSiteURL()) + } else { + go app.SendEmailChangeVerifyEmail(user.Id, user.Email, user.Locale, c.GetSiteURL()) + } + + ReturnStatusOK(w) +} diff --git a/api4/user_test.go b/api4/user_test.go index 6a42d19d2..16ae8bdad 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -1303,7 +1303,7 @@ func TestGetUserAudits(t *testing.T) { CheckNoError(t, resp) } -func TestVerify(t *testing.T) { +func TestVerifyUserEmail(t *testing.T) { th := Setup().InitBasic() defer TearDown() Client := th.Client @@ -1320,15 +1320,34 @@ func TestVerify(t *testing.T) { _, resp = Client.VerifyUserEmail(ruser.Id, hashId) CheckBadRequestStatus(t, resp) - // Comment per request from Joram, he will investigate why it fail with a wrong status - // hashId = ruser.Id+GenerateTestId() - // _, resp = Client.VerifyUserEmail("", hashId) - // CheckBadRequestStatus(t, resp) - _, resp = Client.VerifyUserEmail(ruser.Id, "") CheckBadRequestStatus(t, resp) } +func TestSendVerificationEmail(t *testing.T) { + th := Setup().InitBasic() + defer TearDown() + Client := th.Client + + pass, resp := Client.SendVerificationEmail(th.BasicUser.Email) + CheckNoError(t, resp) + + if !pass { + t.Fatal("should have passed") + } + + _, resp = Client.SendVerificationEmail("") + CheckBadRequestStatus(t, resp) + + // Even non-existent emails should return 200 OK + _, resp = Client.SendVerificationEmail(GenerateTestEmail()) + CheckNoError(t, resp) + + Client.Logout() + _, resp = Client.SendVerificationEmail(th.BasicUser.Email) + CheckNoError(t, resp) +} + func TestSetProfileImage(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer TearDown() -- cgit v1.2.3-1-g7c22