mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.6 KiB
117 lines
3.6 KiB
// 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)) |
|
}
|
|
|