diff options
Diffstat (limited to 'internal/route')
-rw-r--r-- | internal/route/lfs/mocks_test.go | 246 | ||||
-rw-r--r-- | internal/route/org/setting.go | 2 | ||||
-rw-r--r-- | internal/route/user/setting.go | 39 |
3 files changed, 263 insertions, 24 deletions
diff --git a/internal/route/lfs/mocks_test.go b/internal/route/lfs/mocks_test.go index 9cf1827b..4f443f9f 100644 --- a/internal/route/lfs/mocks_test.go +++ b/internal/route/lfs/mocks_test.go @@ -2299,6 +2299,9 @@ type MockUsersStore struct { // CreateFunc is an instance of a mock function object controlling the // behavior of the method Create. CreateFunc *UsersStoreCreateFunc + // DeleteCustomAvatarFunc is an instance of a mock function object + // controlling the behavior of the method DeleteCustomAvatar. + DeleteCustomAvatarFunc *UsersStoreDeleteCustomAvatarFunc // GetByEmailFunc is an instance of a mock function object controlling // the behavior of the method GetByEmail. GetByEmailFunc *UsersStoreGetByEmailFunc @@ -2317,6 +2320,9 @@ type MockUsersStore struct { // ListFollowingsFunc is an instance of a mock function object // controlling the behavior of the method ListFollowings. ListFollowingsFunc *UsersStoreListFollowingsFunc + // UseCustomAvatarFunc is an instance of a mock function object + // controlling the behavior of the method UseCustomAvatar. + UseCustomAvatarFunc *UsersStoreUseCustomAvatarFunc } // NewMockUsersStore creates a new mock of the UsersStore interface. All @@ -2333,6 +2339,11 @@ func NewMockUsersStore() *MockUsersStore { return }, }, + DeleteCustomAvatarFunc: &UsersStoreDeleteCustomAvatarFunc{ + defaultHook: func(context.Context, int64) (r0 error) { + return + }, + }, GetByEmailFunc: &UsersStoreGetByEmailFunc{ defaultHook: func(context.Context, string) (r0 *db.User, r1 error) { return @@ -2363,6 +2374,11 @@ func NewMockUsersStore() *MockUsersStore { return }, }, + UseCustomAvatarFunc: &UsersStoreUseCustomAvatarFunc{ + defaultHook: func(context.Context, int64, []byte) (r0 error) { + return + }, + }, } } @@ -2380,6 +2396,11 @@ func NewStrictMockUsersStore() *MockUsersStore { panic("unexpected invocation of MockUsersStore.Create") }, }, + DeleteCustomAvatarFunc: &UsersStoreDeleteCustomAvatarFunc{ + defaultHook: func(context.Context, int64) error { + panic("unexpected invocation of MockUsersStore.DeleteCustomAvatar") + }, + }, GetByEmailFunc: &UsersStoreGetByEmailFunc{ defaultHook: func(context.Context, string) (*db.User, error) { panic("unexpected invocation of MockUsersStore.GetByEmail") @@ -2410,6 +2431,11 @@ func NewStrictMockUsersStore() *MockUsersStore { panic("unexpected invocation of MockUsersStore.ListFollowings") }, }, + UseCustomAvatarFunc: &UsersStoreUseCustomAvatarFunc{ + defaultHook: func(context.Context, int64, []byte) error { + panic("unexpected invocation of MockUsersStore.UseCustomAvatar") + }, + }, } } @@ -2423,6 +2449,9 @@ func NewMockUsersStoreFrom(i db.UsersStore) *MockUsersStore { CreateFunc: &UsersStoreCreateFunc{ defaultHook: i.Create, }, + DeleteCustomAvatarFunc: &UsersStoreDeleteCustomAvatarFunc{ + defaultHook: i.DeleteCustomAvatar, + }, GetByEmailFunc: &UsersStoreGetByEmailFunc{ defaultHook: i.GetByEmail, }, @@ -2441,6 +2470,9 @@ func NewMockUsersStoreFrom(i db.UsersStore) *MockUsersStore { ListFollowingsFunc: &UsersStoreListFollowingsFunc{ defaultHook: i.ListFollowings, }, + UseCustomAvatarFunc: &UsersStoreUseCustomAvatarFunc{ + defaultHook: i.UseCustomAvatar, + }, } } @@ -2671,6 +2703,112 @@ func (c UsersStoreCreateFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1} } +// UsersStoreDeleteCustomAvatarFunc describes the behavior when the +// DeleteCustomAvatar method of the parent MockUsersStore instance is +// invoked. +type UsersStoreDeleteCustomAvatarFunc struct { + defaultHook func(context.Context, int64) error + hooks []func(context.Context, int64) error + history []UsersStoreDeleteCustomAvatarFuncCall + mutex sync.Mutex +} + +// DeleteCustomAvatar delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockUsersStore) DeleteCustomAvatar(v0 context.Context, v1 int64) error { + r0 := m.DeleteCustomAvatarFunc.nextHook()(v0, v1) + m.DeleteCustomAvatarFunc.appendCall(UsersStoreDeleteCustomAvatarFuncCall{v0, v1, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the DeleteCustomAvatar +// method of the parent MockUsersStore instance is invoked and the hook +// queue is empty. +func (f *UsersStoreDeleteCustomAvatarFunc) SetDefaultHook(hook func(context.Context, int64) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// DeleteCustomAvatar method of the parent MockUsersStore instance invokes +// the hook at the front of the queue and discards it. After the queue is +// empty, the default hook function is invoked for any future action. +func (f *UsersStoreDeleteCustomAvatarFunc) PushHook(hook func(context.Context, int64) error) { + f.mutex.Lock() + f.hooks = append(f.hooks, hook) + f.mutex.Unlock() +} + +// SetDefaultReturn calls SetDefaultHook with a function that returns the +// given values. +func (f *UsersStoreDeleteCustomAvatarFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, int64) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *UsersStoreDeleteCustomAvatarFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, int64) error { + return r0 + }) +} + +func (f *UsersStoreDeleteCustomAvatarFunc) nextHook() func(context.Context, int64) error { + f.mutex.Lock() + defer f.mutex.Unlock() + + if len(f.hooks) == 0 { + return f.defaultHook + } + + hook := f.hooks[0] + f.hooks = f.hooks[1:] + return hook +} + +func (f *UsersStoreDeleteCustomAvatarFunc) appendCall(r0 UsersStoreDeleteCustomAvatarFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of UsersStoreDeleteCustomAvatarFuncCall +// objects describing the invocations of this function. +func (f *UsersStoreDeleteCustomAvatarFunc) History() []UsersStoreDeleteCustomAvatarFuncCall { + f.mutex.Lock() + history := make([]UsersStoreDeleteCustomAvatarFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// UsersStoreDeleteCustomAvatarFuncCall is an object that describes an +// invocation of method DeleteCustomAvatar on an instance of MockUsersStore. +type UsersStoreDeleteCustomAvatarFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is the value of the 2nd argument passed to this method + // invocation. + Arg1 int64 + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c UsersStoreDeleteCustomAvatarFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c UsersStoreDeleteCustomAvatarFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} + // UsersStoreGetByEmailFunc describes the behavior when the GetByEmail // method of the parent MockUsersStore instance is invoked. type UsersStoreGetByEmailFunc struct { @@ -3332,3 +3470,111 @@ func (c UsersStoreListFollowingsFuncCall) Args() []interface{} { func (c UsersStoreListFollowingsFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1} } + +// UsersStoreUseCustomAvatarFunc describes the behavior when the +// UseCustomAvatar method of the parent MockUsersStore instance is invoked. +type UsersStoreUseCustomAvatarFunc struct { + defaultHook func(context.Context, int64, []byte) error + hooks []func(context.Context, int64, []byte) error + history []UsersStoreUseCustomAvatarFuncCall + mutex sync.Mutex +} + +// UseCustomAvatar delegates to the next hook function in the queue and +// stores the parameter and result values of this invocation. +func (m *MockUsersStore) UseCustomAvatar(v0 context.Context, v1 int64, v2 []byte) error { + r0 := m.UseCustomAvatarFunc.nextHook()(v0, v1, v2) + m.UseCustomAvatarFunc.appendCall(UsersStoreUseCustomAvatarFuncCall{v0, v1, v2, r0}) + return r0 +} + +// SetDefaultHook sets function that is called when the UseCustomAvatar +// method of the parent MockUsersStore instance is invoked and the hook +// queue is empty. +func (f *UsersStoreUseCustomAvatarFunc) SetDefaultHook(hook func(context.Context, int64, []byte) error) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// UseCustomAvatar method of the parent MockUsersStore instance invokes the +// hook at the front of the queue and discards it. After the queue is empty, +// the default hook function is invoked for any future action. +func (f *UsersStoreUseCustomAvatarFunc) PushHook(hook func(context.Context, int64, []byte) error) { + f.mutex.Lock() + f.hooks = append(f.hooks, hook) + f.mutex.Unlock() +} + +// SetDefaultReturn calls SetDefaultHook with a function that returns the +// given values. +func (f *UsersStoreUseCustomAvatarFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, int64, []byte) error { + return r0 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *UsersStoreUseCustomAvatarFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, int64, []byte) error { + return r0 + }) +} + +func (f *UsersStoreUseCustomAvatarFunc) nextHook() func(context.Context, int64, []byte) error { + f.mutex.Lock() + defer f.mutex.Unlock() + + if len(f.hooks) == 0 { + return f.defaultHook + } + + hook := f.hooks[0] + f.hooks = f.hooks[1:] + return hook +} + +func (f *UsersStoreUseCustomAvatarFunc) appendCall(r0 UsersStoreUseCustomAvatarFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of UsersStoreUseCustomAvatarFuncCall objects +// describing the invocations of this function. +func (f *UsersStoreUseCustomAvatarFunc) History() []UsersStoreUseCustomAvatarFuncCall { + f.mutex.Lock() + history := make([]UsersStoreUseCustomAvatarFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// UsersStoreUseCustomAvatarFuncCall is an object that describes an +// invocation of method UseCustomAvatar on an instance of MockUsersStore. +type UsersStoreUseCustomAvatarFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is the value of the 2nd argument passed to this method + // invocation. + Arg1 int64 + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 []byte + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c UsersStoreUseCustomAvatarFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c UsersStoreUseCustomAvatarFuncCall) Results() []interface{} { + return []interface{}{c.Result0} +} diff --git a/internal/route/org/setting.go b/internal/route/org/setting.go index e15b9faf..5047a7d5 100644 --- a/internal/route/org/setting.go +++ b/internal/route/org/setting.go @@ -96,7 +96,7 @@ func SettingsAvatar(c *context.Context, f form.Avatar) { } func SettingsDeleteAvatar(c *context.Context) { - if err := c.Org.Organization.DeleteAvatar(); err != nil { + if err := db.Users.DeleteCustomAvatar(c.Req.Context(), c.Org.Organization.ID); err != nil { c.Flash.Error(err.Error()) } diff --git a/internal/route/user/setting.go b/internal/route/user/setting.go index cdb5eee2..3ea1c33e 100644 --- a/internal/route/user/setting.go +++ b/internal/route/user/setting.go @@ -13,9 +13,9 @@ import ( "io" "strings" + "github.com/pkg/errors" "github.com/pquerna/otp" "github.com/pquerna/otp/totp" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -23,7 +23,6 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/cryptoutil" "gogs.io/gogs/internal/db" - "gogs.io/gogs/internal/db/errors" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/form" "gogs.io/gogs/internal/tool" @@ -117,10 +116,15 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) { // FIXME: limit upload size func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxUser *db.User) error { - ctxUser.UseCustomAvatar = f.Source == form.AVATAR_LOCAL - if len(f.Gravatar) > 0 { + if f.Source == form.AVATAR_BYMAIL && len(f.Gravatar) > 0 { + ctxUser.UseCustomAvatar = false ctxUser.Avatar = cryptoutil.MD5(f.Gravatar) ctxUser.AvatarEmail = f.Gravatar + + if err := db.UpdateUser(ctxUser); err != nil { + return fmt.Errorf("update user: %v", err) + } + return nil } if f.Avatar != nil && f.Avatar.Filename != "" { @@ -128,9 +132,7 @@ func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxUser *db.User) er if err != nil { return fmt.Errorf("open avatar reader: %v", err) } - defer func() { - _ = r.Close() - }() + defer func() { _ = r.Close() }() data, err := io.ReadAll(r) if err != nil { @@ -139,23 +141,13 @@ func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxUser *db.User) er if !tool.IsImageFile(data) { return errors.New(c.Tr("settings.uploaded_avatar_not_a_image")) } - if err = ctxUser.UploadAvatar(data); err != nil { - return fmt.Errorf("upload avatar: %v", err) - } - } else { - // No avatar is uploaded but setting has been changed to enable, - // generate a random one when needed. - if ctxUser.UseCustomAvatar && !com.IsFile(userutil.CustomAvatarPath(ctxUser.ID)) { - if err := userutil.GenerateRandomAvatar(ctxUser.ID, ctxUser.Name, ctxUser.Email); err != nil { - log.Error("generate random avatar [%d]: %v", ctxUser.ID, err) - } - } - } - if err := db.UpdateUser(ctxUser); err != nil { - return fmt.Errorf("update user: %v", err) + err = db.Users.UseCustomAvatar(c.Req.Context(), ctxUser.ID, data) + if err != nil { + return errors.Wrap(err, "save avatar") + } + return nil } - return nil } @@ -176,7 +168,8 @@ func SettingsAvatarPost(c *context.Context, f form.Avatar) { } func SettingsDeleteAvatar(c *context.Context) { - if err := c.User.DeleteAvatar(); err != nil { + err := db.Users.DeleteCustomAvatar(c.Req.Context(), c.User.ID) + if err != nil { c.Flash.Error(fmt.Sprintf("Failed to delete avatar: %v", err)) } |