summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api4/apitestlib.go4
-rw-r--r--api4/user.go32
-rw-r--r--api4/user_test.go26
-rw-r--r--model/client4.go11
4 files changed, 73 insertions, 0 deletions
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index d77438e04..2647f20f6 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -323,6 +323,10 @@ func GenerateTestChannelName() string {
return "fakechannel" + model.NewRandomString(10)
}
+func GenerateTestId() string {
+ return model.NewId()
+}
+
func VerifyUserEmail(userId string) {
store.Must(app.Srv.Store.User().VerifyEmail(userId))
}
diff --git a/api4/user.go b/api4/user.go
index 4c40ef4b4..94891d11c 100644
--- a/api4/user.go
+++ b/api4/user.go
@@ -27,6 +27,7 @@ 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("/login", ApiHandler(login)).Methods("POST")
BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST")
@@ -550,3 +551,34 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
}
+
+func verify(c *Context, w http.ResponseWriter, r *http.Request) {
+ props := model.MapFromJson(r.Body)
+
+ userId := props["uid"]
+ if len(userId) != 26 {
+ c.SetInvalidParam("uid")
+ return
+ }
+
+ hashedId := props["hid"]
+ if len(hashedId) == 0 {
+ c.SetInvalidParam("hid")
+ return
+ }
+
+ hashed := model.HashPassword(hashedId)
+ if model.ComparePassword(hashed, userId+utils.Cfg.EmailSettings.InviteSalt) {
+ if c.Err = app.VerifyUserEmail(userId); c.Err != nil {
+ return
+ } else {
+ c.LogAudit("Email Verified")
+ ReturnStatusOK(w)
+ return
+ }
+ }
+
+ c.Err = model.NewLocAppError("verifyEmail", "api.user.verify_email.bad_link.app_error", nil, "")
+ c.Err.StatusCode = http.StatusBadRequest
+ return
+}
diff --git a/api4/user_test.go b/api4/user_test.go
index 07b9745c6..ee6cf079b 100644
--- a/api4/user_test.go
+++ b/api4/user_test.go
@@ -924,3 +924,29 @@ func TestGetAudits(t *testing.T) {
_, resp = th.SystemAdminClient.GetAudits(user.Id, 0, 100, "")
CheckNoError(t, resp)
}
+
+func TestVerify(t *testing.T) {
+ th := Setup().InitBasic()
+ defer TearDown()
+ Client := th.Client
+
+ user := model.User{Email: GenerateTestEmail(), Nickname: "Darth Vader", Password: "hello1", Username: GenerateTestUsername(), Roles: model.ROLE_SYSTEM_ADMIN.Id + " " + model.ROLE_SYSTEM_USER.Id}
+
+ ruser, resp := Client.CreateUser(&user)
+
+ hashId := ruser.Id+utils.Cfg.EmailSettings.InviteSalt
+ _, resp = Client.VerifyUserEmail(ruser.Id, hashId)
+ CheckNoError(t, resp)
+
+ hashId = ruser.Id+GenerateTestId()
+ _, 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)
+}
diff --git a/model/client4.go b/model/client4.go
index 6b9a389c9..f51e86a56 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -479,6 +479,17 @@ func (c *Client4) GetAudits(userId string, page int, perPage int, etag string) (
}
}
+// Verify user email 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 {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// Team Section
// CreateTeam creates a team in the system based on the provided team struct.