diff --git a/src/core/api/immutabletagrule.go b/src/core/api/immutabletagrule.go index b89258e0f..7f5eaa40a 100644 --- a/src/core/api/immutabletagrule.go +++ b/src/core/api/immutabletagrule.go @@ -1,24 +1,21 @@ package api import ( - "encoding/json" "errors" "fmt" "net/http" "strconv" "strings" - "github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/common/rbac" - "github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/pkg/immutabletag" - "github.com/goharbor/harbor/src/pkg/retention/policy/rule" + "github.com/goharbor/harbor/src/pkg/immutabletag/model" ) // ImmutableTagRuleAPI ... type ImmutableTagRuleAPI struct { BaseController - manager immutabletag.Manager + ctr immutabletag.APIController projectID int64 ID int64 } @@ -49,7 +46,7 @@ func (itr *ImmutableTagRuleAPI) Prepare() { itr.ID = ruleID } - itr.manager = immutabletag.NewDefaultRuleManager() + itr.ctr = immutabletag.NewAPIController(immutabletag.NewDefaultRuleManager()) if strings.EqualFold(itr.Ctx.Request.Method, "get") { if !itr.requireAccess(rbac.ActionList) { @@ -77,7 +74,7 @@ func (itr *ImmutableTagRuleAPI) requireAccess(action rbac.Action) bool { // List list all immutable tag rules of current project func (itr *ImmutableTagRuleAPI) List() { - rules, err := itr.manager.QueryImmutableRuleByProjectID(itr.projectID) + rules, err := itr.ctr.ListImmutableRules(itr.projectID) if err != nil { itr.SendInternalServerError(err) return @@ -87,19 +84,14 @@ func (itr *ImmutableTagRuleAPI) List() { // Post create immutable tag rule func (itr *ImmutableTagRuleAPI) Post() { - ir := &models.ImmutableRule{} - if err := itr.DecodeJSONReq(ir); err != nil { - itr.SendBadRequestError(fmt.Errorf("the filter must be a valid json, failed to parse json, error %+v", err)) + ir := &model.Metadata{} + isValid, err := itr.DecodeJSONReqAndValidate(ir) + if !isValid { + itr.SendBadRequestError(err) return } - - if !isValidSelectorJSON(ir.TagFilter) { - itr.SendBadRequestError(fmt.Errorf("the filter should be a valid json")) - return - } - ir.ProjectID = itr.projectID - id, err := itr.manager.CreateImmutableRule(ir) + id, err := itr.ctr.CreateImmutableRule(ir) if err != nil { itr.SendInternalServerError(err) return @@ -114,7 +106,7 @@ func (itr *ImmutableTagRuleAPI) Delete() { itr.SendBadRequestError(fmt.Errorf("invalid immutable rule id %d", itr.ID)) return } - _, err := itr.manager.DeleteImmutableRule(itr.ID) + err := itr.ctr.DeleteImmutableRule(itr.ID) if err != nil { itr.SendInternalServerError(err) return @@ -123,9 +115,9 @@ func (itr *ImmutableTagRuleAPI) Delete() { // Put update an immutable tag rule func (itr *ImmutableTagRuleAPI) Put() { - ir := &models.ImmutableRule{} + ir := &model.Metadata{} if err := itr.DecodeJSONReq(ir); err != nil { - itr.SendInternalServerError(err) + itr.SendBadRequestError(err) return } ir.ID = itr.ID @@ -135,32 +127,9 @@ func (itr *ImmutableTagRuleAPI) Put() { itr.SendBadRequestError(fmt.Errorf("invalid immutable rule id %d", itr.ID)) return } - if len(ir.TagFilter) == 0 { - if _, err := itr.manager.EnableImmutableRule(itr.ID, ir.Enabled); err != nil { - itr.SendInternalServerError(err) - return - } - } else { - if !isValidSelectorJSON(ir.TagFilter) { - itr.SendBadRequestError(fmt.Errorf("the filter should be a valid json")) - return - } - - if _, err := itr.manager.UpdateImmutableRule(itr.ID, ir); err != nil { - itr.SendInternalServerError(err) - return - } + if err := itr.ctr.UpdateImmutableRule(itr.projectID, ir); err != nil { + itr.SendInternalServerError(err) + return } - -} - -func isValidSelectorJSON(filter string) bool { - tagSector := &rule.Metadata{} - err := json.Unmarshal([]byte(filter), tagSector) - if err != nil { - log.Errorf("The json is %v", filter) - return false - } - return true } diff --git a/src/core/api/immutabletagrule_test.go b/src/core/api/immutabletagrule_test.go index 7255b90ce..0877b442b 100644 --- a/src/core/api/immutabletagrule_test.go +++ b/src/core/api/immutabletagrule_test.go @@ -7,24 +7,34 @@ import ( "net/http/httptest" "testing" - "github.com/goharbor/harbor/src/common/models" "github.com/goharbor/harbor/src/pkg/immutabletag" + "github.com/goharbor/harbor/src/pkg/immutabletag/model" ) func TestImmutableTagRuleAPI_List(t *testing.T) { - tagFilter := `{ - "id":0, - "priority":0, - "disabled":false, - "action":"immutable", - "template":"immutable_template", - "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"**"}], - "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"**"}]} - }` - + metadata := &model.Metadata{ + ProjectID: 1, + Disabled: false, + TagSelectors: []*model.Selector{ + { + Kind: "doublestar", + Decoration: "matches", + Pattern: "release-[\\d\\.]+", + }, + }, + ScopeSelectors: map[string][]*model.Selector{ + "repository": { + { + Kind: "doublestar", + Decoration: "matches", + Pattern: ".+", + }, + }, + }, + } mgr := immutabletag.NewDefaultRuleManager() - id, err := mgr.CreateImmutableRule(&models.ImmutableRule{ProjectID: 1, TagFilter: tagFilter}) + id, err := mgr.CreateImmutableRule(metadata) if err != nil { t.Error(err) } @@ -46,7 +56,7 @@ func TestImmutableTagRuleAPI_List(t *testing.T) { credential: admin, }, postFunc: func(responseRecorder *httptest.ResponseRecorder) error { - var rules []models.ImmutableRule + var rules []model.Metadata err := json.Unmarshal([]byte(responseRecorder.Body.String()), &rules) if err != nil { return err @@ -54,7 +64,7 @@ func TestImmutableTagRuleAPI_List(t *testing.T) { if len(rules) <= 0 { return fmt.Errorf("no rules found") } - if rules[0].TagFilter != tagFilter { + if rules[0].TagSelectors[0].Kind != "doublestar" { return fmt.Errorf("rule is not expected. actual: %v", responseRecorder.Body.String()) } return nil @@ -86,43 +96,68 @@ func TestImmutableTagRuleAPI_List(t *testing.T) { func TestImmutableTagRuleAPI_Post(t *testing.T) { - tagFilter := `{ - "id":0, - "priority":0, - "disabled":false, - "action":"immutable", - "template":"immutable_template", - "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"**"}], - "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"**"}]} -}` - body := &models.ImmutableRule{ProjectID: 1, TagFilter: tagFilter} + // body := `{ + // "id":0, + // "projectID":1, + // "priority":0, + // "disabled":false, + // "action":"immutable", + // "template":"immutable_template", + // "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"**"}], + // "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"**"}]} + // }` + + metadata := &model.Metadata{ + ProjectID: 1, + Disabled: false, + Priority: 0, + Template: "immutable_template", + Action: "immutable", + TagSelectors: []*model.Selector{ + { + Kind: "doublestar", + Decoration: "matches", + Pattern: "release-[\\d\\.]+", + }, + }, + ScopeSelectors: map[string][]*model.Selector{ + "repository": { + { + Kind: "doublestar", + Decoration: "matches", + Pattern: ".+", + }, + }, + }, + } + cases := []*codeCheckingCase{ // 401 { request: &testingRequest{ method: http.MethodPost, url: "/api/projects/1/immutabletagrules", - bodyJSON: body, + bodyJSON: metadata, }, code: http.StatusUnauthorized, }, - // 200 + // 201 { request: &testingRequest{ method: http.MethodPost, url: "/api/projects/1/immutabletagrules", credential: admin, - bodyJSON: body, + bodyJSON: metadata, }, code: http.StatusCreated, }, - // 200 + // 201 { request: &testingRequest{ method: http.MethodPost, url: "/api/projects/1/immutabletagrules", credential: projAdmin, - bodyJSON: body, + bodyJSON: metadata, }, code: http.StatusCreated, }, @@ -132,7 +167,7 @@ func TestImmutableTagRuleAPI_Post(t *testing.T) { method: http.MethodPost, url: "/api/projects/1/immutabletagrules", credential: projGuest, - bodyJSON: body, + bodyJSON: metadata, }, code: http.StatusForbidden, }, @@ -142,40 +177,63 @@ func TestImmutableTagRuleAPI_Post(t *testing.T) { } func TestImmutableTagRuleAPI_Put(t *testing.T) { - tagFilter := `{ - "id":0, - "priority":0, - "disabled":false, - "action":"immutable", - "template":"immutable_template", - "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"**"}], - "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"**"}]} -}` - tagFilter2 := `{ - "id":0, - "priority":0, - "disabled":false, - "action":"immutable", - "template":"immutable_template", - "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"release-1.6.0"}], - "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"regids"}]} -}` + metadata := &model.Metadata{ + ProjectID: 1, + Disabled: false, + TagSelectors: []*model.Selector{ + { + Kind: "doublestar", + Decoration: "matches", + Pattern: "release-[\\d\\.]+", + }, + }, + ScopeSelectors: map[string][]*model.Selector{ + "repository": { + { + Kind: "doublestar", + Decoration: "matches", + Pattern: ".+", + }, + }, + }, + } + + metadata2 := &model.Metadata{ + ProjectID: 1, + Disabled: false, + TagSelectors: []*model.Selector{ + { + Kind: "doublestar", + Decoration: "matches", + Pattern: "latest", + }, + }, + ScopeSelectors: map[string][]*model.Selector{ + "repository": { + { + Kind: "doublestar", + Decoration: "matches", + Pattern: ".+", + }, + }, + }, + } mgr := immutabletag.NewDefaultRuleManager() - id, err := mgr.CreateImmutableRule(&models.ImmutableRule{ProjectID: 1, TagFilter: tagFilter}) + id, err := mgr.CreateImmutableRule(metadata) if err != nil { t.Error(err) } defer mgr.DeleteImmutableRule(id) + url := fmt.Sprintf("/api/projects/1/immutabletagrules/%d", id) - body := &models.ImmutableRule{ID: id, ProjectID: 1, TagFilter: tagFilter2} cases := []*codeCheckingCase{ // 401 { request: &testingRequest{ method: http.MethodPut, url: url, - bodyJSON: body, + bodyJSON: metadata2, }, code: http.StatusUnauthorized, }, @@ -185,7 +243,7 @@ func TestImmutableTagRuleAPI_Put(t *testing.T) { method: http.MethodPut, url: url, credential: admin, - bodyJSON: body, + bodyJSON: metadata2, }, code: http.StatusOK, }, @@ -195,7 +253,7 @@ func TestImmutableTagRuleAPI_Put(t *testing.T) { method: http.MethodPut, url: url, credential: projAdmin, - bodyJSON: body, + bodyJSON: metadata2, }, code: http.StatusOK, }, @@ -205,7 +263,7 @@ func TestImmutableTagRuleAPI_Put(t *testing.T) { method: http.MethodPut, url: url, credential: projGuest, - bodyJSON: body, + bodyJSON: metadata2, }, code: http.StatusForbidden, }, @@ -214,17 +272,29 @@ func TestImmutableTagRuleAPI_Put(t *testing.T) { } func TestImmutableTagRuleAPI_Delete(t *testing.T) { - tagFilter := `{ - "id":0, - "priority":0, - "disabled":false, - "action":"immutable", - "template":"immutable_template", - "tag_selectors":[{"kind":"doublestar","decoration":"matches","pattern":"**"}], - "scope_selectors":{"repository":[{"kind":"doublestar","decoration":"repoMatches","pattern":"**"}]} -}` + metadata := &model.Metadata{ + ProjectID: 1, + Disabled: false, + TagSelectors: []*model.Selector{ + { + Kind: "doublestar", + Decoration: "matches", + Pattern: "latest", + }, + }, + ScopeSelectors: map[string][]*model.Selector{ + "repository": { + { + Kind: "doublestar", + Decoration: "matches", + Pattern: ".+", + }, + }, + }, + } + mgr := immutabletag.NewDefaultRuleManager() - id, err := mgr.CreateImmutableRule(&models.ImmutableRule{ProjectID: 1, TagFilter: tagFilter}) + id, err := mgr.CreateImmutableRule(metadata) if err != nil { t.Error(err) } diff --git a/src/pkg/immutabletag/controller.go b/src/pkg/immutabletag/controller.go new file mode 100644 index 000000000..63335eb12 --- /dev/null +++ b/src/pkg/immutabletag/controller.go @@ -0,0 +1,70 @@ +package immutabletag + +import ( + "github.com/goharbor/harbor/src/pkg/immutabletag/model" +) + +// APIController to handle the requests related with immutabletag +type APIController interface { + // GetImmutableRule ... + GetImmutableRule(id int64) (*model.Metadata, error) + + // CreateImmutableRule ... + CreateImmutableRule(m *model.Metadata) (int64, error) + + // DeleteImmutableRule ... + DeleteImmutableRule(id int64) error + + // UpdateImmutableRule ... + UpdateImmutableRule(pid int64, m *model.Metadata) error + + // ListImmutableRules ... + ListImmutableRules(pid int64) ([]model.Metadata, error) +} + +// DefaultAPIController ... +type DefaultAPIController struct { + manager Manager +} + +// GetImmutableRule ... +func (r *DefaultAPIController) GetImmutableRule(id int64) (*model.Metadata, error) { + return r.manager.GetImmutableRule(id) +} + +// DeleteImmutableRule ... +func (r *DefaultAPIController) DeleteImmutableRule(id int64) error { + _, err := r.manager.DeleteImmutableRule(id) + return err +} + +// CreateImmutableRule ... +func (r *DefaultAPIController) CreateImmutableRule(m *model.Metadata) (int64, error) { + return r.manager.CreateImmutableRule(m) +} + +// UpdateImmutableRule ... +func (r *DefaultAPIController) UpdateImmutableRule(pid int64, m *model.Metadata) error { + m0, err := r.manager.GetImmutableRule(m.ID) + if err != nil { + return err + } + if m0.Disabled != m.Disabled { + _, err := r.manager.EnableImmutableRule(m.ID, m.Disabled) + return err + } + _, err = r.manager.UpdateImmutableRule(pid, m) + return err +} + +// ListImmutableRules ... +func (r *DefaultAPIController) ListImmutableRules(pid int64) ([]model.Metadata, error) { + return r.manager.QueryImmutableRuleByProjectID(pid) +} + +// NewAPIController ... +func NewAPIController(immutableMgr Manager) APIController { + return &DefaultAPIController{ + manager: immutableMgr, + } +} diff --git a/src/pkg/immutabletag/controller_test.go b/src/pkg/immutabletag/controller_test.go new file mode 100644 index 000000000..96867ef9f --- /dev/null +++ b/src/pkg/immutabletag/controller_test.go @@ -0,0 +1 @@ +package immutabletag diff --git a/src/pkg/immutabletag/dao/model/rule.go b/src/pkg/immutabletag/dao/model/rule.go index 99b502ea9..878cc3838 100644 --- a/src/pkg/immutabletag/dao/model/rule.go +++ b/src/pkg/immutabletag/dao/model/rule.go @@ -1,5 +1,13 @@ package model +import ( + "github.com/astaxie/beego/orm" +) + +func init() { + orm.RegisterModel(&ImmutableRule{}) +} + // ImmutableRule - rule which filter image tags should be immutable. type ImmutableRule struct { ID int64 `orm:"pk;auto;column(id)" json:"id,omitempty"` diff --git a/src/pkg/immutabletag/manager.go b/src/pkg/immutabletag/manager.go index 0ec671e35..4ef415ae2 100644 --- a/src/pkg/immutabletag/manager.go +++ b/src/pkg/immutabletag/manager.go @@ -1,8 +1,10 @@ package immutabletag import ( + "encoding/json" "github.com/goharbor/harbor/src/pkg/immutabletag/dao" - "github.com/goharbor/harbor/src/pkg/immutabletag/dao/model" + dao_model "github.com/goharbor/harbor/src/pkg/immutabletag/dao/model" + "github.com/goharbor/harbor/src/pkg/immutabletag/model" ) var ( @@ -13,17 +15,17 @@ var ( // Manager ... type Manager interface { // CreateImmutableRule creates the Immutable Rule - CreateImmutableRule(ir *model.ImmutableRule) (int64, error) + CreateImmutableRule(m *model.Metadata) (int64, error) // UpdateImmutableRule update the immutable rules - UpdateImmutableRule(projectID int64, ir *model.ImmutableRule) (int64, error) + UpdateImmutableRule(projectID int64, ir *model.Metadata) (int64, error) // EnableImmutableRule enable/disable immutable rules EnableImmutableRule(id int64, enabled bool) (int64, error) // GetImmutableRule get immutable rule - GetImmutableRule(id int64) (*model.ImmutableRule, error) + GetImmutableRule(id int64) (*model.Metadata, error) // QueryImmutableRuleByProjectID get all immutable rule by project - QueryImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) + QueryImmutableRuleByProjectID(projectID int64) ([]model.Metadata, error) // QueryEnabledImmutableRuleByProjectID get all enabled immutable rule by project - QueryEnabledImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) + QueryEnabledImmutableRuleByProjectID(projectID int64) ([]model.Metadata, error) // DeleteImmutableRule delete the immutable rule DeleteImmutableRule(id int64) (int64, error) } @@ -32,28 +34,68 @@ type defaultRuleManager struct { dao dao.ImmutableRuleDao } -func (drm *defaultRuleManager) CreateImmutableRule(ir *model.ImmutableRule) (int64, error) { - return drm.dao.CreateImmutableRule(ir) +func (drm *defaultRuleManager) CreateImmutableRule(ir *model.Metadata) (int64, error) { + daoRule := &dao_model.ImmutableRule{} + daoRule.Enabled = !ir.Disabled + daoRule.ProjectID = ir.ProjectID + data, _ := json.Marshal(ir) + daoRule.TagFilter = string(data) + return drm.dao.CreateImmutableRule(daoRule) } -func (drm *defaultRuleManager) UpdateImmutableRule(projectID int64, ir *model.ImmutableRule) (int64, error) { - return drm.dao.UpdateImmutableRule(projectID, ir) +func (drm *defaultRuleManager) UpdateImmutableRule(projectID int64, ir *model.Metadata) (int64, error) { + daoRule := &dao_model.ImmutableRule{} + data, _ := json.Marshal(ir) + daoRule.TagFilter = string(data) + return drm.dao.UpdateImmutableRule(projectID, daoRule) } func (drm *defaultRuleManager) EnableImmutableRule(id int64, enabled bool) (int64, error) { return drm.dao.ToggleImmutableRule(id, enabled) } -func (drm *defaultRuleManager) GetImmutableRule(id int64) (*model.ImmutableRule, error) { - return drm.dao.GetImmutableRule(id) +func (drm *defaultRuleManager) GetImmutableRule(id int64) (*model.Metadata, error) { + daoRule, err := drm.dao.GetImmutableRule(id) + if err != nil { + return nil, err + } + rule := &model.Metadata{} + if err = json.Unmarshal([]byte(daoRule.TagFilter), rule); err != nil { + return nil, err + } + return rule, nil } -func (drm *defaultRuleManager) QueryImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) { - return drm.dao.QueryImmutableRuleByProjectID(projectID) +func (drm *defaultRuleManager) QueryImmutableRuleByProjectID(projectID int64) ([]model.Metadata, error) { + daoRules, err := drm.dao.QueryImmutableRuleByProjectID(projectID) + if err != nil { + return nil, err + } + var rules []model.Metadata + for _, daoRule := range daoRules { + rule := model.Metadata{} + if err = json.Unmarshal([]byte(daoRule.TagFilter), &rule); err != nil { + return nil, err + } + rules = append(rules, rule) + } + return rules, nil } -func (drm *defaultRuleManager) QueryEnabledImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) { - return drm.dao.QueryEnabledImmutableRuleByProjectID(projectID) +func (drm *defaultRuleManager) QueryEnabledImmutableRuleByProjectID(projectID int64) ([]model.Metadata, error) { + daoRules, err := drm.dao.QueryEnabledImmutableRuleByProjectID(projectID) + if err != nil { + return nil, err + } + var rules []model.Metadata + for _, daoRule := range daoRules { + rule := model.Metadata{} + if err = json.Unmarshal([]byte(daoRule.TagFilter), &rule); err != nil { + return nil, err + } + rules = append(rules, rule) + } + return rules, nil } func (drm *defaultRuleManager) DeleteImmutableRule(id int64) (int64, error) { diff --git a/src/pkg/immutabletag/manager_test.go b/src/pkg/immutabletag/manager_test.go index 3fac4faa2..319685b26 100644 --- a/src/pkg/immutabletag/manager_test.go +++ b/src/pkg/immutabletag/manager_test.go @@ -1,7 +1,8 @@ package immutabletag import ( - "github.com/goharbor/harbor/src/pkg/immutabletag/dao/model" + dao_model "github.com/goharbor/harbor/src/pkg/immutabletag/dao/model" + "github.com/goharbor/harbor/src/pkg/immutabletag/model" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -15,30 +16,30 @@ type mockImmutableDao struct { mock.Mock } -func (m *mockImmutableDao) CreateImmutableRule(ir *model.ImmutableRule) (int64, error) { +func (m *mockImmutableDao) CreateImmutableRule(ir *dao_model.ImmutableRule) (int64, error) { args := m.Called(ir) return int64(args.Int(0)), args.Error(1) } -func (m *mockImmutableDao) UpdateImmutableRule(projectID int64, ir *model.ImmutableRule) (int64, error) { +func (m *mockImmutableDao) UpdateImmutableRule(projectID int64, ir *dao_model.ImmutableRule) (int64, error) { args := m.Called(ir) return int64(0), args.Error(1) } -func (m *mockImmutableDao) QueryImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) { +func (m *mockImmutableDao) QueryImmutableRuleByProjectID(projectID int64) ([]dao_model.ImmutableRule, error) { args := m.Called() - var irs []model.ImmutableRule + var irs []dao_model.ImmutableRule if args.Get(0) != nil { - irs = args.Get(0).([]model.ImmutableRule) + irs = args.Get(0).([]dao_model.ImmutableRule) } return irs, args.Error(1) } -func (m *mockImmutableDao) QueryEnabledImmutableRuleByProjectID(projectID int64) ([]model.ImmutableRule, error) { +func (m *mockImmutableDao) QueryEnabledImmutableRuleByProjectID(projectID int64) ([]dao_model.ImmutableRule, error) { args := m.Called() - var irs []model.ImmutableRule + var irs []dao_model.ImmutableRule if args.Get(0) != nil { - irs = args.Get(0).([]model.ImmutableRule) + irs = args.Get(0).([]dao_model.ImmutableRule) } return irs, args.Error(1) } @@ -53,11 +54,11 @@ func (m *mockImmutableDao) ToggleImmutableRule(id int64, enabled bool) (int64, e return int64(args.Int(0)), args.Error(1) } -func (m *mockImmutableDao) GetImmutableRule(id int64) (*model.ImmutableRule, error) { +func (m *mockImmutableDao) GetImmutableRule(id int64) (*dao_model.ImmutableRule, error) { args := m.Called(id) - var ir *model.ImmutableRule + var ir *dao_model.ImmutableRule if args.Get(0) != nil { - ir = args.Get(0).(*model.ImmutableRule) + ir = args.Get(0).(*dao_model.ImmutableRule) } return ir, args.Error(1) @@ -98,53 +99,75 @@ func TestManagerTestingSuite(t *testing.T) { func (m *managerTestingSuite) TestCreateImmutableRule() { m.mockImmutableDao.On("CreateImmutableRule", mock.Anything).Return(1, nil) - id, err := Mgr.CreateImmutableRule(&model.ImmutableRule{}) + id, err := Mgr.CreateImmutableRule(&model.Metadata{}) m.mockImmutableDao.AssertCalled(m.t, "CreateImmutableRule", mock.Anything) m.require.Nil(err) m.assert.Equal(int64(1), id) } func (m *managerTestingSuite) TestQueryImmutableRuleByProjectID() { - m.mockImmutableDao.On("QueryImmutableRuleByProjectID", mock.Anything).Return([]model.ImmutableRule{ + m.mockImmutableDao.On("QueryImmutableRuleByProjectID", mock.Anything).Return([]dao_model.ImmutableRule{ { - ProjectID: int64(1), - TagFilter: "project_1_tag_filter", - Enabled: false, + ID: 1, + ProjectID: 1, + Enabled: true, + TagFilter: "{\"id\":1, \"projectID\":1,\"priority\":0,\"disabled\":false,\"action\":\"immutable\"," + + "\"template\":\"immutable_template\"," + + "\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}]," + + "\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]}}", }, { - ProjectID: int64(2), - TagFilter: "project_2_tag_filter", - Enabled: true, + ID: 2, + ProjectID: 1, + Enabled: false, + TagFilter: "{\"id\":2, \"projectID\":1,\"priority\":0,\"disabled\":false,\"action\":\"immutable\"," + + "\"template\":\"immutable_template\"," + + "\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}]," + + "\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]}}", }}, nil) irs, err := Mgr.QueryImmutableRuleByProjectID(int64(1)) m.mockImmutableDao.AssertCalled(m.t, "QueryImmutableRuleByProjectID", mock.Anything) m.require.Nil(err) m.assert.Equal(len(irs), 2) - m.assert.Equal(irs[0].TagFilter, "project_1_tag_filter") + m.assert.Equal(irs[1].Disabled, false) } func (m *managerTestingSuite) TestQueryEnabledImmutableRuleByProjectID() { - m.mockImmutableDao.On("QueryEnabledImmutableRuleByProjectID", mock.Anything).Return([]model.ImmutableRule{ + m.mockImmutableDao.On("QueryEnabledImmutableRuleByProjectID", mock.Anything).Return([]dao_model.ImmutableRule{ { - ProjectID: int64(1), - TagFilter: "project_1_tag_filter", + ID: 1, + ProjectID: 1, Enabled: true, + TagFilter: "{\"id\":1, \"projectID\":1,\"priority\":0,\"disabled\":false,\"action\":\"immutable\"," + + "\"template\":\"immutable_template\"," + + "\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}]," + + "\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]}}", }, { - ProjectID: int64(2), - TagFilter: "project_2_tag_filter", + ID: 2, + ProjectID: 1, Enabled: true, + TagFilter: "{\"id\":2, \"projectID\":1,\"priority\":0,\"disabled\":false,\"action\":\"immutable\"," + + "\"template\":\"immutable_template\"," + + "\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}]," + + "\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]}}", }}, nil) irs, err := Mgr.QueryEnabledImmutableRuleByProjectID(int64(1)) m.mockImmutableDao.AssertCalled(m.t, "QueryEnabledImmutableRuleByProjectID", mock.Anything) m.require.Nil(err) m.assert.Equal(len(irs), 2) - m.assert.Equal(irs[0].Enabled, true) + m.assert.Equal(irs[0].Disabled, false) } func (m *managerTestingSuite) TestGetImmutableRule() { - m.mockImmutableDao.On("GetImmutableRule", mock.Anything).Return(&model.ImmutableRule{ - ID: 1, + m.mockImmutableDao.On("GetImmutableRule", mock.Anything).Return(&dao_model.ImmutableRule{ + ID: 1, + ProjectID: 1, + Enabled: true, + TagFilter: "{\"id\":1, \"projectID\":1,\"priority\":0,\"disabled\":false,\"action\":\"immutable\"," + + "\"template\":\"immutable_template\"," + + "\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}]," + + "\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]}}", }, nil) ir, err := Mgr.GetImmutableRule(1) m.mockImmutableDao.AssertCalled(m.t, "GetImmutableRule", mock.Anything) @@ -155,7 +178,7 @@ func (m *managerTestingSuite) TestGetImmutableRule() { func (m *managerTestingSuite) TestUpdateImmutableRule() { m.mockImmutableDao.On("UpdateImmutableRule", mock.Anything).Return(1, nil) - id, err := Mgr.UpdateImmutableRule(int64(1), &model.ImmutableRule{}) + id, err := Mgr.UpdateImmutableRule(int64(1), &model.Metadata{}) m.mockImmutableDao.AssertCalled(m.t, "UpdateImmutableRule", mock.Anything) m.require.Nil(err) m.assert.Equal(int64(0), id) diff --git a/src/pkg/immutabletag/model/rule.go b/src/pkg/immutabletag/model/rule.go index fc18c1162..0795abe6c 100644 --- a/src/pkg/immutabletag/model/rule.go +++ b/src/pkg/immutabletag/model/rule.go @@ -7,7 +7,10 @@ import ( // Metadata of the immutable rule type Metadata struct { // UUID of rule - ID int `json:"id"` + ID int64 `json:"id"` + + // ProjectID of project + ProjectID int64 `json:"project_id"` // Disabled rule Disabled bool `json:"disabled"`