diff options
author | Saturnino Abril <saturnino.abril@gmail.com> | 2017-02-27 23:25:28 +0900 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2017-02-27 09:25:28 -0500 |
commit | 71d010b7af3601b0690407af328ec2865e3a0efd (patch) | |
tree | cd8f6a3dce8846641e304d9396e8c098004049f5 | |
parent | 19b753467d37209f2227567637e60138d05dd405 (diff) | |
download | chat-71d010b7af3601b0690407af328ec2865e3a0efd.tar.gz chat-71d010b7af3601b0690407af328ec2865e3a0efd.tar.bz2 chat-71d010b7af3601b0690407af328ec2865e3a0efd.zip |
APIv4: GET /users/{user_id}/image (#5526)
-rw-r--r-- | api4/user.go | 43 | ||||
-rw-r--r-- | api4/user_test.go | 33 | ||||
-rw-r--r-- | app/user_test.go | 22 | ||||
-rw-r--r-- | model/client4.go | 11 |
4 files changed, 108 insertions, 1 deletions
diff --git a/api4/user.go b/api4/user.go index 94891d11c..9fa6568d3 100644 --- a/api4/user.go +++ b/api4/user.go @@ -4,7 +4,9 @@ package api4 import ( + "fmt" "net/http" + "strconv" l4g "github.com/alecthomas/log4go" "github.com/mattermost/platform/app" @@ -20,6 +22,7 @@ func InitUser() { BaseRoutes.Users.Handle("/ids", ApiSessionRequired(getUsersByIds)).Methods("POST") BaseRoutes.User.Handle("", ApiSessionRequired(getUser)).Methods("GET") + BaseRoutes.User.Handle("/image", ApiSessionRequired(getProfileImage)).Methods("GET") BaseRoutes.User.Handle("", ApiSessionRequired(updateUser)).Methods("PUT") BaseRoutes.User.Handle("/patch", ApiSessionRequired(patchUser)).Methods("PUT") BaseRoutes.User.Handle("", ApiSessionRequired(deleteUser)).Methods("DELETE") @@ -38,7 +41,6 @@ func InitUser() { BaseRoutes.User.Handle("/sessions", ApiSessionRequired(getSessions)).Methods("GET") BaseRoutes.User.Handle("/sessions/revoke", ApiSessionRequired(revokeSession)).Methods("POST") BaseRoutes.User.Handle("/audits", ApiSessionRequired(getAudits)).Methods("GET") - } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -156,6 +158,45 @@ func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) { } } +func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireUserId() + if c.Err != nil { + return + } + + if users, err := app.GetUsersByIds([]string{c.Params.UserId}, c.IsSystemAdmin()); err != nil { + c.Err = err + return + } else { + if len(users) == 0 { + c.Err = err + } + + user := users[0] + etag := strconv.FormatInt(user.LastPictureUpdate, 10) + if HandleEtag(etag, "Get Profile Image", w, r) { + return + } + + var img []byte + img, readFailed, err := app.GetProfileImage(user) + if err != nil { + c.Err = err + return + } + + if readFailed { + w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%v, public", 5*60)) // 5 mins + } else { + w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%v, public", 24*60*60)) // 24 hrs + } + + w.Header().Set("Content-Type", "image/png") + w.Header().Set(model.HEADER_ETAG_SERVER, etag) + w.Write(img) + } +} + func getUsers(c *Context, w http.ResponseWriter, r *http.Request) { inTeamId := r.URL.Query().Get("in_team") inChannelId := r.URL.Query().Get("in_channel") diff --git a/api4/user_test.go b/api4/user_test.go index ee6cf079b..5cdab21f5 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -261,6 +261,39 @@ func TestGetUserByEmail(t *testing.T) { } } +func TestGetProfileImage(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + user := th.BasicUser + + data, resp := Client.GetProfileImage(user.Id, "") + CheckNoError(t, resp) + if data == nil || len(data) == 0 { + t.Fatal("Should not be empty") + } + + _, resp = Client.GetProfileImage(user.Id, resp.Etag) + if resp.StatusCode != http.StatusNotModified { + t.Fatal("Should have hit etag") + } + + _, resp = Client.GetProfileImage("junk", "") + CheckBadRequestStatus(t, resp) + + Client.Logout() + _, resp = Client.GetProfileImage(user.Id, "") + CheckUnauthorizedStatus(t, resp) + + _, resp = th.SystemAdminClient.GetProfileImage(user.Id, "") + CheckNoError(t, resp) + + info := &model.FileInfo{Path: "/users/" + user.Id + "/profile.png"} + if err := cleanupTestFile(info); err != nil { + t.Fatal(err) + } +} + func TestGetUsersByIds(t *testing.T) { th := Setup().InitBasic() Client := th.Client diff --git a/app/user_test.go b/app/user_test.go index 177f5a638..8979af7d7 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -5,6 +5,8 @@ package app import ( "bytes" + "image" + "image/color" "encoding/json" "math/rand" "strings" @@ -89,7 +91,27 @@ func TestCreateOAuthUser(t *testing.T) { if err == nil { t.Fatal("should have failed - user creation disabled") } +} + +func TestCreateProfileImage(t *testing.T) { + utils.LoadConfig("config.json") + + b, err := CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba") + if err != nil { + t.Fatal(err) + } + rdr := bytes.NewReader(b) + img, _, err2 := image.Decode(rdr) + if err2 != nil { + t.Fatal(err) + } + + colorful := color.RGBA{116, 49, 196, 255} + + if img.At(1, 1) != colorful { + t.Fatal("Failed to create correct color") + } } func TestUpdateOAuthUserAttrs(t *testing.T) { diff --git a/model/client4.go b/model/client4.go index f51e86a56..2a762aa9d 100644 --- a/model/client4.go +++ b/model/client4.go @@ -318,6 +318,17 @@ func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) { } } +// GetProfileImage gets user's profile image. Must be logged in or be a system administrator. +func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response) { + if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/image", etag); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: err} + } else if data, err := ioutil.ReadAll(r.Body); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)} + } else { + return data, 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) |