summaryrefslogtreecommitdiffstats
path: root/models/user/avatar.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
commitdd136858f1ea40ad3c94191d647487fa4f31926c (patch)
tree58fec94a7b2a12510c9664b21793f1ed560c6518 /models/user/avatar.go
parentInitial commit. (diff)
downloadforgejo-dd136858f1ea40ad3c94191d647487fa4f31926c.tar.xz
forgejo-dd136858f1ea40ad3c94191d647487fa4f31926c.zip
Adding upstream version 9.0.0.upstream/9.0.0upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'models/user/avatar.go')
-rw-r--r--models/user/avatar.go115
1 files changed, 115 insertions, 0 deletions
diff --git a/models/user/avatar.go b/models/user/avatar.go
new file mode 100644
index 0000000..c6937d7
--- /dev/null
+++ b/models/user/avatar.go
@@ -0,0 +1,115 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package user
+
+import (
+ "context"
+ "crypto/md5"
+ "fmt"
+ "image/png"
+ "io"
+ "strings"
+
+ "code.gitea.io/gitea/models/avatars"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/avatar"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/storage"
+)
+
+// CustomAvatarRelativePath returns user custom avatar relative path.
+func (u *User) CustomAvatarRelativePath() string {
+ return u.Avatar
+}
+
+// GenerateRandomAvatar generates a random avatar for user.
+func GenerateRandomAvatar(ctx context.Context, u *User) error {
+ seed := u.Email
+ if len(seed) == 0 {
+ seed = u.Name
+ }
+
+ img, err := avatar.RandomImage([]byte(seed))
+ if err != nil {
+ return fmt.Errorf("RandomImage: %w", err)
+ }
+
+ u.Avatar = avatars.HashEmail(seed)
+
+ // Don't share the images so that we can delete them easily
+ if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
+ if err := png.Encode(w, img); err != nil {
+ log.Error("Encode: %v", err)
+ }
+ return err
+ }); err != nil {
+ return fmt.Errorf("Failed to create dir %s: %w", u.CustomAvatarRelativePath(), err)
+ }
+
+ if _, err := db.GetEngine(ctx).ID(u.ID).Cols("avatar").Update(u); err != nil {
+ return err
+ }
+
+ log.Info("New random avatar created: %d", u.ID)
+ return nil
+}
+
+// AvatarLinkWithSize returns a link to the user's avatar with size. size <= 0 means default size
+func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
+ if u.IsGhost() {
+ return avatars.DefaultAvatarLink()
+ }
+
+ useLocalAvatar := false
+ autoGenerateAvatar := false
+
+ disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx)
+
+ switch {
+ case u.UseCustomAvatar:
+ useLocalAvatar = true
+ case disableGravatar, setting.OfflineMode:
+ useLocalAvatar = true
+ autoGenerateAvatar = true
+ }
+
+ if useLocalAvatar {
+ if u.Avatar == "" && autoGenerateAvatar {
+ if err := GenerateRandomAvatar(ctx, u); err != nil {
+ log.Error("GenerateRandomAvatar: %v", err)
+ }
+ }
+ if u.Avatar == "" {
+ return avatars.DefaultAvatarLink()
+ }
+ return avatars.GenerateUserAvatarImageLink(u.Avatar, size)
+ }
+ return avatars.GenerateEmailAvatarFastLink(ctx, u.AvatarEmail, size)
+}
+
+// AvatarLink returns the full avatar link with http host
+func (u *User) AvatarLink(ctx context.Context) string {
+ link := u.AvatarLinkWithSize(ctx, 0)
+ if !strings.HasPrefix(link, "//") && !strings.Contains(link, "://") {
+ return setting.AppURL + strings.TrimPrefix(link, setting.AppSubURL+"/")
+ }
+ return link
+}
+
+// IsUploadAvatarChanged returns true if the current user's avatar would be changed with the provided data
+func (u *User) IsUploadAvatarChanged(data []byte) bool {
+ if !u.UseCustomAvatar || len(u.Avatar) == 0 {
+ return true
+ }
+ avatarID := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", u.ID, md5.Sum(data)))))
+ return u.Avatar != avatarID
+}
+
+// ExistsWithAvatarAtStoragePath returns true if there is a user with this Avatar
+func ExistsWithAvatarAtStoragePath(ctx context.Context, storagePath string) (bool, error) {
+ // See func (u *User) CustomAvatarRelativePath()
+ // u.Avatar is used directly as the storage path - therefore we can check for existence directly using the path
+ return db.GetEngine(ctx).Where("`avatar`=?", storagePath).Exist(new(User))
+}