diff --git a/app/rest/avatar/avatar.go b/app/rest/avatar/avatar.go index 37e8f85e..ff185972 100644 --- a/app/rest/avatar/avatar.go +++ b/app/rest/avatar/avatar.go @@ -3,6 +3,7 @@ package avatar import ( + "crypto/sha1" "fmt" "hash/crc64" "io" @@ -48,13 +49,13 @@ func (p *Proxy) Put(u store.User) (avatarURL string, err error) { log.Printf("[WARN] can't close response body, %s", e) } }() - - location := p.location(u.ID) + encID := p.encodeID(u.ID) + location := p.location(encID) if err = os.Mkdir(location, 0700); err != nil && !strings.Contains(err.Error(), "file exists") { return "", errors.Wrapf(err, "failed to make avatar location %s", location) } - avFile := path.Join(location, u.ID+".image") + avFile := path.Join(location, encID+".image") fh, err := os.Create(avFile) if err != nil { return "", errors.Wrapf(err, "can't create file %s", avFile) @@ -70,7 +71,7 @@ func (p *Proxy) Put(u store.User) (avatarURL string, err error) { } log.Printf("[DEBUG] saved avatar from %s to %s, user %q", u.Picture, avFile, u.Name) - return p.RoutePath + "/" + u.ID + ".image", nil + return p.RoutePath + "/" + encID + ".image", nil } // Routes returns auth routes for given provider @@ -110,6 +111,15 @@ func (p *Proxy) Routes() chi.Router { return router } +func (p *Proxy) encodeID(id string) string { + h := sha1.New() + _, err := h.Write([]byte(id)) + if err != nil { + return id + } + return fmt.Sprintf("%x", h.Sum(nil)) +} + // get location for user id by adding partion to final path // the end result is a full path like this - /tmp/avatars.test/992 func (p *Proxy) location(id string) string { diff --git a/app/rest/avatar/avatar_test.go b/app/rest/avatar/avatar_test.go index 183c24ec..77ba8b93 100644 --- a/app/rest/avatar/avatar_test.go +++ b/app/rest/avatar/avatar_test.go @@ -3,6 +3,7 @@ package avatar import ( "bytes" "io" + "io/ioutil" "net/http" "net/http/httptest" "os" @@ -21,22 +22,37 @@ func TestPut(t *testing.T) { u := store.User{ID: "user1", Name: "user1 name", Picture: "https://friends.radio-t.com/resources/images/rt_logo_64.png"} res, err := p.Put(u) assert.NoError(t, err) - assert.Equal(t, "/avatar/user1.image", res) - fi, err := os.Stat("/tmp/avatars.test/20/user1.image") + assert.Equal(t, "/avatar/b3daa77b4c04a9551b8781d03191fe098f325e67.image", res) + fi, err := os.Stat("/tmp/avatars.test/30/b3daa77b4c04a9551b8781d03191fe098f325e67.image") assert.NoError(t, err) assert.Equal(t, int64(8432), fi.Size()) u.ID = "user2" res, err = p.Put(u) assert.NoError(t, err) - assert.Equal(t, "/avatar/user2.image", res) - fi, err = os.Stat("/tmp/avatars.test/92/user2.image") + assert.Equal(t, "/avatar/a1881c06eec96db9901c7bbfe41c42a3f08e9cb4.image", res) + fi, err = os.Stat("/tmp/avatars.test/84/a1881c06eec96db9901c7bbfe41c42a3f08e9cb4.image") assert.NoError(t, err) assert.Equal(t, int64(8432), fi.Size()) } +func TestPutDefault(t *testing.T) { + p := Proxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar", DefaultAvatar: "default.image"} + os.MkdirAll("/tmp/avatars.test", 0700) + ioutil.WriteFile("/tmp/avatars.test/default.image", []byte("1234567890"), 0600) + defer os.RemoveAll("/tmp/avatars.test") + + u := store.User{ID: "user1", Name: "user1 name"} + res, err := p.Put(u) + assert.NoError(t, err) + assert.Equal(t, "/avatar/default.image", res) + fi, err := os.Stat("/tmp/avatars.test/default.image") + assert.NoError(t, err) + assert.Equal(t, int64(10), fi.Size()) + +} func TestRoutes(t *testing.T) { - p := Proxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar"} + p := Proxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar", DefaultAvatar: "default.image"} os.MkdirAll("/tmp/avatars.test", 0700) defer os.RemoveAll("/tmp/avatars.test") @@ -44,7 +60,7 @@ func TestRoutes(t *testing.T) { _, err := p.Put(u) assert.NoError(t, err) - req, err := http.NewRequest("GET", "/user1.image", nil) + req, err := http.NewRequest("GET", "/b3daa77b4c04a9551b8781d03191fe098f325e67.image", nil) if err != nil { t.Fatal(err) } @@ -60,3 +76,29 @@ func TestRoutes(t *testing.T) { assert.NoError(t, err) assert.Equal(t, int64(8432), sz) } +func TestRoutesDefault(t *testing.T) { + p := Proxy{StorePath: "/tmp/avatars.test", RoutePath: "/avatar", DefaultAvatar: "default.image"} + os.MkdirAll("/tmp/avatars.test", 0700) + ioutil.WriteFile("/tmp/avatars.test/default.image", []byte("1234567890"), 0600) + defer os.RemoveAll("/tmp/avatars.test") + + u := store.User{ID: "user1", Name: "user1 name"} + _, err := p.Put(u) + assert.NoError(t, err) + + req, err := http.NewRequest("GET", "/no-such-thing.image", nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.Handler(p.Routes()) + handler.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, http.Header{"Content-Type": []string{"image/*"}}, rr.HeaderMap) + bb := bytes.Buffer{} + sz, err := io.Copy(&bb, rr.Body) + assert.NoError(t, err) + assert.Equal(t, int64(10), sz) +}