| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- // Copyright 2020 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package user
-
- import (
- "context"
- "fmt"
- "image/png"
- "io"
-
- "code.gitea.io/gitea/models/avatars"
- "code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/avatar"
- "code.gitea.io/gitea/modules/httplib"
- "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)
-
- _, err = storage.Avatars.Stat(u.CustomAvatarRelativePath())
- if err != nil {
- // If unable to Stat the avatar file (usually it means non-existing), then try to save a new one
- // 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 nil
- }); err != nil {
- return fmt.Errorf("failed to save avatar %s: %w", u.CustomAvatarRelativePath(), err)
- }
- }
-
- if _, err := db.GetEngine(ctx).ID(u.ID).Cols("avatar").Update(u); err != nil {
- return err
- }
-
- 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 {
- // ghost user was deleted, Gitea actions is a bot user, 0 means the user should be a virtual user
- // which comes from git configure information
- if u.IsGhost() || u.IsGiteaActions() || u.ID <= 0 {
- 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 url with http host.
- // TODO: refactor it to a relative URL, but it is still used in API response at the moment
- func (u *User) AvatarLink(ctx context.Context) string {
- relLink := u.AvatarLinkWithSize(ctx, 0) // it can't be empty
- return httplib.MakeAbsoluteURL(ctx, relLink)
- }
-
- // 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 := avatar.HashAvatar(u.ID, 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))
- }
|