diff options
-rw-r--r-- | api4/context.go | 13 | ||||
-rw-r--r-- | api4/params.go | 5 | ||||
-rw-r--r-- | api4/user.go | 34 | ||||
-rw-r--r-- | api4/user_test.go | 65 | ||||
-rw-r--r-- | app/user.go | 7 | ||||
-rw-r--r-- | model/client4.go | 14 |
6 files changed, 134 insertions, 4 deletions
diff --git a/api4/context.go b/api4/context.go index 1a3011795..7ad6f30b4 100644 --- a/api4/context.go +++ b/api4/context.go @@ -358,3 +358,16 @@ func (c *Context) RequireChannelId() *Context { } return c } + +func (c *Context) RequireEmail() *Context { + if c.Err != nil { + return c + } + + pos := strings.Index(c.Params.Email, "@") + if pos < 0 { + c.SetInvalidUrlParam("email") + } + + return c +} diff --git a/api4/params.go b/api4/params.go index 1c0c153ea..a043919fa 100644 --- a/api4/params.go +++ b/api4/params.go @@ -25,6 +25,7 @@ type ApiParams struct { CommandId string HookId string EmojiId string + Email string Page int PerPage int } @@ -66,6 +67,10 @@ func ApiParamsFromRequest(r *http.Request) *ApiParams { params.EmojiId = val } + if val, ok := props["email"]; ok { + params.Email = val + } + if val, err := strconv.Atoi(r.URL.Query().Get("page")); err != nil { params.Page = PAGE_DEFAULT } else { diff --git a/api4/user.go b/api4/user.go index 14067bdf5..cf9bb4ead 100644 --- a/api4/user.go +++ b/api4/user.go @@ -27,6 +27,8 @@ func InitUser() { BaseRoutes.Users.Handle("/login", ApiHandler(login)).Methods("POST") BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST") + BaseRoutes.UserByEmail.Handle("", ApiSessionRequired(getUserByEmail)).Methods("GET") + } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -88,6 +90,34 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) { } } +func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireEmail() + if c.Err != nil { + return + } + + // No permission check required + + var user *model.User + var err *model.AppError + + if user, err = app.GetUserByEmail(c.Params.Email); err != nil { + c.Err = err + return + } + + etag := user.Etag(utils.Cfg.PrivacySettings.ShowFullName, utils.Cfg.PrivacySettings.ShowEmailAddress) + + if HandleEtag(etag, "Get User", w, r) { + return + } else { + app.SanitizeProfile(user, c.IsSystemAdmin()) + w.Header().Set(model.HEADER_ETAG_SERVER, etag) + w.Write([]byte(user.ToJson())) + return + } +} + func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { inTeamId := r.URL.Query().Get("in_team") inChannelId := r.URL.Query().Get("in_channel") @@ -292,9 +322,7 @@ func logout(c *Context, w http.ResponseWriter, r *http.Request) { data["user_id"] = c.Session.UserId Logout(c, w, r) - if c.Err == nil { - w.Write([]byte(model.MapToJson(data))) - } + } func Logout(c *Context, w http.ResponseWriter, r *http.Request) { diff --git a/api4/user_test.go b/api4/user_test.go index 40f6b4117..dc8a82310 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -131,6 +131,71 @@ func TestGetUser(t *testing.T) { } } +func TestGetUserByEmail(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + + user := th.CreateUser() + + ruser, resp := Client.GetUserByEmail(user.Email, "") + CheckNoError(t, resp) + CheckUserSanitization(t, ruser) + + if ruser.Email != user.Email { + t.Fatal("emails did not match") + } + + ruser, resp = Client.GetUserByEmail(user.Email, resp.Etag) + CheckEtag(t, ruser, resp) + + + _, resp = Client.GetUserByEmail(GenerateTestUsername(), "") + CheckBadRequestStatus(t, resp) + + _, resp = Client.GetUserByEmail(GenerateTestEmail(), "") + CheckNotFoundStatus(t, resp) + + // Check against privacy config settings + emailPrivacy := utils.Cfg.PrivacySettings.ShowEmailAddress + namePrivacy := utils.Cfg.PrivacySettings.ShowFullName + defer func() { + utils.Cfg.PrivacySettings.ShowEmailAddress = emailPrivacy + utils.Cfg.PrivacySettings.ShowFullName = namePrivacy + }() + utils.Cfg.PrivacySettings.ShowEmailAddress = false + utils.Cfg.PrivacySettings.ShowFullName = false + + ruser, resp = Client.GetUserByEmail(user.Email, "") + CheckNoError(t, resp) + + if ruser.Email != "" { + t.Fatal("email should be blank") + } + if ruser.FirstName != "" { + t.Fatal("first name should be blank") + } + if ruser.LastName != "" { + t.Fatal("last name should be blank") + } + + Client.Logout() + _, resp = Client.GetUserByEmail(user.Email, "") + CheckUnauthorizedStatus(t, resp) + + // System admins should ignore privacy settings + ruser, resp = th.SystemAdminClient.GetUserByEmail(user.Email, resp.Etag) + if ruser.Email == "" { + t.Fatal("email should not be blank") + } + if ruser.FirstName == "" { + t.Fatal("first name should not be blank") + } + if ruser.LastName == "" { + t.Fatal("last name should not be blank") + } +} + func TestGetUsersByIds(t *testing.T) { th := Setup().InitBasic() Client := th.Client diff --git a/app/user.go b/app/user.go index bc809cfaa..c302db511 100644 --- a/app/user.go +++ b/app/user.go @@ -331,7 +331,12 @@ func GetUserByUsername(username string) (*model.User, *model.AppError) { } func GetUserByEmail(email string) (*model.User, *model.AppError) { - if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil { + + if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil && result.Err.Id == "store.sql_user.missing_account.const"{ + result.Err.StatusCode = http.StatusNotFound + return nil, result.Err + } else if result.Err != nil { + result.Err.StatusCode = http.StatusBadRequest return nil, result.Err } else { return result.Data.(*model.User), nil diff --git a/model/client4.go b/model/client4.go index 1bdb7e55e..42b96a730 100644 --- a/model/client4.go +++ b/model/client4.go @@ -56,6 +56,10 @@ func (c *Client4) GetUserRoute(userId string) string { return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId) } +func (c *Client4) GetUserByEmailRoute(email string) string { + return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email) +} + func (c *Client4) GetTeamsRoute() string { return fmt.Sprintf("/teams") } @@ -210,6 +214,16 @@ func (c *Client4) GetUser(userId, etag string) (*User, *Response) { } } +// GetUserByEmail returns a user based on the provided user email string. +func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) { + if r, err := c.DoApiGet(c.GetUserByEmailRoute(email), etag); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return UserFromJson(r.Body), BuildResponse(r) + } +} + // GetUsers returns a page of users on the system. Page counting starts at 0. func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) { query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) |