diff --git a/models/action_test.go b/models/action_test.go index 16fdc7adcc90..c90538ebe602 100644 --- a/models/action_test.go +++ b/models/action_test.go @@ -173,7 +173,7 @@ func TestPushCommits_AvatarLink(t *testing.T) { pushCommits.Len = len(pushCommits.Commits) assert.Equal(t, - "https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon", + "/suburl/user/avatar/user2/-1", pushCommits.AvatarLink("user2@example.com")) assert.Equal(t, diff --git a/models/user.go b/models/user.go index e31f8b853472..030e23c383af 100644 --- a/models/user.go +++ b/models/user.go @@ -17,6 +17,7 @@ import ( "image/png" "os" "path/filepath" + "strconv" "strings" "time" "unicode/utf8" @@ -374,9 +375,20 @@ func (u *User) generateRandomAvatar(e Engine) error { return nil } -// SizedRelAvatarLink returns a relative link to the user's avatar. When -// applicable, the link is for an avatar of the indicated size (in pixels). +// SizedRelAvatarLink returns a link to the user's avatar via +// the local explore page. Function returns immediately. +// When applicable, the link is for an avatar of the indicated size (in pixels). func (u *User) SizedRelAvatarLink(size int) string { + return strings.TrimRight(setting.AppSubURL, "/") + "/user/avatar/" + u.Name + "/" + strconv.Itoa(size) +} + +// RealSizedAvatarLink returns a link to the user's avatar. When +// applicable, the link is for an avatar of the indicated size (in pixels). +// +// This function make take time to return when federated avatars +// are in use, due to a DNS lookup need +// +func (u *User) RealSizedAvatarLink(size int) string { if u.ID == -1 { return base.DefaultAvatarLink() } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index e18ac0923ecc..5262d4ad5cf7 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -404,6 +404,7 @@ func RegisterRoutes(m *macaron.Macaron) { // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/activate", user.Activate, reqSignIn) m.Any("/activate_email", user.ActivateEmail) + m.Get("/avatar/:username/:size", user.Avatar) m.Get("/email2user", user.Email2User) m.Get("/recover_account", user.ResetPasswd) m.Post("/recover_account", user.ResetPasswdPost) diff --git a/routers/user/avatar.go b/routers/user/avatar.go new file mode 100644 index 000000000000..20597c72ffa3 --- /dev/null +++ b/routers/user/avatar.go @@ -0,0 +1,37 @@ +// Copyright 2019 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 user + +import ( + "strconv" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" +) + +// Avatar redirect browser to user avatar of requested size +func Avatar(ctx *context.Context) { + userName := ctx.Params(":username") + size, err := strconv.Atoi(ctx.Params(":size")) + if err != nil { + ctx.ServerError("Invalid avatar size", err) + return + } + + log.Debug("Asked avatar for user %v and size %v", userName, size) + + user, err := models.GetUserByName(userName) + if err != nil { + if models.IsErrUserNotExist(err) { + ctx.ServerError("Requested avatar for invalid user", err) + } else { + ctx.ServerError("Retrieving user by name", err) + } + return + } + + ctx.Redirect(user.RealSizedAvatarLink(size)) +}