diff --git a/api/v2.0/swagger.yaml b/api/v2.0/swagger.yaml index 46fa15561..b0d5e04c5 100644 --- a/api/v2.0/swagger.yaml +++ b/api/v2.0/swagger.yaml @@ -529,6 +529,56 @@ paths: $ref: '#/responses/409' '500': $ref: '#/responses/500' + /projects/{project_name}/repositories/{repository_name}/tags: + get: + summary: List tags + description: List tags under the specific project and repository. + tags: + - tag + operationId: listTags + parameters: + - $ref: '#/parameters/requestId' + - $ref: '#/parameters/projectName' + - $ref: '#/parameters/repositoryName' + - $ref: '#/parameters/query' + - $ref: '#/parameters/page' + - $ref: '#/parameters/pageSize' + - name: with_signature + in: query + description: Specify whether the signature is included inside the returning tags + type: boolean + required: false + default: false + - name: with_immutable_status + in: query + description: Specify whether the immutable status is included inside the returning tags + type: boolean + required: false + default: false + responses: + '200': + description: Success + headers: + X-Total-Count: + description: The total count of tags + type: integer + Link: + description: Link refers to the previous page and next page + type: string + schema: + type: array + items: + $ref: '#/definitions/Tag' + '400': + $ref: '#/responses/400' + '401': + $ref: '#/responses/401' + '403': + $ref: '#/responses/403' + '404': + $ref: '#/responses/404' + '500': + $ref: '#/responses/500' /audit-logs: get: summary: Get recent logs of the projects which the user is a member of diff --git a/src/common/rbac/const.go b/src/common/rbac/const.go index f3c7edd67..f71332b7d 100755 --- a/src/common/rbac/const.go +++ b/src/common/rbac/const.go @@ -34,37 +34,26 @@ const ( // const resource variables const ( - ResourceAll = Resource("*") // resource match any other resources - ResourceConfiguration = Resource("configuration") // project configuration compatible for portal only - ResourceHelmChart = Resource("helm-chart") - ResourceHelmChartVersion = Resource("helm-chart-version") - ResourceHelmChartVersionLabel = Resource("helm-chart-version-label") - ResourceLabel = Resource("label") - ResourceLabelResource = Resource("label-resource") - ResourceLog = Resource("log") - ResourceMember = Resource("member") - ResourceMetadata = Resource("metadata") - ResourceQuota = Resource("quota") - ResourceReplication = Resource("replication") // TODO remove - ResourceReplicationJob = Resource("replication-job") // TODO remove - ResourceReplicationExecution = Resource("replication-execution") - ResourceReplicationTask = Resource("replication-task") - ResourceRepository = Resource("repository") - ResourceTagRetention = Resource("tag-retention") - ResourceImmutableTag = Resource("immutable-tag") - ResourceRepositoryLabel = Resource("repository-label") // TODO remove - ResourceRepositoryTag = Resource("repository-tag") // TODO remove - ResourceRepositoryTagLabel = Resource("repository-tag-label") // TODO remove - ResourceRepositoryTagManifest = Resource("repository-tag-manifest") - ResourceRepositoryTagScanJob = Resource("repository-tag-scan-job") // TODO: remove - ResourceRepositoryTagVulnerability = Resource("repository-tag-vulnerability") // TODO: remove - ResourceRobot = Resource("robot") - ResourceNotificationPolicy = Resource("notification-policy") - ResourceScan = Resource("scan") - ResourceScanner = Resource("scanner") - ResourceArtifact = Resource("artifact") - ResourceTag = Resource("tag") - ResourceArtifactAddition = Resource("artifact-addition") - ResourceArtifactLabel = Resource("artifact-label") - ResourceSelf = Resource("") // subresource for self + ResourceAll = Resource("*") // resource match any other resources + ResourceConfiguration = Resource("configuration") // project configuration compatible for portal only + ResourceHelmChart = Resource("helm-chart") + ResourceHelmChartVersion = Resource("helm-chart-version") + ResourceHelmChartVersionLabel = Resource("helm-chart-version-label") + ResourceLabel = Resource("label") + ResourceLog = Resource("log") + ResourceMember = Resource("member") + ResourceMetadata = Resource("metadata") + ResourceQuota = Resource("quota") + ResourceRepository = Resource("repository") + ResourceTagRetention = Resource("tag-retention") + ResourceImmutableTag = Resource("immutable-tag") + ResourceRobot = Resource("robot") + ResourceNotificationPolicy = Resource("notification-policy") + ResourceScan = Resource("scan") + ResourceScanner = Resource("scanner") + ResourceArtifact = Resource("artifact") + ResourceTag = Resource("tag") + ResourceArtifactAddition = Resource("artifact-addition") + ResourceArtifactLabel = Resource("artifact-label") + ResourceSelf = Resource("") // subresource for self ) diff --git a/src/common/rbac/project_rbac_role.go b/src/common/rbac/project_rbac_role.go index 17d8b3ec2..87ce9e9f6 100644 --- a/src/common/rbac/project_rbac_role.go +++ b/src/common/rbac/project_rbac_role.go @@ -39,20 +39,12 @@ var ( {Resource: ResourceLog, Action: ActionList}, - {Resource: ResourceReplication, Action: ActionRead}, - {Resource: ResourceReplication, Action: ActionList}, - - {Resource: ResourceReplicationJob, Action: ActionRead}, - {Resource: ResourceReplicationJob, Action: ActionList}, - {Resource: ResourceLabel, Action: ActionCreate}, {Resource: ResourceLabel, Action: ActionRead}, {Resource: ResourceLabel, Action: ActionUpdate}, {Resource: ResourceLabel, Action: ActionDelete}, {Resource: ResourceLabel, Action: ActionList}, - {Resource: ResourceLabelResource, Action: ActionList}, - {Resource: ResourceQuota, Action: ActionRead}, {Resource: ResourceRepository, Action: ActionCreate}, @@ -75,25 +67,6 @@ var ( {Resource: ResourceImmutableTag, Action: ActionDelete}, {Resource: ResourceImmutableTag, Action: ActionList}, - {Resource: ResourceRepositoryLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionDelete}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagScanJob, Action: ActionCreate}, - {Resource: ResourceRepositoryTagScanJob, Action: ActionRead}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - - {Resource: ResourceRepositoryTagLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryTagLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryTagLabel, Action: ActionList}, - {Resource: ResourceHelmChart, Action: ActionCreate}, // upload helm chart {Resource: ResourceHelmChart, Action: ActionRead}, // download helm chart {Resource: ResourceHelmChart, Action: ActionDelete}, @@ -134,6 +107,7 @@ var ( {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, {Resource: ResourceTag, Action: ActionCreate}, {Resource: ResourceTag, Action: ActionDelete}, @@ -156,9 +130,6 @@ var ( {Resource: ResourceQuota, Action: ActionRead}, - {Resource: ResourceReplication, Action: ActionRead}, - {Resource: ResourceReplication, Action: ActionList}, - {Resource: ResourceLabel, Action: ActionCreate}, {Resource: ResourceLabel, Action: ActionRead}, {Resource: ResourceLabel, Action: ActionUpdate}, @@ -185,25 +156,6 @@ var ( {Resource: ResourceImmutableTag, Action: ActionDelete}, {Resource: ResourceImmutableTag, Action: ActionList}, - {Resource: ResourceRepositoryLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionDelete}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagScanJob, Action: ActionCreate}, - {Resource: ResourceRepositoryTagScanJob, Action: ActionRead}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - - {Resource: ResourceRepositoryTagLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryTagLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryTagLabel, Action: ActionList}, - {Resource: ResourceHelmChart, Action: ActionCreate}, {Resource: ResourceHelmChart, Action: ActionRead}, {Resource: ResourceHelmChart, Action: ActionDelete}, @@ -235,6 +187,7 @@ var ( {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, {Resource: ResourceTag, Action: ActionCreate}, {Resource: ResourceTag, Action: ActionDelete}, @@ -262,21 +215,6 @@ var ( {Resource: ResourceRepository, Action: ActionPush}, {Resource: ResourceRepository, Action: ActionPull}, - {Resource: ResourceRepositoryLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - - {Resource: ResourceRepositoryTagLabel, Action: ActionCreate}, - {Resource: ResourceRepositoryTagLabel, Action: ActionDelete}, - {Resource: ResourceRepositoryTagLabel, Action: ActionList}, - {Resource: ResourceHelmChart, Action: ActionCreate}, {Resource: ResourceHelmChart, Action: ActionRead}, {Resource: ResourceHelmChart, Action: ActionList}, @@ -302,6 +240,7 @@ var ( {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, {Resource: ResourceTag, Action: ActionCreate}, {Resource: ResourceArtifactLabel, Action: ActionCreate}, @@ -325,17 +264,6 @@ var ( {Resource: ResourceRepository, Action: ActionList}, {Resource: ResourceRepository, Action: ActionPull}, - {Resource: ResourceRepositoryLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - {Resource: ResourceHelmChart, Action: ActionRead}, {Resource: ResourceHelmChart, Action: ActionList}, @@ -351,6 +279,8 @@ var ( {Resource: ResourceScanner, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, + {Resource: ResourceArtifact, Action: ActionRead}, {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, @@ -364,13 +294,6 @@ var ( {Resource: ResourceRepository, Action: ActionList}, {Resource: ResourceRepository, Action: ActionPull}, - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - {Resource: ResourceHelmChart, Action: ActionRead}, {Resource: ResourceHelmChart, Action: ActionList}, @@ -383,6 +306,8 @@ var ( {Resource: ResourceScanner, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, + {Resource: ResourceArtifact, Action: ActionRead}, {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, diff --git a/src/common/rbac/project_rbac_util.go b/src/common/rbac/project_rbac_util.go index 8bcf1ab58..ea7e2198d 100644 --- a/src/common/rbac/project_rbac_util.go +++ b/src/common/rbac/project_rbac_util.go @@ -29,17 +29,6 @@ var ( {Resource: ResourceRepository, Action: ActionList}, {Resource: ResourceRepository, Action: ActionPull}, - {Resource: ResourceRepositoryLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTag, Action: ActionRead}, - {Resource: ResourceRepositoryTag, Action: ActionList}, - - {Resource: ResourceRepositoryTagLabel, Action: ActionList}, - - {Resource: ResourceRepositoryTagVulnerability, Action: ActionList}, - - {Resource: ResourceRepositoryTagManifest, Action: ActionRead}, - {Resource: ResourceHelmChart, Action: ActionRead}, {Resource: ResourceHelmChart, Action: ActionList}, @@ -49,6 +38,8 @@ var ( {Resource: ResourceScan, Action: ActionRead}, {Resource: ResourceScanner, Action: ActionRead}, + {Resource: ResourceTag, Action: ActionList}, + {Resource: ResourceArtifact, Action: ActionRead}, {Resource: ResourceArtifact, Action: ActionList}, {Resource: ResourceArtifactAddition, Action: ActionRead}, diff --git a/src/server/v2.0/handler/handler.go b/src/server/v2.0/handler/handler.go index e35cb1fc0..09a9b0aa1 100644 --- a/src/server/v2.0/handler/handler.go +++ b/src/server/v2.0/handler/handler.go @@ -34,6 +34,7 @@ func New() http.Handler { AuditlogAPI: newAuditLogAPI(), ScanAPI: newScanAPI(), ProjectAPI: newProjectAPI(), + TagAPI: newTagAPI(), }) if err != nil { log.Fatal(err) diff --git a/src/server/v2.0/handler/tag.go b/src/server/v2.0/handler/tag.go new file mode 100644 index 000000000..d907221f5 --- /dev/null +++ b/src/server/v2.0/handler/tag.go @@ -0,0 +1,93 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + "fmt" + + "github.com/go-openapi/runtime/middleware" + "github.com/goharbor/harbor/src/common/rbac" + "github.com/goharbor/harbor/src/controller/repository" + "github.com/goharbor/harbor/src/controller/tag" + "github.com/goharbor/harbor/src/server/v2.0/models" + operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/tag" +) + +func newTagAPI() *tagAPI { + return &tagAPI{ + repoCtl: repository.Ctl, + tagCtl: tag.Ctl, + } +} + +type tagAPI struct { + BaseAPI + repoCtl repository.Controller + tagCtl tag.Controller +} + +func (t *tagAPI) Prepare(ctx context.Context, operation string, params interface{}) middleware.Responder { + if err := unescapePathParams(params, "RepositoryName"); err != nil { + t.SendError(ctx, err) + } + return nil +} + +func (t *tagAPI) ListTags(ctx context.Context, params operation.ListTagsParams) middleware.Responder { + if err := t.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionList, rbac.ResourceTag); err != nil { + return t.SendError(ctx, err) + } + // set query + query, err := t.BuildQuery(ctx, params.Q, params.Page, params.PageSize) + if err != nil { + return t.SendError(ctx, err) + } + + repository, err := t.repoCtl.GetByName(ctx, fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName)) + if err != nil { + return t.SendError(ctx, err) + } + query.Keywords["RepositoryID"] = repository.RepositoryID + + // get the total count of tags + total, err := t.tagCtl.Count(ctx, query) + if err != nil { + return t.SendError(ctx, err) + } + + // set option + option := &tag.Option{} + if params.WithSignature != nil { + option.WithSignature = *params.WithSignature + } + if params.WithImmutableStatus != nil { + option.WithImmutableStatus = *params.WithImmutableStatus + } + // list tags according to the query and option + tags, err := t.tagCtl.List(ctx, query, option) + if err != nil { + return t.SendError(ctx, err) + } + + var ts []*models.Tag + for _, tag := range tags { + ts = append(ts, tag.ToSwagger()) + } + return operation.NewListTagsOK(). + WithXTotalCount(total). + WithLink(t.Links(ctx, params.HTTPRequest.URL, total, query.PageNumber, query.PageSize).String()). + WithPayload(ts) +}