aboutsummaryrefslogtreecommitdiffstats
path: root/models/avatars/avatar.go
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-10-05 09:08:19 +0800
committerGitHub <noreply@github.com>2023-10-05 09:08:19 +0800
commit9f8d59858af581a2c278a4896a301339991ece5b (patch)
tree577a395a442ccd9579dfd2726750301e6a934ef3 /models/avatars/avatar.go
parent976d1760ac483a6f5fa8fa5ad24d94cae58497eb (diff)
downloadgitea-9f8d59858af581a2c278a4896a301339991ece5b.tar.gz
gitea-9f8d59858af581a2c278a4896a301339991ece5b.zip
Refactor system setting (#27000)
This PR reduces the complexity of the system setting system. It only needs one line to introduce a new option, and the option can be used anywhere out-of-box. It is still high-performant (and more performant) because the config values are cached in the config system.
Diffstat (limited to 'models/avatars/avatar.go')
-rw-r--r--models/avatars/avatar.go81
1 files changed, 58 insertions, 23 deletions
diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go
index e40aa3f542..b0bfa44089 100644
--- a/models/avatars/avatar.go
+++ b/models/avatars/avatar.go
@@ -5,18 +5,20 @@ package avatars
import (
"context"
+ "fmt"
"net/url"
"path"
"strconv"
"strings"
- "sync"
+ "sync/atomic"
"code.gitea.io/gitea/models/db"
- system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+
+ "strk.kbt.io/projects/go/libravatar"
)
const (
@@ -36,24 +38,54 @@ func init() {
db.RegisterModel(new(EmailHash))
}
-var (
+type avatarSettingStruct struct {
defaultAvatarLink string
- once sync.Once
-)
+ gravatarSource string
+ gravatarSourceURL *url.URL
+ libravatar *libravatar.Libravatar
+}
-// DefaultAvatarLink the default avatar link
-func DefaultAvatarLink() string {
- once.Do(func() {
+var avatarSettingAtomic atomic.Pointer[avatarSettingStruct]
+
+func loadAvatarSetting() (*avatarSettingStruct, error) {
+ s := avatarSettingAtomic.Load()
+ if s == nil || s.gravatarSource != setting.GravatarSource {
+ s = &avatarSettingStruct{}
u, err := url.Parse(setting.AppSubURL)
if err != nil {
- log.Error("Can not parse AppSubURL: %v", err)
- return
+ return nil, fmt.Errorf("unable to parse AppSubURL: %w", err)
}
u.Path = path.Join(u.Path, "/assets/img/avatar_default.png")
- defaultAvatarLink = u.String()
- })
- return defaultAvatarLink
+ s.defaultAvatarLink = u.String()
+
+ s.gravatarSourceURL, err = url.Parse(setting.GravatarSource)
+ if err != nil {
+ return nil, fmt.Errorf("unable to parse GravatarSource %q: %w", setting.GravatarSource, err)
+ }
+
+ s.libravatar = libravatar.New()
+ if s.gravatarSourceURL.Scheme == "https" {
+ s.libravatar.SetUseHTTPS(true)
+ s.libravatar.SetSecureFallbackHost(s.gravatarSourceURL.Host)
+ } else {
+ s.libravatar.SetUseHTTPS(false)
+ s.libravatar.SetFallbackHost(s.gravatarSourceURL.Host)
+ }
+
+ avatarSettingAtomic.Store(s)
+ }
+ return s, nil
+}
+
+// DefaultAvatarLink the default avatar link
+func DefaultAvatarLink() string {
+ a, err := loadAvatarSetting()
+ if err != nil {
+ log.Error("Failed to loadAvatarSetting: %v", err)
+ return ""
+ }
+ return a.defaultAvatarLink
}
// HashEmail hashes email address to MD5 string. https://en.gravatar.com/site/implement/hash/
@@ -76,7 +108,11 @@ func GetEmailForHash(md5Sum string) (string, error) {
// LibravatarURL returns the URL for the given email. Slow due to the DNS lookup.
// This function should only be called if a federated avatar service is enabled.
func LibravatarURL(email string) (*url.URL, error) {
- urlStr, err := system_model.LibravatarService.FromEmail(email)
+ a, err := loadAvatarSetting()
+ if err != nil {
+ return nil, err
+ }
+ urlStr, err := a.libravatar.FromEmail(email)
if err != nil {
log.Error("LibravatarService.FromEmail(email=%s): error %v", email, err)
return nil, err
@@ -153,15 +189,13 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return DefaultAvatarLink()
}
- disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar,
- setting.GetDefaultDisableGravatar(),
- )
-
- enableFederatedAvatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureEnableFederatedAvatar,
- setting.GetDefaultEnableFederatedAvatar(disableGravatar))
+ avatarSetting, err := loadAvatarSetting()
+ if err != nil {
+ return DefaultAvatarLink()
+ }
- var err error
- if enableFederatedAvatar && system_model.LibravatarService != nil {
+ enableFederatedAvatar := setting.Config().Picture.EnableFederatedAvatar.Value(ctx)
+ if enableFederatedAvatar {
emailHash := saveEmailHash(email)
if final {
// for final link, we can spend more time on slow external query
@@ -179,9 +213,10 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
return urlStr
}
+ disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx)
if !disableGravatar {
// copy GravatarSourceURL, because we will modify its Path.
- avatarURLCopy := *system_model.GravatarSourceURL
+ avatarURLCopy := *avatarSetting.gravatarSourceURL
avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email))
return generateRecognizedAvatarURL(avatarURLCopy, size)
}