diff --git a/src/controller/retention/controller.go b/src/controller/retention/controller.go index 3be7e1719..e3a31b946 100644 --- a/src/controller/retention/controller.go +++ b/src/controller/retention/controller.go @@ -305,6 +305,7 @@ func convertExecution(exec *task.Execution) *retention.Execution { Status: exec.Status, Trigger: exec.Trigger, DryRun: exec.ExtraAttrs["dry_run"].(bool), + Type: exec.VendorType, } } diff --git a/src/pkg/retention/models.go b/src/pkg/retention/models.go index a1bc1f689..f1fb27456 100644 --- a/src/pkg/retention/models.go +++ b/src/pkg/retention/models.go @@ -39,6 +39,7 @@ type Execution struct { Status string `json:"status"` Trigger string `json:"trigger"` DryRun bool `json:"dry_run"` + Type string `json:"-"` } // Task of retention diff --git a/src/server/v2.0/handler/retention.go b/src/server/v2.0/handler/retention.go index cecaa36ca..b7bd273f2 100644 --- a/src/server/v2.0/handler/retention.go +++ b/src/server/v2.0/handler/retention.go @@ -11,6 +11,7 @@ import ( "github.com/goharbor/harbor/src/common/rbac" projectCtl "github.com/goharbor/harbor/src/controller/project" retentionCtl "github.com/goharbor/harbor/src/controller/retention" + "github.com/goharbor/harbor/src/jobservice/job" "github.com/goharbor/harbor/src/lib/errors" "github.com/goharbor/harbor/src/pkg/project/metadata" "github.com/goharbor/harbor/src/pkg/retention/policy" @@ -274,11 +275,19 @@ func (r *retentionAPI) OperateRetentionExecution(ctx context.Context, params ope if err != nil { return r.SendError(ctx, errors.BadRequestError(err)) } - err = r.requireAccess(ctx, p, rbac.ActionUpdate) - if err != nil { + if p == nil { + return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode)) + } + if err := r.requireAccess(ctx, p, rbac.ActionUpdate); err != nil { return r.SendError(ctx, err) } - if err = r.retentionCtl.OperateRetentionExec(ctx, params.Eid, params.Body.Action); err != nil { + if err := r.requirePolicyAccess(ctx, p); err != nil { + return r.SendError(ctx, err) + } + if err := r.requireExecutionInProject(ctx, p, params.Eid); err != nil { + return r.SendError(ctx, err) + } + if err := r.retentionCtl.OperateRetentionExec(ctx, params.Eid, params.Body.Action); err != nil { return r.SendError(ctx, err) } return operation.NewOperateRetentionExecutionOK() @@ -323,8 +332,16 @@ func (r *retentionAPI) ListRetentionTasks(ctx context.Context, params operation. if err != nil { return r.SendError(ctx, errors.BadRequestError(err)) } - err = r.requireAccess(ctx, p, rbac.ActionList) - if err != nil { + if p == nil { + return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode)) + } + if err := r.requireAccess(ctx, p, rbac.ActionList); err != nil { + return r.SendError(ctx, err) + } + if err := r.requirePolicyAccess(ctx, p); err != nil { + return r.SendError(ctx, err) + } + if err := r.requireExecutionInProject(ctx, p, params.Eid); err != nil { return r.SendError(ctx, err) } tasks, err := r.retentionCtl.ListRetentionExecTasks(ctx, params.Eid, query) @@ -349,8 +366,16 @@ func (r *retentionAPI) GetRetentionTaskLog(ctx context.Context, params operation if err != nil { return r.SendError(ctx, errors.BadRequestError(err)) } - err = r.requireAccess(ctx, p, rbac.ActionRead) - if err != nil { + if p == nil { + return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode)) + } + if err := r.requireAccess(ctx, p, rbac.ActionRead); err != nil { + return r.SendError(ctx, err) + } + if err := r.requirePolicyAccess(ctx, p); err != nil { + return r.SendError(ctx, err) + } + if err := r.requireTaskInProject(ctx, p, params.Eid, params.Tid); err != nil { return r.SendError(ctx, err) } @@ -391,3 +416,37 @@ func (r *retentionAPI) requirePolicyAccess(ctx context.Context, p *policy.Metada return errors.NotFoundError(errors.Errorf("the retention policy id %d does not match", p.ID)) } + +func (r *retentionAPI) requireExecutionInProject(ctx context.Context, p *policy.Metadata, executionID int64) error { + exec, err := r.retentionCtl.GetRetentionExec(ctx, executionID) + if err != nil { + return err + } + if exec == nil { + return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode) + } + if exec.PolicyID != p.ID { + return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode) + } + if exec.Type != job.Retention { + return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode) + } + return nil +} + +func (r *retentionAPI) requireTaskInProject(ctx context.Context, p *policy.Metadata, executionID, taskID int64) error { + if err := r.requireExecutionInProject(ctx, p, executionID); err != nil { + return err + } + task, err := r.retentionCtl.GetRetentionExecTask(ctx, taskID) + if err != nil { + return err + } + if task == nil { + return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode) + } + if task.ExecutionID != executionID { + return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode) + } + return nil +}