Files
Gitea/modules/setting/picture.go
T
silverwind e3ee28f15b fix(avatar): use sha256 and inline the federated avatar lookup (#38843)
- Hash emails with sha256. Gravatar moved to sha256, and both it and
libravatar.org serve the same image for either hash.
- Drop `strk.kbt.io/projects/go/libravatar` for a 46 line inline SRV
lookup. It could not bound or cancel its DNS query and panicked on an
unexpected resolver error. The replacement carries the request context
and a 3s timeout.
- Fix federated avatars querying DNS for every avatar on every render.
`loadAvatarSetting` compared a cache field that was never assigned, so
each call rebuilt the resolver and dropped its cache. That cache is
gone, both settings are read where they are used.
- Migration 348 recreates `email_hash` with a 64 char hash column and a
`hash_type` column, so a later algorithm change can tell old rows apart.
The MD5 rows are unreachable and their `UNIQUE` email index would reject
the SHA256 replacements.
- Fix a re-saved avatar form replacing an uploaded avatar with a random
one.
- Remove the `duoshuo` `GRAVATAR_SOURCE` alias, that service shut down
in 2017.
- Remove dead i18n key.

Fixes: https://github.com/go-gitea/gitea/issues/34284
Fixes: https://github.com/go-gitea/gitea/issues/28110
Docs: https://gitea.com/gitea/docs/pulls/499
Signed-off-by: silverwind <me@silverwind.io>
2026-08-10 23:13:28 +00:00

89 lines
2.4 KiB
Go

// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
// Avatar settings
var (
Avatar = struct {
Storage *Storage
MaxWidth int
MaxHeight int
MaxFileSize int64
MaxOriginSize int64
RenderedSizeFactor int
}{
MaxWidth: 4096,
MaxHeight: 4096,
MaxFileSize: 1048576,
MaxOriginSize: 262144,
RenderedSizeFactor: 2,
}
GravatarSource string
RepoAvatar = struct {
Storage *Storage
Fallback string
FallbackImage string
}{}
)
func loadAvatarsFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("picture")
avatarSec := rootCfg.Section("avatar")
storageType := sec.Key("AVATAR_STORAGE_TYPE").MustString("")
// Specifically default PATH to AVATAR_UPLOAD_PATH
avatarSec.Key("PATH").MustString(sec.Key("AVATAR_UPLOAD_PATH").String())
var err error
Avatar.Storage, err = getStorage(rootCfg, "avatars", storageType, avatarSec)
if err != nil {
return err
}
Avatar.MaxWidth = sec.Key("AVATAR_MAX_WIDTH").MustInt(4096)
Avatar.MaxHeight = sec.Key("AVATAR_MAX_HEIGHT").MustInt(4096)
Avatar.MaxFileSize = sec.Key("AVATAR_MAX_FILE_SIZE").MustInt64(1048576)
Avatar.MaxOriginSize = sec.Key("AVATAR_MAX_ORIGIN_SIZE").MustInt64(262144)
Avatar.RenderedSizeFactor = sec.Key("AVATAR_RENDERED_SIZE_FACTOR").MustInt(2)
switch source := sec.Key("GRAVATAR_SOURCE").MustString("gravatar"); source {
case "gravatar":
GravatarSource = "https://secure.gravatar.com/avatar/"
case "libravatar":
GravatarSource = "https://seccdn.libravatar.org/avatar/"
default:
GravatarSource = source
}
deprecatedSettingDB(rootCfg, "picture", "DISABLE_GRAVATAR")
deprecatedSettingDB(rootCfg, "picture", "ENABLE_FEDERATED_AVATAR")
return nil
}
func loadRepoAvatarFrom(rootCfg ConfigProvider) error {
sec := rootCfg.Section("picture")
repoAvatarSec := rootCfg.Section("repo-avatar")
storageType := sec.Key("REPOSITORY_AVATAR_STORAGE_TYPE").MustString("")
// Specifically default PATH to AVATAR_UPLOAD_PATH
repoAvatarSec.Key("PATH").MustString(sec.Key("REPOSITORY_AVATAR_UPLOAD_PATH").String())
var err error
RepoAvatar.Storage, err = getStorage(rootCfg, "repo-avatars", storageType, repoAvatarSec)
if err != nil {
return err
}
RepoAvatar.Fallback = sec.Key("REPOSITORY_AVATAR_FALLBACK").MustString("none")
RepoAvatar.FallbackImage = sec.Key("REPOSITORY_AVATAR_FALLBACK_IMAGE").MustString(AppSubURL + "/assets/img/repo_default.png")
return nil
}