From f7f1f0d268630132310cbd858a9a601ff0abf435 Mon Sep 17 00:00:00 2001 From: Ibrahim Serdar Acikgoz Date: Fri, 26 Jun 2020 16:08:01 +0300 Subject: [PATCH] [MM-23721] api4/user: add verify user by Id endpoint (#14244) * api4/user: add verify user by id method * Update api4/user.go Co-Authored-By: Miguel de la Cruz * Update model/client4.go Co-Authored-By: Miguel de la Cruz * api4/user: reflect review comments * Update api4/user_test.go Co-authored-by: Miguel de la Cruz Co-authored-by: Miguel de la Cruz Co-authored-by: mattermod --- api4/user.go | 33 +++++++++++++++++++++++++++++++++ api4/user_test.go | 30 ++++++++++++++++++++++++++++++ model/client4.go | 10 ++++++++++ 3 files changed, 73 insertions(+) diff --git a/api4/user.go b/api4/user.go index c15a475bb2..c9b33375ef 100644 --- a/api4/user.go +++ b/api4/user.go @@ -49,6 +49,7 @@ func (api *API) InitUser() { api.BaseRoutes.Users.Handle("/password/reset/send", api.ApiHandler(sendPasswordReset)).Methods("POST") api.BaseRoutes.Users.Handle("/email/verify", api.ApiHandler(verifyUserEmail)).Methods("POST") api.BaseRoutes.Users.Handle("/email/verify/send", api.ApiHandler(sendVerificationEmail)).Methods("POST") + api.BaseRoutes.User.Handle("/email/verify/member", api.ApiSessionRequired(verifyUserEmailWithoutToken)).Methods("POST") api.BaseRoutes.User.Handle("/terms_of_service", api.ApiSessionRequired(saveUserTermsOfService)).Methods("POST") api.BaseRoutes.User.Handle("/terms_of_service", api.ApiSessionRequired(getUserTermsOfService)).Methods("GET") @@ -2332,3 +2333,35 @@ func publishUserTyping(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) } + +func verifyUserEmailWithoutToken(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + user, err := c.App.GetUser(c.Params.UserId) + if err != nil { + c.Err = err + return + } + + auditRec := c.MakeAuditRecord("verifyUserEmailWithoutToken", audit.Fail) + defer c.LogAuditRec(auditRec) + auditRec.AddMeta("user_id", user.Id) + + if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) { + c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) + return + } + + if err := c.App.VerifyUserEmail(user.Id, user.Email); err != nil { + c.Err = err + return + } + + auditRec.Success() + c.LogAudit("user verified") + + w.Write([]byte(user.ToJson())) +} diff --git a/api4/user_test.go b/api4/user_test.go index 5862720f60..3864a8266c 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -4769,6 +4769,36 @@ func TestPromoteGuestToUser(t *testing.T) { }) } +func TestVerifyUserEmailWithoutToken(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + t.Run("Should verify a new user", func(t *testing.T) { + email := th.GenerateTestEmail() + user := model.User{Email: email, Nickname: "Darth Vader", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID} + ruser, _ := th.Client.CreateUser(&user) + + vuser, resp := th.SystemAdminClient.VerifyUserEmailWithoutToken(ruser.Id) + require.Nil(t, resp.Error) + require.Equal(t, ruser.Id, vuser.Id) + }) + + t.Run("Should not be able to find user", func(t *testing.T) { + vuser, resp := th.SystemAdminClient.VerifyUserEmailWithoutToken("randomId") + require.NotNil(t, resp.Error) + CheckErrorMessage(t, resp, "api.context.invalid_url_param.app_error") + require.Nil(t, vuser) + }) + + t.Run("Should not be able to verify user due to permissions", func(t *testing.T) { + user := th.CreateUser() + vuser, resp := th.Client.VerifyUserEmailWithoutToken(user.Id) + require.NotNil(t, resp.Error) + CheckErrorMessage(t, resp, "api.context.permissions.app_error") + require.Nil(t, vuser) + }) +} + func TestGetKnownUsers(t *testing.T) { th := Setup(t) defer th.TearDown() diff --git a/model/client4.go b/model/client4.go index b937323d8d..17dea3dc53 100644 --- a/model/client4.go +++ b/model/client4.go @@ -1325,6 +1325,16 @@ func (c *Client4) VerifyUserEmail(token string) (bool, *Response) { return CheckStatusOK(r), BuildResponse(r) } +// VerifyUserEmailWithoutToken will verify a user's email by its Id. (Requires manage system role) +func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response) { + r, err := c.DoApiPost(c.GetUserRoute(userId)+"/email/verify/member", "") + if err != nil { + return nil, BuildErrorResponse(r, err) + } + defer closeBody(r) + return UserFromJson(r.Body), 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.