Skip to content

Fix broken avatars since #15301 #15731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions integrations/user_avatar_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package integrations

import (
"bytes"
"image/png"
"io"
"mime/multipart"
"net/http"
"net/url"
"strings"
"testing"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/avatar"
"github.com/stretchr/testify/assert"
)

func TestUserAvatar(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) // owner of the repo3, is an org

seed := user2.Email
if len(seed) == 0 {
seed = user2.Name
}

img, err := avatar.RandomImage([]byte(seed))
if err != nil {
assert.NoError(t, err)
return
}

session := loginUser(t, "user2")
csrf := GetCSRF(t, session, "/user/settings")

imgData := &bytes.Buffer{}

body := &bytes.Buffer{}

//Setup multi-part
writer := multipart.NewWriter(body)
writer.WriteField("source", "local")
part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png")
if err != nil {
assert.NoError(t, err)
return
}

if err := png.Encode(imgData, img); err != nil {
assert.NoError(t, err)
return
}

if _, err := io.Copy(part, imgData); err != nil {
assert.NoError(t, err)
return
}

if err := writer.Close(); err != nil {
assert.NoError(t, err)
return
}

req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body)
req.Header.Add("X-Csrf-Token", csrf)
req.Header.Add("Content-Type", writer.FormDataContentType())

session.MakeRequest(t, req, http.StatusFound)

user2 = models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) // owner of the repo3, is an org

req = NewRequest(t, "GET", user2.AvatarLink())
resp := session.MakeRequest(t, req, http.StatusFound)
location := resp.Header().Get("Location")
if !strings.HasPrefix(location, "/avatars") {
assert.Fail(t, "Avatar location is not local: %s", location)
}
req = NewRequest(t, "GET", location)
session.MakeRequest(t, req, http.StatusOK)

// Can't test if the response matches because the image is regened on upload but checking that this at least doesn't give a 404 should be enough.
})
}
4 changes: 2 additions & 2 deletions routers/routes/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ func WebRoutes() *web.Route {
))

// We use r.Route here over r.Use because this prevents requests that are not for avatars having to go through this additional handler
routes.Route("/avatars", "GET, HEAD", storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars))
routes.Route("/repo-avatars", "GET, HEAD", storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars))
routes.Route("/avatars/*", "GET, HEAD", storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars))
routes.Route("/repo-avatars/*", "GET, HEAD", storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars))

// for health check - doeesn't need to be passed through gzip handler
routes.Head("/", func(w http.ResponseWriter, req *http.Request) {
Expand Down