summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-03-24 16:42:05 -0400
committerCorey Hulen <corey@hulen.com>2017-03-24 13:42:05 -0700
commit11b7aa859c4b5108207b1395a91ddbc988ccf00b (patch)
tree30d93a5ad563dbf6bea17bdcfb9a9a24abbeb4bf
parenta2f78d01bd4d105da374c46bd40c2a585bddd536 (diff)
downloadchat-11b7aa859c4b5108207b1395a91ddbc988ccf00b.tar.gz
chat-11b7aa859c4b5108207b1395a91ddbc988ccf00b.tar.bz2
chat-11b7aa859c4b5108207b1395a91ddbc988ccf00b.zip
Implement POST /users/email/verify/send endpoint for APIv4 (#5825)
-rw-r--r--api4/user.go40
-rw-r--r--api4/user_test.go31
-rw-r--r--model/client4.go19
3 files changed, 74 insertions, 16 deletions
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()
diff --git a/model/client4.go b/model/client4.go
index 3aef5019c..b269f2f34 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -645,10 +645,23 @@ func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag strin
}
}
-// Verify user email user id and hash strings.
+// VerifyUserEmail will verify a user's email using user id and hash strings.
func (c *Client4) VerifyUserEmail(userId, hashId string) (bool, *Response) {
- requestBody := map[string]string{"uid": userId, "hid": hashId}
- if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/email/verify", MapToJson(requestBody)); err != nil {
+ requestBody := map[string]string{"user_id": userId, "hash_id": hashId}
+ if r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify", MapToJson(requestBody)); err != nil {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
+// SendVerificationEmail will send an email to the user with the provided email address, if
+// that user exists. The email will contain a link that can be used to verify the user's
+// email address.
+func (c *Client4) SendVerificationEmail(email string) (bool, *Response) {
+ requestBody := map[string]string{"email": email}
+ if r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify/send", MapToJson(requestBody)); err != nil {
return false, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)