mirror of https://github.com/goharbor/harbor.git
feat(api): support project name in the path of apis (#13744)
Support project name in the path of projects and robotsV1 APIs. Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
parent
949379f7bc
commit
af24a073dc
|
@ -98,6 +98,7 @@ paths:
|
|||
operationId: createProject
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/resourceNameInLocation'
|
||||
- name: project
|
||||
in: body
|
||||
description: New created project.
|
||||
|
@ -115,7 +116,7 @@ paths:
|
|||
$ref: '#/responses/409'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
'/projects/{project_id}':
|
||||
'/projects/{project_name_or_id}':
|
||||
get:
|
||||
summary: Return specific project detail information
|
||||
description: This endpoint returns specific project information by project ID.
|
||||
|
@ -124,7 +125,8 @@ paths:
|
|||
operationId: getProject
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectId'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
responses:
|
||||
'200':
|
||||
description: Return matched project information.
|
||||
|
@ -142,7 +144,8 @@ paths:
|
|||
operationId: updateProject
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectId'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- name: project
|
||||
in: body
|
||||
required: true
|
||||
|
@ -170,7 +173,8 @@ paths:
|
|||
operationId: deleteProject
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectId'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
|
@ -184,7 +188,7 @@ paths:
|
|||
$ref: '#/responses/412'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_id}/_deletable:
|
||||
/projects/{project_name_or_id}/_deletable:
|
||||
get:
|
||||
summary: Get the deletable status of the project
|
||||
description: Get the deletable status of the project
|
||||
|
@ -193,7 +197,8 @@ paths:
|
|||
operationId: getProjectDeletable
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectId'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
responses:
|
||||
'200':
|
||||
description: Return deletable status of the project.
|
||||
|
@ -207,7 +212,7 @@ paths:
|
|||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
'/projects/{project_id}/summary':
|
||||
'/projects/{project_name_or_id}/summary':
|
||||
get:
|
||||
summary: Get summary of the project.
|
||||
description: Get summary of the project.
|
||||
|
@ -216,7 +221,8 @@ paths:
|
|||
operationId: getProjectSummary
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectId'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
responses:
|
||||
'200':
|
||||
description: Get summary of the project successfully.
|
||||
|
@ -1416,13 +1422,14 @@ paths:
|
|||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_id_or_name}/robots:
|
||||
/projects/{project_name_or_id}/robots:
|
||||
get:
|
||||
summary: Get all robot accounts of specified project
|
||||
description: Get all robot accounts of specified project
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- $ref: '#/parameters/page'
|
||||
- $ref: '#/parameters/pageSize'
|
||||
- $ref: '#/parameters/query'
|
||||
|
@ -1457,7 +1464,8 @@ paths:
|
|||
operationId: CreateRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- name: robot
|
||||
in: body
|
||||
description: The JSON object of a robot account.
|
||||
|
@ -1486,7 +1494,7 @@ paths:
|
|||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_id_or_name}/robots/{robot_id}:
|
||||
/projects/{project_name_or_id}/robots/{robot_id}:
|
||||
get:
|
||||
summary: Get a robot account
|
||||
description: This endpoint returns specific robot account information by robot ID.
|
||||
|
@ -1495,7 +1503,8 @@ paths:
|
|||
operationId: GetRobotByIDV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
|
@ -1518,7 +1527,8 @@ paths:
|
|||
operationId: UpdateRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
- name: robot
|
||||
in: body
|
||||
|
@ -1549,7 +1559,8 @@ paths:
|
|||
operationId: DeleteRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/isResourceName'
|
||||
- $ref: '#/parameters/projectNameOrId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
|
@ -2193,23 +2204,30 @@ parameters:
|
|||
type: string
|
||||
required: false
|
||||
minLength: 1
|
||||
resourceNameInLocation:
|
||||
name: X-Resource-Name-In-Location
|
||||
description: The flag to indicate whether to return the name of the resource in Location. When X-Resource-Name-In-Location is true, the Location will return the name of the resource.
|
||||
in: header
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
isResourceName:
|
||||
name: X-Is-Resource-Name
|
||||
description: The flag to indicate whether the parameter which supports both name and id in the path is the name of the resource. When the X-Is-Resource-Name is false and the parameter can be converted to an integer, the parameter will be as an id, otherwise, it will be as a name.
|
||||
in: header
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
projectName:
|
||||
name: project_name
|
||||
in: path
|
||||
description: The name of the project
|
||||
required: true
|
||||
type: string
|
||||
projectId:
|
||||
name: project_id
|
||||
projectNameOrId:
|
||||
name: project_name_or_id
|
||||
in: path
|
||||
description: The ID of the project
|
||||
required: true
|
||||
type: integer
|
||||
format: int64
|
||||
projectIDOrName:
|
||||
name: project_id_or_name
|
||||
in: path
|
||||
description: The id or name of the project
|
||||
description: The name or id of the project
|
||||
required: true
|
||||
type: string
|
||||
repositoryName:
|
||||
|
|
|
@ -183,16 +183,23 @@ func (a *projectAPI) CreateProject(ctx context.Context, params operation.CreateP
|
|||
}
|
||||
}
|
||||
|
||||
location := fmt.Sprintf("%s/%d", strings.TrimSuffix(params.HTTPRequest.URL.Path, "/"), projectID)
|
||||
var location string
|
||||
if lib.BoolValue(params.XResourceNameInLocation) {
|
||||
location = fmt.Sprintf("%s/%s", strings.TrimSuffix(params.HTTPRequest.URL.Path, "/"), req.ProjectName)
|
||||
} else {
|
||||
location = fmt.Sprintf("%s/%d", strings.TrimSuffix(params.HTTPRequest.URL.Path, "/"), projectID)
|
||||
}
|
||||
|
||||
return operation.NewCreateProjectCreated().WithLocation(location)
|
||||
}
|
||||
|
||||
func (a *projectAPI) DeleteProject(ctx context.Context, params operation.DeleteProjectParams) middleware.Responder {
|
||||
if err := a.RequireProjectAccess(ctx, params.ProjectID, rbac.ActionDelete); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := a.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionDelete); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
result, err := a.deletable(ctx, params.ProjectID)
|
||||
p, result, err := a.deletable(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
@ -201,19 +208,19 @@ func (a *projectAPI) DeleteProject(ctx context.Context, params operation.DeleteP
|
|||
return a.SendError(ctx, errors.PreconditionFailedError(errors.New(result.Message)))
|
||||
}
|
||||
|
||||
if err := a.projectCtl.Delete(ctx, params.ProjectID); err != nil {
|
||||
if err := a.projectCtl.Delete(ctx, p.ProjectID); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
// remove the robot associated with the project
|
||||
if err := a.robotMgr.DeleteByProjectID(ctx, params.ProjectID); err != nil {
|
||||
if err := a.robotMgr.DeleteByProjectID(ctx, p.ProjectID); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
referenceID := quota.ReferenceID(params.ProjectID)
|
||||
referenceID := quota.ReferenceID(p.ProjectID)
|
||||
q, err := a.quotaCtl.GetByRef(ctx, quota.ProjectReference, referenceID)
|
||||
if err != nil {
|
||||
log.Warningf("failed to get quota for project %d, error: %v", params.ProjectID, err)
|
||||
log.Warningf("failed to get quota for project %s, error: %v", projectNameOrID, err)
|
||||
} else {
|
||||
if err := a.quotaCtl.Delete(ctx, q.ID); err != nil {
|
||||
return a.SendError(ctx, fmt.Errorf("failed to delete quota for project: %v", err))
|
||||
|
@ -221,7 +228,7 @@ func (a *projectAPI) DeleteProject(ctx context.Context, params operation.DeleteP
|
|||
}
|
||||
|
||||
// preheat policies under the project should be deleted after deleting the project
|
||||
if err = a.preheatCtl.DeletePoliciesOfProject(ctx, params.ProjectID); err != nil {
|
||||
if err = a.preheatCtl.DeletePoliciesOfProject(ctx, p.ProjectID); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
|
@ -269,11 +276,12 @@ func (a *projectAPI) GetLogs(ctx context.Context, params operation.GetLogsParams
|
|||
}
|
||||
|
||||
func (a *projectAPI) GetProject(ctx context.Context, params operation.GetProjectParams) middleware.Responder {
|
||||
if err := a.RequireProjectAccess(ctx, params.ProjectID, rbac.ActionRead); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := a.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionRead); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
p, err := a.getProject(ctx, params.ProjectID, project.WithCVEAllowlist(), project.WithOwner())
|
||||
p, err := a.getProject(ctx, projectNameOrID, project.WithCVEAllowlist(), project.WithOwner())
|
||||
if err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
@ -282,11 +290,12 @@ func (a *projectAPI) GetProject(ctx context.Context, params operation.GetProject
|
|||
}
|
||||
|
||||
func (a *projectAPI) GetProjectDeletable(ctx context.Context, params operation.GetProjectDeletableParams) middleware.Responder {
|
||||
if err := a.RequireProjectAccess(ctx, params.ProjectID, rbac.ActionDelete); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := a.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionDelete); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
result, err := a.deletable(ctx, params.ProjectID)
|
||||
_, result, err := a.deletable(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
@ -295,11 +304,12 @@ func (a *projectAPI) GetProjectDeletable(ctx context.Context, params operation.G
|
|||
}
|
||||
|
||||
func (a *projectAPI) GetProjectSummary(ctx context.Context, params operation.GetProjectSummaryParams) middleware.Responder {
|
||||
if err := a.RequireProjectAccess(ctx, params.ProjectID, rbac.ActionRead); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := a.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionRead); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
p, err := a.getProject(ctx, params.ProjectID)
|
||||
p, err := a.getProject(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
@ -440,11 +450,12 @@ func (a *projectAPI) ListProjects(ctx context.Context, params operation.ListProj
|
|||
}
|
||||
|
||||
func (a *projectAPI) UpdateProject(ctx context.Context, params operation.UpdateProjectParams) middleware.Responder {
|
||||
if err := a.RequireProjectAccess(ctx, params.ProjectID, rbac.ActionUpdate); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := a.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionUpdate); err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
||||
p, err := a.projectCtl.Get(ctx, params.ProjectID, project.Metadata(false))
|
||||
p, err := a.projectCtl.Get(ctx, projectNameOrID, project.Metadata(false))
|
||||
if err != nil {
|
||||
return a.SendError(ctx, err)
|
||||
}
|
||||
|
@ -452,10 +463,10 @@ func (a *projectAPI) UpdateProject(ctx context.Context, params operation.UpdateP
|
|||
if params.Project.CVEAllowlist != nil {
|
||||
if params.Project.CVEAllowlist.ProjectID == 0 {
|
||||
// project_id in cve_allowlist not provided or provided as 0, let it to be the id of the project which will be updating
|
||||
params.Project.CVEAllowlist.ProjectID = params.ProjectID
|
||||
} else if params.Project.CVEAllowlist.ProjectID != params.ProjectID {
|
||||
params.Project.CVEAllowlist.ProjectID = p.ProjectID
|
||||
} else if params.Project.CVEAllowlist.ProjectID != p.ProjectID {
|
||||
return a.SendError(ctx, errors.BadRequestError(nil).
|
||||
WithMessage("project_id in cve_allowlist must be %d but it's %d", params.ProjectID, params.Project.CVEAllowlist.ProjectID))
|
||||
WithMessage("project_id in cve_allowlist must be %d but it's %d", p.ProjectID, params.Project.CVEAllowlist.ProjectID))
|
||||
}
|
||||
|
||||
if err := lib.JSONCopy(&p.CVEAllowlist, params.Project.CVEAllowlist); err != nil {
|
||||
|
@ -477,26 +488,26 @@ func (a *projectAPI) UpdateProject(ctx context.Context, params operation.UpdateP
|
|||
return operation.NewUpdateProjectOK()
|
||||
}
|
||||
|
||||
func (a *projectAPI) deletable(ctx context.Context, projectID int64) (*models.ProjectDeletable, error) {
|
||||
proj, err := a.getProject(ctx, projectID)
|
||||
func (a *projectAPI) deletable(ctx context.Context, projectNameOrID interface{}) (*project.Project, *models.ProjectDeletable, error) {
|
||||
p, err := a.getProject(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := &models.ProjectDeletable{Deletable: true}
|
||||
if proj.RepoCount > 0 {
|
||||
if p.RepoCount > 0 {
|
||||
result.Deletable = false
|
||||
result.Message = "the project contains repositories, can not be deleted"
|
||||
} else if proj.ChartCount > 0 {
|
||||
} else if p.ChartCount > 0 {
|
||||
result.Deletable = false
|
||||
result.Message = "the project contains helm charts, can not be deleted"
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return p, result, nil
|
||||
}
|
||||
|
||||
func (a *projectAPI) getProject(ctx context.Context, projectID int64, options ...project.Option) (*project.Project, error) {
|
||||
p, err := a.projectCtl.Get(ctx, projectID, options...)
|
||||
func (a *projectAPI) getProject(ctx context.Context, projectNameOrID interface{}, options ...project.Option) (*project.Project, error) {
|
||||
p, err := a.projectCtl.Get(ctx, projectNameOrID, options...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package handler
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/goharbor/harbor/src/common/rbac"
|
||||
"github.com/goharbor/harbor/src/common/utils"
|
||||
"github.com/goharbor/harbor/src/controller/project"
|
||||
"github.com/goharbor/harbor/src/controller/robot"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
|
@ -20,8 +22,6 @@ import (
|
|||
handler_model "github.com/goharbor/harbor/src/server/v2.0/handler/model"
|
||||
"github.com/goharbor/harbor/src/server/v2.0/models"
|
||||
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/robotv1"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func newRobotV1API() *robotV1API {
|
||||
|
@ -40,7 +40,8 @@ type robotV1API struct {
|
|||
}
|
||||
|
||||
func (rAPI *robotV1API) CreateRobotV1(ctx context.Context, params operation.CreateRobotV1Params) middleware.Responder {
|
||||
if err := rAPI.RequireProjectAccess(ctx, params.ProjectIDOrName, rbac.ActionCreate, rbac.ResourceRobot); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := rAPI.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionCreate, rbac.ResourceRobot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
|
@ -57,19 +58,11 @@ func (rAPI *robotV1API) CreateRobotV1(ctx context.Context, params operation.Crea
|
|||
Level: robot.LEVELPROJECT,
|
||||
}
|
||||
|
||||
projectID, projectName, err := utils.ParseProjectIDOrName(params.ProjectIDOrName)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if projectID != 0 {
|
||||
p, err := project.Ctl.Get(ctx, projectID)
|
||||
projectName, ok := projectNameOrID.(string)
|
||||
if !ok {
|
||||
p, err := rAPI.projectCtr.Get(ctx, projectNameOrID, project.Metadata(false))
|
||||
if err != nil {
|
||||
log.Errorf("failed to get project %s: %v", projectName, err)
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
if p == nil {
|
||||
log.Warningf("project %s not found", projectName)
|
||||
log.Errorf("failed to get project %s: %v", projectNameOrID, err)
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
projectName = p.Name
|
||||
|
@ -116,11 +109,12 @@ func (rAPI *robotV1API) CreateRobotV1(ctx context.Context, params operation.Crea
|
|||
}
|
||||
|
||||
func (rAPI *robotV1API) DeleteRobotV1(ctx context.Context, params operation.DeleteRobotV1Params) middleware.Responder {
|
||||
if err := rAPI.RequireProjectAccess(ctx, params.ProjectIDOrName, rbac.ActionDelete, rbac.ResourceRobot); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := rAPI.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionDelete, rbac.ResourceRobot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
pro, err := rAPI.projectCtr.Get(ctx, params.ProjectIDOrName)
|
||||
pro, err := rAPI.projectCtr.Get(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
@ -142,7 +136,8 @@ func (rAPI *robotV1API) DeleteRobotV1(ctx context.Context, params operation.Dele
|
|||
}
|
||||
|
||||
func (rAPI *robotV1API) ListRobotV1(ctx context.Context, params operation.ListRobotV1Params) middleware.Responder {
|
||||
if err := rAPI.RequireProjectAccess(ctx, params.ProjectIDOrName, rbac.ActionList, rbac.ResourceRobot); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := rAPI.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionList, rbac.ResourceRobot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
|
@ -151,7 +146,7 @@ func (rAPI *robotV1API) ListRobotV1(ctx context.Context, params operation.ListRo
|
|||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
pro, err := rAPI.projectCtr.Get(ctx, params.ProjectIDOrName)
|
||||
pro, err := rAPI.projectCtr.Get(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
@ -182,11 +177,12 @@ func (rAPI *robotV1API) ListRobotV1(ctx context.Context, params operation.ListRo
|
|||
}
|
||||
|
||||
func (rAPI *robotV1API) GetRobotByIDV1(ctx context.Context, params operation.GetRobotByIDV1Params) middleware.Responder {
|
||||
if err := rAPI.RequireProjectAccess(ctx, params.ProjectIDOrName, rbac.ActionRead, rbac.ResourceRobot); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := rAPI.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionRead, rbac.ResourceRobot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
pro, err := rAPI.projectCtr.Get(ctx, params.ProjectIDOrName)
|
||||
pro, err := rAPI.projectCtr.Get(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
@ -205,11 +201,12 @@ func (rAPI *robotV1API) GetRobotByIDV1(ctx context.Context, params operation.Get
|
|||
}
|
||||
|
||||
func (rAPI *robotV1API) UpdateRobotV1(ctx context.Context, params operation.UpdateRobotV1Params) middleware.Responder {
|
||||
if err := rAPI.RequireProjectAccess(ctx, params.ProjectIDOrName, rbac.ActionUpdate, rbac.ResourceRobot); err != nil {
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
if err := rAPI.RequireProjectAccess(ctx, projectNameOrID, rbac.ActionUpdate, rbac.ResourceRobot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
pro, err := rAPI.projectCtr.Get(ctx, params.ProjectIDOrName)
|
||||
pro, err := rAPI.projectCtr.Get(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
@ -251,7 +248,8 @@ func (rAPI *robotV1API) validate(ctx context.Context, params operation.CreateRob
|
|||
return errors.New(nil).WithMessage("bad request no access").WithCode(errors.BadRequestCode)
|
||||
}
|
||||
|
||||
pro, err := rAPI.projectCtr.Get(ctx, params.ProjectIDOrName)
|
||||
projectNameOrID := parseProjectNameOrID(params.ProjectNameOrID, params.XIsResourceName)
|
||||
pro, err := rAPI.projectCtr.Get(ctx, projectNameOrID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -267,7 +265,7 @@ func (rAPI *robotV1API) validate(ctx context.Context, params operation.CreateRob
|
|||
p := &types.Policy{}
|
||||
lib.JSONCopy(p, policy)
|
||||
if !mp[p.String()] {
|
||||
return errors.New(nil).WithMessage("%s action of %s resource not exist in project %s", policy.Action, policy.Resource, params.ProjectIDOrName).WithCode(errors.BadRequestCode)
|
||||
return errors.New(nil).WithMessage("%s action of %s resource not exist in project %s", policy.Action, policy.Resource, projectNameOrID).WithCode(errors.BadRequestCode)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,12 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/goharbor/harbor/src/controller/artifact"
|
||||
"github.com/goharbor/harbor/src/controller/artifact/processor"
|
||||
"github.com/goharbor/harbor/src/controller/scan"
|
||||
"github.com/goharbor/harbor/src/lib"
|
||||
"github.com/goharbor/harbor/src/lib/log"
|
||||
"github.com/goharbor/harbor/src/pkg/scan/report"
|
||||
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
|
||||
|
@ -126,3 +128,18 @@ func unescapePathParams(params interface{}, fieldNames ...string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseProjectNameOrID(str string, isResourceName *bool) interface{} {
|
||||
if lib.BoolValue(isResourceName) {
|
||||
// always as projectName
|
||||
return str
|
||||
}
|
||||
|
||||
v, err := strconv.ParseInt(str, 10, 64)
|
||||
if err != nil {
|
||||
// it's projectName
|
||||
return str
|
||||
}
|
||||
|
||||
return v // projectID
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue