diff --git a/src/controller/config/controller.go b/src/controller/config/controller.go index 1e8b41322..4fa847c53 100644 --- a/src/controller/config/controller.go +++ b/src/controller/config/controller.go @@ -19,12 +19,13 @@ import ( "encoding/json" "fmt" "github.com/goharbor/harbor/src/common" - "github.com/goharbor/harbor/src/common/dao" "github.com/goharbor/harbor/src/lib/config" "github.com/goharbor/harbor/src/lib/config/metadata" "github.com/goharbor/harbor/src/lib/config/models" "github.com/goharbor/harbor/src/lib/errors" "github.com/goharbor/harbor/src/lib/log" + "github.com/goharbor/harbor/src/lib/q" + "github.com/goharbor/harbor/src/pkg/user" ) var ( @@ -40,20 +41,23 @@ type Controller interface { UpdateUserConfigs(ctx context.Context, conf map[string]interface{}) error // GetAll get all configurations, used by internal, should include the system config items AllConfigs(ctx context.Context) (map[string]interface{}, error) + // ConvertForGet - delete sensitive attrs and add editable field to every attr + ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal bool) (map[string]*models.Value, error) } type controller struct { + userManager user.Manager } // NewController ... func NewController() Controller { - return &controller{} + return &controller{userManager: user.Mgr} } func (c *controller) UserConfigs(ctx context.Context) (map[string]*models.Value, error) { mgr := config.GetCfgManager(ctx) configs := mgr.GetUserCfgs(ctx) - return ConvertForGet(ctx, configs, false) + return c.ConvertForGet(ctx, configs, false) } func (c *controller) AllConfigs(ctx context.Context) (map[string]interface{}, error) { @@ -85,7 +89,7 @@ func (c *controller) UpdateUserConfigs(ctx context.Context, conf map[string]inte func (c *controller) validateCfg(ctx context.Context, cfgs map[string]interface{}) (bool, error) { mgr := config.GetCfgManager(ctx) - flag, err := authModeCanBeModified(ctx) + flag, err := c.authModeCanBeModified(ctx) if err != nil { return true, err } @@ -126,7 +130,7 @@ type ScanAllPolicy struct { } // ConvertForGet - delete sensitive attrs and add editable field to every attr -func ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal bool) (map[string]*models.Value, error) { +func (c *controller) ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal bool) (map[string]*models.Value, error) { result := map[string]*models.Value{} mList := metadata.Instance().GetAll() @@ -165,7 +169,7 @@ func ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal boo } // set value for auth_mode - flag, err := authModeCanBeModified(ctx) + flag, err := c.authModeCanBeModified(ctx) if err != nil { return nil, err } @@ -174,6 +178,10 @@ func ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal boo return result, nil } -func authModeCanBeModified(ctx context.Context) (bool, error) { - return dao.AuthModeCanBeModified(ctx) +func (c *controller) authModeCanBeModified(ctx context.Context) (bool, error) { + users, err := c.userManager.List(ctx, &q.Query{}) + if err != nil { + return false, err + } + return len(users) == 0, nil } diff --git a/src/controller/config/test/controller_test.go b/src/controller/config/test/controller_test.go index bafc50938..264b79822 100644 --- a/src/controller/config/test/controller_test.go +++ b/src/controller/config/test/controller_test.go @@ -77,7 +77,7 @@ func (c *controllerTestSuite) TestConvertForGet() { } // password type should not sent to external api call - resp, err := ConvertForGet(ctx, conf, false) + resp, err := c.controller.ConvertForGet(ctx, conf, false) c.Nil(err) c.Equal("ldaps.myexample,com", resp["ldap_url"].Val) c.Equal("ldap_auth", resp["auth_mode"].Val) @@ -91,7 +91,7 @@ func (c *controllerTestSuite) TestConvertForGet() { "auth_mode": "ldap_auth", "ldap_search_password": "admin", } - resp2, err2 := ConvertForGet(ctx, conf2, true) + resp2, err2 := c.controller.ConvertForGet(ctx, conf2, true) c.Nil(err2) c.Equal("ldaps.myexample,com", resp2["ldap_url"].Val) c.Equal("ldap_auth", resp2["auth_mode"].Val) diff --git a/src/lib/config/config.go b/src/lib/config/config.go index 7ff18c417..56d0399fa 100644 --- a/src/lib/config/config.go +++ b/src/lib/config/config.go @@ -18,6 +18,8 @@ import ( "context" "errors" "github.com/goharbor/harbor/src/common" + comModels "github.com/goharbor/harbor/src/common/models" + "github.com/goharbor/harbor/src/lib/config/metadata" "github.com/goharbor/harbor/src/lib/config/models" "github.com/goharbor/harbor/src/lib/encrypt" "github.com/goharbor/harbor/src/lib/log" @@ -43,6 +45,19 @@ var ( // InternalCfg internal configure response model type InternalCfg map[string]*models.Value +// Manager defines the operation for config +type Manager interface { + Load(ctx context.Context) error + Set(ctx context.Context, key string, value interface{}) + Save(ctx context.Context) error + Get(ctx context.Context, key string) *metadata.ConfigureValue + UpdateConfig(ctx context.Context, cfgs map[string]interface{}) error + GetUserCfgs(ctx context.Context) map[string]interface{} + ValidateCfg(ctx context.Context, cfgs map[string]interface{}) error + GetAll(ctx context.Context) map[string]interface{} + GetDatabaseCfg() *comModels.Database +} + // Register register the config manager func Register(name string, mgr Manager) { managersMU.Lock() diff --git a/src/lib/config/context.go b/src/lib/config/context.go index b14da4591..2aadb20dd 100644 --- a/src/lib/config/context.go +++ b/src/lib/config/context.go @@ -16,25 +16,10 @@ package config import ( "context" - "github.com/goharbor/harbor/src/common/models" - "github.com/goharbor/harbor/src/lib/config/metadata" ) type cfgMgrKey struct{} -// Manager defines the operation for config -type Manager interface { - Load(ctx context.Context) error - Set(ctx context.Context, key string, value interface{}) - Save(ctx context.Context) error - Get(ctx context.Context, key string) *metadata.ConfigureValue - UpdateConfig(ctx context.Context, cfgs map[string]interface{}) error - GetUserCfgs(ctx context.Context) map[string]interface{} - ValidateCfg(ctx context.Context, cfgs map[string]interface{}) error - GetAll(ctx context.Context) map[string]interface{} - GetDatabaseCfg() *models.Database -} - // FromContext returns CfgManager from context func FromContext(ctx context.Context) (Manager, bool) { m, ok := ctx.Value(cfgMgrKey{}).(Manager) diff --git a/src/lib/config/metadata/yaml/genyaml.go b/src/lib/config/metadata/yaml/genyaml.go index 0cd86f9d1..eb603b576 100644 --- a/src/lib/config/metadata/yaml/genyaml.go +++ b/src/lib/config/metadata/yaml/genyaml.go @@ -85,6 +85,7 @@ var responseMap = map[string]string{ "integer": "IntegerConfigItem", } +// Used to generate swagger file for config response and configurations func main() { l := []yamlFile{ {"configurations.yml", false, cfgTemplate}, diff --git a/src/pkg/config/db/dao/dao.go b/src/pkg/config/db/dao/dao.go index 6cacbcd06..2e49ebd4d 100644 --- a/src/pkg/config/db/dao/dao.go +++ b/src/pkg/config/db/dao/dao.go @@ -39,7 +39,7 @@ func New() DAO { return &dao{} } -func (d dao) GetConfigEntries(ctx context.Context) ([]*models.ConfigEntry, error) { +func (d *dao) GetConfigEntries(ctx context.Context) ([]*models.ConfigEntry, error) { o, err := orm.FromContext(ctx) if err != nil { return nil, err @@ -58,7 +58,7 @@ func (d dao) GetConfigEntries(ctx context.Context) ([]*models.ConfigEntry, error return p, nil } -func (d dao) SaveConfigEntries(ctx context.Context, entries []models.ConfigEntry) error { +func (d *dao) SaveConfigEntries(ctx context.Context, entries []models.ConfigEntry) error { o, err := orm.FromContext(ctx) if err != nil { return err @@ -84,23 +84,3 @@ func (d dao) SaveConfigEntries(ctx context.Context, entries []models.ConfigEntry } return nil } - -// GetConfigEntries Get configuration from database -func GetConfigEntries(ctx context.Context) ([]*models.ConfigEntry, error) { - o, err := orm.FromContext(ctx) - if err != nil { - return nil, err - } - var p []*models.ConfigEntry - sql := "select * from properties" - n, err := o.Raw(sql, []interface{}{}).QueryRows(&p) - - if err != nil { - return nil, err - } - - if n == 0 { - return nil, nil - } - return p, nil -} diff --git a/src/pkg/config/db/dao/dao_test.go b/src/pkg/config/db/dao/dao_test.go index b08580c21..02fcf45ce 100644 --- a/src/pkg/config/db/dao/dao_test.go +++ b/src/pkg/config/db/dao/dao_test.go @@ -56,7 +56,7 @@ func TestSaveConfigEntries(t *testing.T) { if err != nil { t.Fatalf("failed to save configuration to database %v", err) } - readEntries, err := GetConfigEntries(testCtx) + readEntries, err := dao.GetConfigEntries(testCtx) if err != nil { t.Fatalf("Failed to get configuration from database %v", err) } @@ -104,7 +104,7 @@ func TestSaveConfigEntries(t *testing.T) { if err != nil { t.Fatalf("failed to save configuration to database %v", err) } - readEntries, err = GetConfigEntries(testCtx) + readEntries, err = dao.GetConfigEntries(testCtx) if err != nil { t.Fatalf("Failed to get configuration from database %v", err) } diff --git a/src/server/v2.0/handler/config.go b/src/server/v2.0/handler/config.go index 11e423b7b..f50d45991 100644 --- a/src/server/v2.0/handler/config.go +++ b/src/server/v2.0/handler/config.go @@ -90,7 +90,7 @@ func (c *configAPI) GetInternalconfig(ctx context.Context, params configure.GetI return c.SendError(ctx, err) } cfg, err := c.controller.AllConfigs(ctx) - resultCfg, err := config.ConvertForGet(ctx, cfg, true) + resultCfg, err := c.controller.ConvertForGet(ctx, cfg, true) if err != nil { return c.SendError(ctx, err) } diff --git a/src/testing/controller/config/controller.go b/src/testing/controller/config/controller.go index 34526c2d5..54c3408e5 100644 --- a/src/testing/controller/config/controller.go +++ b/src/testing/controller/config/controller.go @@ -37,6 +37,29 @@ func (_m *Controller) AllConfigs(ctx context.Context) (map[string]interface{}, e return r0, r1 } +// ConvertForGet provides a mock function with given fields: ctx, cfg, internal +func (_m *Controller) ConvertForGet(ctx context.Context, cfg map[string]interface{}, internal bool) (map[string]*models.Value, error) { + ret := _m.Called(ctx, cfg, internal) + + var r0 map[string]*models.Value + if rf, ok := ret.Get(0).(func(context.Context, map[string]interface{}, bool) map[string]*models.Value); ok { + r0 = rf(ctx, cfg, internal) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]*models.Value) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, map[string]interface{}, bool) error); ok { + r1 = rf(ctx, cfg, internal) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // UpdateUserConfigs provides a mock function with given fields: ctx, conf func (_m *Controller) UpdateUserConfigs(ctx context.Context, conf map[string]interface{}) error { ret := _m.Called(ctx, conf)