aboutsummaryrefslogtreecommitdiff
path: root/internal/db
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db')
-rw-r--r--internal/db/repo.go2
-rw-r--r--internal/db/user.go40
-rw-r--r--internal/db/users.go34
-rw-r--r--internal/db/users_test.go67
4 files changed, 102 insertions, 41 deletions
diff --git a/internal/db/repo.go b/internal/db/repo.go
index 7c307144..9f889bc2 100644
--- a/internal/db/repo.go
+++ b/internal/db/repo.go
@@ -336,7 +336,7 @@ func (repo *Repository) UploadAvatar(data []byte) error {
}
defer fw.Close()
- m := resize.Resize(avatar.AVATAR_SIZE, avatar.AVATAR_SIZE, img, resize.NearestNeighbor)
+ m := resize.Resize(avatar.DefaultSize, avatar.DefaultSize, img, resize.NearestNeighbor)
if err = png.Encode(fw, m); err != nil {
return fmt.Errorf("encode image: %v", err)
}
diff --git a/internal/db/user.go b/internal/db/user.go
index bf432a6a..6a2aa296 100644
--- a/internal/db/user.go
+++ b/internal/db/user.go
@@ -5,27 +5,22 @@
package db
import (
- "bytes"
"context"
"encoding/hex"
"fmt"
- "image"
_ "image/jpeg"
- "image/png"
"os"
"path/filepath"
"strings"
"time"
"unicode/utf8"
- "github.com/nfnt/resize"
"github.com/unknwon/com"
log "unknwon.dev/clog/v2"
"xorm.io/xorm"
"github.com/gogs/git-module"
- "gogs.io/gogs/internal/avatar"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/db/errors"
"gogs.io/gogs/internal/errutil"
@@ -58,41 +53,6 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) {
}
}
-// UploadAvatar saves custom avatar for user.
-// FIXME: split uploads to different subdirs in case we have massive number of users.
-func (u *User) UploadAvatar(data []byte) error {
- img, _, err := image.Decode(bytes.NewReader(data))
- if err != nil {
- return fmt.Errorf("decode image: %v", err)
- }
-
- _ = os.MkdirAll(conf.Picture.AvatarUploadPath, os.ModePerm)
- fw, err := os.Create(userutil.CustomAvatarPath(u.ID))
- if err != nil {
- return fmt.Errorf("create custom avatar directory: %v", err)
- }
- defer fw.Close()
-
- m := resize.Resize(avatar.AVATAR_SIZE, avatar.AVATAR_SIZE, img, resize.NearestNeighbor)
- if err = png.Encode(fw, m); err != nil {
- return fmt.Errorf("encode image: %v", err)
- }
-
- return nil
-}
-
-// DeleteAvatar deletes the user's custom avatar.
-func (u *User) DeleteAvatar() error {
- avatarPath := userutil.CustomAvatarPath(u.ID)
- log.Trace("DeleteAvatar [%d]: %s", u.ID, avatarPath)
- if err := os.Remove(avatarPath); err != nil {
- return err
- }
-
- u.UseCustomAvatar = false
- return UpdateUser(u)
-}
-
// IsAdminOfRepo returns true if user has admin or higher access of repository.
func (u *User) IsAdminOfRepo(repo *Repository) bool {
return Perms.Authorize(context.TODO(), u.ID, repo.ID, AccessModeAdmin,
diff --git a/internal/db/users.go b/internal/db/users.go
index fa327157..ca755fc6 100644
--- a/internal/db/users.go
+++ b/internal/db/users.go
@@ -7,6 +7,7 @@ package db
import (
"context"
"fmt"
+ "os"
"strings"
"time"
@@ -45,6 +46,9 @@ type UsersStore interface {
// ErrUserAlreadyExist when a user with same name already exists, or
// ErrEmailAlreadyUsed if the email has been used by another user.
Create(ctx context.Context, username, email string, opts CreateUserOptions) (*User, error)
+ // DeleteCustomAvatar deletes the current user custom avatar and falls back to
+ // use look up avatar by email.
+ DeleteCustomAvatar(ctx context.Context, userID int64) error
// GetByEmail returns the user (not organization) with given email. It ignores
// records with unverified emails and returns ErrUserNotExist when not found.
GetByEmail(ctx context.Context, email string) (*User, error)
@@ -64,6 +68,8 @@ type UsersStore interface {
// Results are paginated by given page and page size, and sorted by the time of
// follow in descending order.
ListFollowings(ctx context.Context, userID int64, page, pageSize int) ([]*User, error)
+ // UseCustomAvatar uses the given avatar as the user custom avatar.
+ UseCustomAvatar(ctx context.Context, userID int64, avatar []byte) error
}
var Users UsersStore
@@ -267,6 +273,18 @@ func (db *users) Create(ctx context.Context, username, email string, opts Create
return user, db.WithContext(ctx).Create(user).Error
}
+func (db *users) DeleteCustomAvatar(ctx context.Context, userID int64) error {
+ _ = os.Remove(userutil.CustomAvatarPath(userID))
+ return db.WithContext(ctx).
+ Model(&User{}).
+ Where("id = ?", userID).
+ Updates(map[string]interface{}{
+ "use_custom_avatar": false,
+ "updated_unix": db.NowFunc().Unix(),
+ }).
+ Error
+}
+
var _ errutil.NotFound = (*ErrUserNotExist)(nil)
type ErrUserNotExist struct {
@@ -397,6 +415,22 @@ func (db *users) ListFollowings(ctx context.Context, userID int64, page, pageSiz
return users, tx.Find(&users).Error
}
+func (db *users) UseCustomAvatar(ctx context.Context, userID int64, avatar []byte) error {
+ err := userutil.SaveAvatar(userID, avatar)
+ if err != nil {
+ return errors.Wrap(err, "save avatar")
+ }
+
+ return db.WithContext(ctx).
+ Model(&User{}).
+ Where("id = ?", userID).
+ Updates(map[string]interface{}{
+ "use_custom_avatar": true,
+ "updated_unix": db.NowFunc().Unix(),
+ }).
+ Error
+}
+
// UserType indicates the type of the user account.
type UserType int
diff --git a/internal/db/users_test.go b/internal/db/users_test.go
index 1a33151a..efd5681c 100644
--- a/internal/db/users_test.go
+++ b/internal/db/users_test.go
@@ -7,6 +7,7 @@ package db
import (
"context"
"fmt"
+ "os"
"testing"
"time"
@@ -16,6 +17,9 @@ import (
"gogs.io/gogs/internal/auth"
"gogs.io/gogs/internal/dbtest"
"gogs.io/gogs/internal/errutil"
+ "gogs.io/gogs/internal/osutil"
+ "gogs.io/gogs/internal/userutil"
+ "gogs.io/gogs/public"
)
func TestUsers(t *testing.T) {
@@ -35,12 +39,14 @@ func TestUsers(t *testing.T) {
}{
{"Authenticate", usersAuthenticate},
{"Create", usersCreate},
+ {"DeleteCustomAvatar", usersDeleteCustomAvatar},
{"GetByEmail", usersGetByEmail},
{"GetByID", usersGetByID},
{"GetByUsername", usersGetByUsername},
{"HasForkedRepository", usersHasForkedRepository},
{"ListFollowers", usersListFollowers},
{"ListFollowings", usersListFollowings},
+ {"UseCustomAvatar", usersUseCustomAvatar},
} {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
@@ -186,6 +192,42 @@ func usersCreate(t *testing.T, db *users) {
assert.Equal(t, db.NowFunc().Format(time.RFC3339), user.Updated.UTC().Format(time.RFC3339))
}
+func usersDeleteCustomAvatar(t *testing.T, db *users) {
+ ctx := context.Background()
+
+ alice, err := db.Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
+ require.NoError(t, err)
+
+ avatar, err := public.Files.ReadFile("img/avatar_default.png")
+ require.NoError(t, err)
+
+ avatarPath := userutil.CustomAvatarPath(alice.ID)
+ _ = os.Remove(avatarPath)
+ defer func() { _ = os.Remove(avatarPath) }()
+
+ err = db.UseCustomAvatar(ctx, alice.ID, avatar)
+ require.NoError(t, err)
+
+ // Make sure avatar is saved and the user flag is updated.
+ got := osutil.IsFile(avatarPath)
+ assert.True(t, got)
+
+ alice, err = db.GetByID(ctx, alice.ID)
+ require.NoError(t, err)
+ assert.True(t, alice.UseCustomAvatar)
+
+ // Delete avatar should remove the file and revert the user flag.
+ err = db.DeleteCustomAvatar(ctx, alice.ID)
+ require.NoError(t, err)
+
+ got = osutil.IsFile(avatarPath)
+ assert.False(t, got)
+
+ alice, err = db.GetByID(ctx, alice.ID)
+ require.NoError(t, err)
+ assert.False(t, alice.UseCustomAvatar)
+}
+
func usersGetByEmail(t *testing.T, db *users) {
ctx := context.Background()
@@ -366,3 +408,28 @@ func usersListFollowings(t *testing.T, db *users) {
require.Len(t, got, 1)
assert.Equal(t, alice.ID, got[0].ID)
}
+
+func usersUseCustomAvatar(t *testing.T, db *users) {
+ ctx := context.Background()
+
+ alice, err := db.Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
+ require.NoError(t, err)
+
+ avatar, err := public.Files.ReadFile("img/avatar_default.png")
+ require.NoError(t, err)
+
+ avatarPath := userutil.CustomAvatarPath(alice.ID)
+ _ = os.Remove(avatarPath)
+ defer func() { _ = os.Remove(avatarPath) }()
+
+ err = db.UseCustomAvatar(ctx, alice.ID, avatar)
+ require.NoError(t, err)
+
+ // Make sure avatar is saved and the user flag is updated.
+ got := osutil.IsFile(avatarPath)
+ assert.True(t, got)
+
+ alice, err = db.GetByID(ctx, alice.ID)
+ require.NoError(t, err)
+ assert.True(t, alice.UseCustomAvatar)
+}