diff --git a/src/controller/config/controller.go b/src/controller/config/controller.go index cf90d085a..28e345874 100644 --- a/src/controller/config/controller.go +++ b/src/controller/config/controller.go @@ -227,5 +227,5 @@ func (c *controller) authModeCanBeModified(ctx context.Context) (bool, error) { if err != nil { return false, err } - return cnt == 1, nil // admin user only + return cnt == 0, nil } diff --git a/src/pkg/user/manager.go b/src/pkg/user/manager.go index 3ba06a1c3..0e25778ca 100644 --- a/src/pkg/user/manager.go +++ b/src/pkg/user/manager.go @@ -42,7 +42,7 @@ type Manager interface { // List users according to the query List(ctx context.Context, query *q.Query, options ...models.Option) (commonmodels.Users, error) // Count counts the number of users according to the query - Count(ctx context.Context, query *q.Query) (int64, error) + Count(ctx context.Context, query *q.Query, options ...models.Option) (int64, error) // Create creates the user, the password of input should be plaintext Create(ctx context.Context, user *commonmodels.User) (int, error) // Delete deletes the user by updating user's delete flag and update the name and Email @@ -131,7 +131,11 @@ func (m *manager) MatchLocalPassword(ctx context.Context, usernameOrEmail, passw return nil, nil } -func (m *manager) Count(ctx context.Context, query *q.Query) (int64, error) { +func (m *manager) Count(ctx context.Context, query *q.Query, options ...models.Option) (int64, error) { + opts := models.NewOptions(options...) + if !opts.IncludeDefaultAdmin { + query = excludeDefaultAdmin(query) + } return m.dao.Count(ctx, query) } @@ -206,11 +210,22 @@ func (m *manager) List(ctx context.Context, query *q.Query, options ...models.Op } opts := models.NewOptions(options...) if !opts.IncludeDefaultAdmin { - query.Keywords["user_id__gt"] = 1 + query = excludeDefaultAdmin(query) } return m.dao.List(ctx, query) } +func excludeDefaultAdmin(query *q.Query) (qu *q.Query) { + if query == nil { + query = q.New(q.KeyWords{}) + } + if query.Keywords == nil { + query.Keywords = q.KeyWords{} + } + query.Keywords["user_id__gt"] = 1 + return query +} + func injectPasswd(u *commonmodels.User, password string) { salt := utils.GenerateRandomString() u.Password = utils.Encrypt(password, salt, utils.SHA256) diff --git a/src/testing/pkg/user/manager.go b/src/testing/pkg/user/manager.go index 2d591b723..708af1f4a 100644 --- a/src/testing/pkg/user/manager.go +++ b/src/testing/pkg/user/manager.go @@ -5,12 +5,13 @@ package user import ( context "context" - models "github.com/goharbor/harbor/src/common/models" + commonmodels "github.com/goharbor/harbor/src/common/models" + mock "github.com/stretchr/testify/mock" - q "github.com/goharbor/harbor/src/lib/q" + models "github.com/goharbor/harbor/src/pkg/user/models" - usermodels "github.com/goharbor/harbor/src/pkg/user/models" + q "github.com/goharbor/harbor/src/lib/q" ) // Manager is an autogenerated mock type for the Manager type @@ -18,20 +19,27 @@ type Manager struct { mock.Mock } -// Count provides a mock function with given fields: ctx, query -func (_m *Manager) Count(ctx context.Context, query *q.Query) (int64, error) { - ret := _m.Called(ctx, query) +// Count provides a mock function with given fields: ctx, query, options +func (_m *Manager) Count(ctx context.Context, query *q.Query, options ...models.Option) (int64, error) { + _va := make([]interface{}, len(options)) + for _i := range options { + _va[_i] = options[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, query) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) var r0 int64 - if rf, ok := ret.Get(0).(func(context.Context, *q.Query) int64); ok { - r0 = rf(ctx, query) + if rf, ok := ret.Get(0).(func(context.Context, *q.Query, ...models.Option) int64); ok { + r0 = rf(ctx, query, options...) } else { r0 = ret.Get(0).(int64) } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *q.Query) error); ok { - r1 = rf(ctx, query) + if rf, ok := ret.Get(1).(func(context.Context, *q.Query, ...models.Option) error); ok { + r1 = rf(ctx, query, options...) } else { r1 = ret.Error(1) } @@ -40,18 +48,18 @@ func (_m *Manager) Count(ctx context.Context, query *q.Query) (int64, error) { } // Create provides a mock function with given fields: ctx, _a1 -func (_m *Manager) Create(ctx context.Context, _a1 *models.User) (int, error) { +func (_m *Manager) Create(ctx context.Context, _a1 *commonmodels.User) (int, error) { ret := _m.Called(ctx, _a1) var r0 int - if rf, ok := ret.Get(0).(func(context.Context, *models.User) int); ok { + if rf, ok := ret.Get(0).(func(context.Context, *commonmodels.User) int); ok { r0 = rf(ctx, _a1) } else { r0 = ret.Get(0).(int) } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *models.User) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *commonmodels.User) error); ok { r1 = rf(ctx, _a1) } else { r1 = ret.Error(1) @@ -89,15 +97,15 @@ func (_m *Manager) DeleteGDPR(ctx context.Context, id int) error { } // Get provides a mock function with given fields: ctx, id -func (_m *Manager) Get(ctx context.Context, id int) (*models.User, error) { +func (_m *Manager) Get(ctx context.Context, id int) (*commonmodels.User, error) { ret := _m.Called(ctx, id) - var r0 *models.User - if rf, ok := ret.Get(0).(func(context.Context, int) *models.User); ok { + var r0 *commonmodels.User + if rf, ok := ret.Get(0).(func(context.Context, int) *commonmodels.User); ok { r0 = rf(ctx, id) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.User) + r0 = ret.Get(0).(*commonmodels.User) } } @@ -112,15 +120,15 @@ func (_m *Manager) Get(ctx context.Context, id int) (*models.User, error) { } // GetByName provides a mock function with given fields: ctx, username -func (_m *Manager) GetByName(ctx context.Context, username string) (*models.User, error) { +func (_m *Manager) GetByName(ctx context.Context, username string) (*commonmodels.User, error) { ret := _m.Called(ctx, username) - var r0 *models.User - if rf, ok := ret.Get(0).(func(context.Context, string) *models.User); ok { + var r0 *commonmodels.User + if rf, ok := ret.Get(0).(func(context.Context, string) *commonmodels.User); ok { r0 = rf(ctx, username) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.User) + r0 = ret.Get(0).(*commonmodels.User) } } @@ -135,7 +143,7 @@ func (_m *Manager) GetByName(ctx context.Context, username string) (*models.User } // List provides a mock function with given fields: ctx, query, options -func (_m *Manager) List(ctx context.Context, query *q.Query, options ...usermodels.Option) (models.Users, error) { +func (_m *Manager) List(ctx context.Context, query *q.Query, options ...models.Option) (commonmodels.Users, error) { _va := make([]interface{}, len(options)) for _i := range options { _va[_i] = options[_i] @@ -145,17 +153,17 @@ func (_m *Manager) List(ctx context.Context, query *q.Query, options ...usermode _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 models.Users - if rf, ok := ret.Get(0).(func(context.Context, *q.Query, ...usermodels.Option) models.Users); ok { + var r0 commonmodels.Users + if rf, ok := ret.Get(0).(func(context.Context, *q.Query, ...models.Option) commonmodels.Users); ok { r0 = rf(ctx, query, options...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(models.Users) + r0 = ret.Get(0).(commonmodels.Users) } } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *q.Query, ...usermodels.Option) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *q.Query, ...models.Option) error); ok { r1 = rf(ctx, query, options...) } else { r1 = ret.Error(1) @@ -165,15 +173,15 @@ func (_m *Manager) List(ctx context.Context, query *q.Query, options ...usermode } // MatchLocalPassword provides a mock function with given fields: ctx, username, password -func (_m *Manager) MatchLocalPassword(ctx context.Context, username string, password string) (*models.User, error) { +func (_m *Manager) MatchLocalPassword(ctx context.Context, username string, password string) (*commonmodels.User, error) { ret := _m.Called(ctx, username, password) - var r0 *models.User - if rf, ok := ret.Get(0).(func(context.Context, string, string) *models.User); ok { + var r0 *commonmodels.User + if rf, ok := ret.Get(0).(func(context.Context, string, string) *commonmodels.User); ok { r0 = rf(ctx, username, password) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.User) + r0 = ret.Get(0).(*commonmodels.User) } } @@ -188,11 +196,11 @@ func (_m *Manager) MatchLocalPassword(ctx context.Context, username string, pass } // Onboard provides a mock function with given fields: ctx, _a1 -func (_m *Manager) Onboard(ctx context.Context, _a1 *models.User) error { +func (_m *Manager) Onboard(ctx context.Context, _a1 *commonmodels.User) error { ret := _m.Called(ctx, _a1) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *models.User) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, *commonmodels.User) error); ok { r0 = rf(ctx, _a1) } else { r0 = ret.Error(0) @@ -230,7 +238,7 @@ func (_m *Manager) UpdatePassword(ctx context.Context, id int, newPassword strin } // UpdateProfile provides a mock function with given fields: ctx, _a1, col -func (_m *Manager) UpdateProfile(ctx context.Context, _a1 *models.User, col ...string) error { +func (_m *Manager) UpdateProfile(ctx context.Context, _a1 *commonmodels.User, col ...string) error { _va := make([]interface{}, len(col)) for _i := range col { _va[_i] = col[_i] @@ -241,7 +249,7 @@ func (_m *Manager) UpdateProfile(ctx context.Context, _a1 *models.User, col ...s ret := _m.Called(_ca...) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *models.User, ...string) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, *commonmodels.User, ...string) error); ok { r0 = rf(ctx, _a1, col...) } else { r0 = ret.Error(0)