From c5969d9898ba25ab32875a2784a397e7c6dadf08 Mon Sep 17 00:00:00 2001 From: rhclayto Date: Tue, 13 Jan 2026 06:58:08 -0700 Subject: [PATCH] feat: add configurable gravatar-compatible base URL (#2083) This adds the ability to set a base URL for a Gravatar-compatible avatar service (Gravatar itself, or Libravatar, for instance). The default will be www.gravatar.com, so nothing will change from current behaviour unless the user explicitly configures another URL. Resolves #2082 --- config-raw.json | 5 +++++ pkg/config/config.go | 8 ++++++++ pkg/modules/avatar/gravatar/gravatar.go | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/config-raw.json b/config-raw.json index 68b8767c3..4df3590d4 100644 --- a/config-raw.json +++ b/config-raw.json @@ -616,6 +616,11 @@ "key": "gravatarexpiration", "default_value": "3600", "comment": "When using gravatar, this is the duration in seconds until a cached gravatar user avatar expires" + }, + { + "key": "gravatarbaseurl", + "default_value": "https://www.gravatar.com", + "comment": "If you use a Gravatar-compatible service other than gravatar.com, you may configure the base URL for the service here.\nFor instance, gravatarbaseurl: 'https://libravatar.org'. The default is https://www.gravatar.com." } ] }, diff --git a/pkg/config/config.go b/pkg/config/config.go index d778f0bab..64e931893 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -187,6 +187,7 @@ const ( CorsMaxAge Key = `cors.maxage` AvatarGravaterExpiration Key = `avatar.gravatarexpiration` + AvatarGravatarBaseURL Key = `avatar.gravatarbaseurl` BackgroundsEnabled Key = `backgrounds.enabled` BackgroundsUploadEnabled Key = `backgrounds.providers.upload.enabled` @@ -456,6 +457,7 @@ func InitDefaultConfig() { MigrationMicrosoftTodoEnable.setDefault(false) // Avatar AvatarGravaterExpiration.setDefault(3600) + AvatarGravatarBaseURL.setDefault("https://www.gravatar.com") // Project Backgrounds BackgroundsEnabled.setDefault(true) BackgroundsUploadEnabled.setDefault(true) @@ -605,6 +607,12 @@ func InitConfig() { readConfigValuesFromFiles() + if _, err := url.ParseRequestURI(AvatarGravatarBaseURL.GetString()); err != nil { + log.Fatalf("Could not parse gravatarbaseurl: %s", err) + } + + AvatarGravatarBaseURL.Set(strings.TrimRight(AvatarGravatarBaseURL.GetString(), "/")) + if RateLimitStore.GetString() == "keyvalue" { RateLimitStore.Set(KeyvalueType.GetString()) } diff --git a/pkg/modules/avatar/gravatar/gravatar.go b/pkg/modules/avatar/gravatar/gravatar.go index 8f459e7b6..6912677d3 100644 --- a/pkg/modules/avatar/gravatar/gravatar.go +++ b/pkg/modules/avatar/gravatar/gravatar.go @@ -86,7 +86,7 @@ func (g *Provider) GetAvatar(user *user.User, size int64) ([]byte, string, error } log.Debugf("Gravatar for user %d with size %d not cached, requesting from gravatar...", user.ID, size) - req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "https://www.gravatar.com/avatar/"+utils.Md5String(strings.ToLower(user.Email))+"?s="+sizeString+"&d=mp", nil) + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, config.AvatarGravatarBaseURL.GetString()+"/avatar/"+utils.Md5String(strings.ToLower(user.Email))+"?s="+sizeString+"&d=mp", nil) if err != nil { return nil, err }