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.

avatar.go 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package user
  5. import (
  6. "context"
  7. "crypto/md5"
  8. "fmt"
  9. "image/png"
  10. "io"
  11. "strings"
  12. "code.gitea.io/gitea/models/avatars"
  13. "code.gitea.io/gitea/models/db"
  14. "code.gitea.io/gitea/modules/avatar"
  15. "code.gitea.io/gitea/modules/log"
  16. "code.gitea.io/gitea/modules/setting"
  17. "code.gitea.io/gitea/modules/storage"
  18. )
  19. // CustomAvatarRelativePath returns user custom avatar relative path.
  20. func (u *User) CustomAvatarRelativePath() string {
  21. return u.Avatar
  22. }
  23. // GenerateRandomAvatar generates a random avatar for user.
  24. func GenerateRandomAvatar(ctx context.Context, u *User) error {
  25. seed := u.Email
  26. if len(seed) == 0 {
  27. seed = u.Name
  28. }
  29. img, err := avatar.RandomImage([]byte(seed))
  30. if err != nil {
  31. return fmt.Errorf("RandomImage: %v", err)
  32. }
  33. u.Avatar = avatars.HashEmail(seed)
  34. // Don't share the images so that we can delete them easily
  35. if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
  36. if err := png.Encode(w, img); err != nil {
  37. log.Error("Encode: %v", err)
  38. }
  39. return err
  40. }); err != nil {
  41. return fmt.Errorf("Failed to create dir %s: %v", u.CustomAvatarRelativePath(), err)
  42. }
  43. if _, err := db.GetEngine(ctx).ID(u.ID).Cols("avatar").Update(u); err != nil {
  44. return err
  45. }
  46. log.Info("New random avatar created: %d", u.ID)
  47. return nil
  48. }
  49. // AvatarLinkWithSize returns a link to the user's avatar with size. size <= 0 means default size
  50. func (u *User) AvatarLinkWithSize(size int) string {
  51. if u.ID == -1 {
  52. // ghost user
  53. return avatars.DefaultAvatarLink()
  54. }
  55. useLocalAvatar := false
  56. autoGenerateAvatar := false
  57. switch {
  58. case u.UseCustomAvatar:
  59. useLocalAvatar = true
  60. case setting.DisableGravatar, setting.OfflineMode:
  61. useLocalAvatar = true
  62. autoGenerateAvatar = true
  63. }
  64. if useLocalAvatar {
  65. if u.Avatar == "" && autoGenerateAvatar {
  66. if err := GenerateRandomAvatar(db.DefaultContext, u); err != nil {
  67. log.Error("GenerateRandomAvatar: %v", err)
  68. }
  69. }
  70. if u.Avatar == "" {
  71. return avatars.DefaultAvatarLink()
  72. }
  73. return avatars.GenerateUserAvatarImageLink(u.Avatar, size)
  74. }
  75. return avatars.GenerateEmailAvatarFastLink(u.AvatarEmail, size)
  76. }
  77. // AvatarLink returns the full avatar link with http host
  78. func (u *User) AvatarLink() string {
  79. link := u.AvatarLinkWithSize(0)
  80. if !strings.HasPrefix(link, "//") && !strings.Contains(link, "://") {
  81. return setting.AppURL + strings.TrimPrefix(link, setting.AppSubURL+"/")
  82. }
  83. return link
  84. }
  85. // IsUploadAvatarChanged returns true if the current user's avatar would be changed with the provided data
  86. func (u *User) IsUploadAvatarChanged(data []byte) bool {
  87. if !u.UseCustomAvatar || len(u.Avatar) == 0 {
  88. return true
  89. }
  90. avatarID := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", u.ID, md5.Sum(data)))))
  91. return u.Avatar != avatarID
  92. }