@@ -5,18 +5,20 @@ package avatars
55
66import (
77 "context"
8+ "fmt"
89 "net/url"
910 "path"
1011 "strconv"
1112 "strings"
12- "sync"
13+ "sync/atomic "
1314
1415 "code.gitea.io/gitea/models/db"
15- system_model "code.gitea.io/gitea/models/system"
1616 "code.gitea.io/gitea/modules/base"
1717 "code.gitea.io/gitea/modules/cache"
1818 "code.gitea.io/gitea/modules/log"
1919 "code.gitea.io/gitea/modules/setting"
20+
21+ "strk.kbt.io/projects/go/libravatar"
2022)
2123
2224const (
@@ -36,24 +38,54 @@ func init() {
3638 db .RegisterModel (new (EmailHash ))
3739}
3840
39- var (
41+ type avatarSettingStruct struct {
4042 defaultAvatarLink string
41- once sync.Once
42- )
43+ gravatarSource string
44+ gravatarSourceURL * url.URL
45+ libravatar * libravatar.Libravatar
46+ }
4347
44- // DefaultAvatarLink the default avatar link
45- func DefaultAvatarLink () string {
46- once .Do (func () {
48+ var avatarSettingAtomic atomic.Pointer [avatarSettingStruct ]
49+
50+ func loadAvatarSetting () (* avatarSettingStruct , error ) {
51+ s := avatarSettingAtomic .Load ()
52+ if s == nil || s .gravatarSource != setting .GravatarSource {
53+ s = & avatarSettingStruct {}
4754 u , err := url .Parse (setting .AppSubURL )
4855 if err != nil {
49- log .Error ("Can not parse AppSubURL: %v" , err )
50- return
56+ return nil , fmt .Errorf ("unable to parse AppSubURL: %w" , err )
5157 }
5258
5359 u .Path = path .Join (u .Path , "/assets/img/avatar_default.png" )
54- defaultAvatarLink = u .String ()
55- })
56- return defaultAvatarLink
60+ s .defaultAvatarLink = u .String ()
61+
62+ s .gravatarSourceURL , err = url .Parse (setting .GravatarSource )
63+ if err != nil {
64+ return nil , fmt .Errorf ("unable to parse GravatarSource %q: %w" , setting .GravatarSource , err )
65+ }
66+
67+ s .libravatar = libravatar .New ()
68+ if s .gravatarSourceURL .Scheme == "https" {
69+ s .libravatar .SetUseHTTPS (true )
70+ s .libravatar .SetSecureFallbackHost (s .gravatarSourceURL .Host )
71+ } else {
72+ s .libravatar .SetUseHTTPS (false )
73+ s .libravatar .SetFallbackHost (s .gravatarSourceURL .Host )
74+ }
75+
76+ avatarSettingAtomic .Store (s )
77+ }
78+ return s , nil
79+ }
80+
81+ // DefaultAvatarLink the default avatar link
82+ func DefaultAvatarLink () string {
83+ a , err := loadAvatarSetting ()
84+ if err != nil {
85+ log .Error ("Failed to loadAvatarSetting: %v" , err )
86+ return ""
87+ }
88+ return a .defaultAvatarLink
5789}
5890
5991// HashEmail hashes email address to MD5 string. https://en.gravatar.com/site/implement/hash/
@@ -76,7 +108,11 @@ func GetEmailForHash(md5Sum string) (string, error) {
76108// LibravatarURL returns the URL for the given email. Slow due to the DNS lookup.
77109// This function should only be called if a federated avatar service is enabled.
78110func LibravatarURL (email string ) (* url.URL , error ) {
79- urlStr , err := system_model .LibravatarService .FromEmail (email )
111+ a , err := loadAvatarSetting ()
112+ if err != nil {
113+ return nil , err
114+ }
115+ urlStr , err := a .libravatar .FromEmail (email )
80116 if err != nil {
81117 log .Error ("LibravatarService.FromEmail(email=%s): error %v" , email , err )
82118 return nil , err
@@ -153,15 +189,13 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final
153189 return DefaultAvatarLink ()
154190 }
155191
156- disableGravatar := system_model .GetSettingWithCacheBool (ctx , system_model .KeyPictureDisableGravatar ,
157- setting .GetDefaultDisableGravatar (),
158- )
159-
160- enableFederatedAvatar := system_model .GetSettingWithCacheBool (ctx , system_model .KeyPictureEnableFederatedAvatar ,
161- setting .GetDefaultEnableFederatedAvatar (disableGravatar ))
192+ avatarSetting , err := loadAvatarSetting ()
193+ if err != nil {
194+ return DefaultAvatarLink ()
195+ }
162196
163- var err error
164- if enableFederatedAvatar && system_model . LibravatarService != nil {
197+ enableFederatedAvatar := setting . Config (). Picture . EnableFederatedAvatar . Value ()
198+ if enableFederatedAvatar {
165199 emailHash := saveEmailHash (email )
166200 if final {
167201 // 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
179213 return urlStr
180214 }
181215
216+ disableGravatar := setting .Config ().Picture .DisableGravatar .Value ()
182217 if ! disableGravatar {
183218 // copy GravatarSourceURL, because we will modify its Path.
184- avatarURLCopy := * system_model . GravatarSourceURL
219+ avatarURLCopy := * avatarSetting . gravatarSourceURL
185220 avatarURLCopy .Path = path .Join (avatarURLCopy .Path , HashEmail (email ))
186221 return generateRecognizedAvatarURL (avatarURLCopy , size )
187222 }
0 commit comments