mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-02 13:01:23 +01:00
add robot account 2 api handler
Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
parent
9571af84bd
commit
8e61a3ea31
@ -1410,6 +1410,154 @@ paths:
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_id_or_name}/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/page'
|
||||
- $ref: '#/parameters/pageSize'
|
||||
- $ref: '#/parameters/query'
|
||||
tags:
|
||||
- robotv1
|
||||
operationId: ListRobotV1
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
headers:
|
||||
X-Total-Count:
|
||||
description: The total count of robot accounts
|
||||
type: integer
|
||||
Link:
|
||||
description: Link refers to the previous page and next page
|
||||
type: string
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Robot'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
post:
|
||||
summary: Create a robot account
|
||||
description: Create a robot account
|
||||
tags:
|
||||
- robotv1
|
||||
operationId: CreateRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- name: robot
|
||||
in: body
|
||||
description: The JSON object of a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotCreateV1'
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
headers:
|
||||
X-Request-Id:
|
||||
description: The ID of the corresponding request for the response
|
||||
type: string
|
||||
Location:
|
||||
description: The location of the resource
|
||||
type: string
|
||||
schema:
|
||||
$ref: '#/definitions/RobotCreated'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/projects/{project_id_or_name}/robots/{robot_id}:
|
||||
get:
|
||||
summary: Get a robot account
|
||||
description: This endpoint returns specific robot account information by robot ID.
|
||||
tags:
|
||||
- robotv1
|
||||
operationId: GetRobotByIDV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
description: Return matched robot information.
|
||||
schema:
|
||||
$ref: '#/definitions/Robot'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
put:
|
||||
summary: Update status of robot account.
|
||||
description: Used to disable/enable a specified robot account.
|
||||
tags:
|
||||
- robotv1
|
||||
operationId: UpdateRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/robotId'
|
||||
- name: robot
|
||||
in: body
|
||||
description: The JSON object of a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Robot'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'409':
|
||||
$ref: '#/responses/409'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
delete:
|
||||
summary: Delete a robot account
|
||||
description: This endpoint deletes specific robot account information by robot ID.
|
||||
tags:
|
||||
- robotv1
|
||||
operationId: DeleteRobotV1
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/projectIDOrName'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/icons/{digest}:
|
||||
get:
|
||||
summary: Get artifact icon
|
||||
@ -1431,6 +1579,149 @@ paths:
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/robots:
|
||||
get:
|
||||
summary: Get robot account
|
||||
description: List the robot accounts with the specified level and project.
|
||||
tags:
|
||||
- robot
|
||||
operationId: ListRobot
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/query'
|
||||
- $ref: '#/parameters/page'
|
||||
- $ref: '#/parameters/pageSize'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
headers:
|
||||
X-Total-Count:
|
||||
description: The total count of robot accounts
|
||||
type: integer
|
||||
Link:
|
||||
description: Link refers to the previous page and next page
|
||||
type: string
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Robot'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
post:
|
||||
summary: Create a robot account
|
||||
description: Create a robot account
|
||||
tags:
|
||||
- robot
|
||||
operationId: CreateRobot
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- name: robot
|
||||
in: body
|
||||
description: The JSON object of a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
headers:
|
||||
X-Request-Id:
|
||||
description: The ID of the corresponding request for the response
|
||||
type: string
|
||||
Location:
|
||||
description: The location of the resource
|
||||
type: string
|
||||
schema:
|
||||
$ref: '#/definitions/RobotCreated'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/robots/{robot_id}:
|
||||
get:
|
||||
summary: Get a robot account
|
||||
description: This endpoint returns specific robot account information by robot ID.
|
||||
tags:
|
||||
- robot
|
||||
operationId: GetRobotByID
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
description: Return matched robot information.
|
||||
schema:
|
||||
$ref: '#/definitions/Robot'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
put:
|
||||
summary: Update a robot account
|
||||
description: This endpoint updates specific robot account information by robot ID.
|
||||
tags:
|
||||
- robot
|
||||
operationId: UpdateRobot
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
- name: robot
|
||||
in: body
|
||||
description: The JSON object of a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotCreate'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'409':
|
||||
$ref: '#/responses/409'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
delete:
|
||||
summary: Delete a robot account
|
||||
description: This endpoint deletes specific robot account information by robot ID.
|
||||
tags:
|
||||
- robot
|
||||
operationId: DeleteRobot
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestId'
|
||||
- $ref: '#/parameters/robotId'
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/200'
|
||||
'400':
|
||||
$ref: '#/responses/400'
|
||||
'401':
|
||||
$ref: '#/responses/401'
|
||||
'403':
|
||||
$ref: '#/responses/403'
|
||||
'404':
|
||||
$ref: '#/responses/404'
|
||||
'500':
|
||||
$ref: '#/responses/500'
|
||||
/replication/executions:
|
||||
get:
|
||||
summary: List replication executions
|
||||
@ -1661,6 +1952,12 @@ parameters:
|
||||
required: true
|
||||
type: integer
|
||||
format: int64
|
||||
projectIDOrName:
|
||||
name: project_id_or_name
|
||||
in: path
|
||||
description: The id or name of the project
|
||||
required: true
|
||||
type: string
|
||||
repositoryName:
|
||||
name: repository_name
|
||||
in: path
|
||||
@ -1726,6 +2023,12 @@ parameters:
|
||||
description: Task ID
|
||||
required: true
|
||||
type: integer
|
||||
robotId:
|
||||
name: robot_id
|
||||
in: path
|
||||
description: Robot ID
|
||||
required: true
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
@ -2518,7 +2821,7 @@ definitions:
|
||||
$ref: "#/definitions/ResourceList"
|
||||
description: The used status of the quota
|
||||
registry:
|
||||
$ref: "#/definitions/Registry"
|
||||
$ref: "#/definitions/Registry"
|
||||
CVEAllowlist:
|
||||
type: object
|
||||
description: The CVE Allowlist for system or project
|
||||
@ -2693,3 +2996,129 @@ definitions:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The end time of the task
|
||||
Robot:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
description: The ID of the robot
|
||||
name:
|
||||
type: string
|
||||
description: The name of the tag
|
||||
description:
|
||||
type: string
|
||||
description: The description of the robot
|
||||
secret:
|
||||
type: string
|
||||
description: The secret of the robot
|
||||
level:
|
||||
type: string
|
||||
description: The level of the robot, project or system
|
||||
disable:
|
||||
type: boolean
|
||||
x-omitempty: false
|
||||
description: The disable status of the robot
|
||||
expires_at:
|
||||
type: integer
|
||||
format: int64
|
||||
description: The expiration data of the robot
|
||||
permissions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Permission'
|
||||
creation_time:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The creation time of the robot.
|
||||
update_time:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The update time of the robot.
|
||||
RobotCreate:
|
||||
type: object
|
||||
description: The request for robot account creation.
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The name of the tag
|
||||
description:
|
||||
type: string
|
||||
description: The description of the robot
|
||||
secret:
|
||||
type: string
|
||||
description: The secret of the robot
|
||||
level:
|
||||
type: string
|
||||
description: The level of the robot, project or system
|
||||
disable:
|
||||
type: boolean
|
||||
description: The disable status of the robot
|
||||
expires_at:
|
||||
type: integer
|
||||
format: int64
|
||||
description: The expiration data of the robot
|
||||
permissions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Permission'
|
||||
RobotCreated:
|
||||
type: object
|
||||
description: The response for robot account creation.
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
description: The ID of the robot
|
||||
name:
|
||||
type: string
|
||||
description: The name of the tag
|
||||
secret:
|
||||
type: string
|
||||
description: The secret of the robot
|
||||
creation_time:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The creation time of the robot.
|
||||
Permission:
|
||||
type: object
|
||||
properties:
|
||||
kind:
|
||||
type: string
|
||||
description: The kind of the permission
|
||||
namespace:
|
||||
type: string
|
||||
description: The namespace of the permission
|
||||
access:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Access'
|
||||
Access:
|
||||
type: object
|
||||
properties:
|
||||
resource:
|
||||
type: string
|
||||
description: The resource of the access
|
||||
action:
|
||||
type: string
|
||||
description: The action of the access
|
||||
effect:
|
||||
type: string
|
||||
description: The effect of the access
|
||||
RobotCreateV1:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The name of robot account
|
||||
description:
|
||||
type: string
|
||||
description: The description of robot account
|
||||
expires_at:
|
||||
type: integer
|
||||
description: The expiration time on or after which the JWT MUST NOT be accepted for processing.
|
||||
access:
|
||||
type: array
|
||||
description: The permission of robot account
|
||||
items:
|
||||
$ref: '#/definitions/Access'
|
||||
|
@ -37,9 +37,9 @@ func (eff Effect) String() string {
|
||||
|
||||
// Policy the type of policy
|
||||
type Policy struct {
|
||||
Resource
|
||||
Action
|
||||
Effect
|
||||
Resource `json:"resource,omitempty"`
|
||||
Action `json:"action,omitempty"`
|
||||
Effect `json:"effect,omitempty"`
|
||||
}
|
||||
|
||||
// GetEffect returns effect of resource, default is allow
|
||||
|
@ -36,6 +36,8 @@ func New() http.Handler {
|
||||
ProjectAPI: newProjectAPI(),
|
||||
PreheatAPI: newPreheatAPI(),
|
||||
IconAPI: newIconAPI(),
|
||||
RobotAPI: newRobotAPI(),
|
||||
Robotv1API: newRobotV1API(),
|
||||
ReplicationAPI: newReplicationAPI(),
|
||||
})
|
||||
if err != nil {
|
||||
|
41
src/server/v2.0/handler/model/robot.go
Normal file
41
src/server/v2.0/handler/model/robot.go
Normal file
@ -0,0 +1,41 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/goharbor/harbor/src/controller/robot"
|
||||
"github.com/goharbor/harbor/src/lib"
|
||||
"github.com/goharbor/harbor/src/server/v2.0/models"
|
||||
)
|
||||
|
||||
type Robot struct {
|
||||
*robot.Robot
|
||||
}
|
||||
|
||||
func (r *Robot) ToSwagger() *models.Robot {
|
||||
perms := []*models.Permission{}
|
||||
for _, p := range r.Permissions {
|
||||
temp := &models.Permission{}
|
||||
lib.JSONCopy(temp, p)
|
||||
perms = append(perms, temp)
|
||||
}
|
||||
|
||||
return &models.Robot{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
Description: r.Description,
|
||||
Secret: r.Secret,
|
||||
ExpiresAt: r.ExpiresAt,
|
||||
Level: r.Level,
|
||||
Disable: r.Disabled,
|
||||
CreationTime: strfmt.DateTime(r.CreationTime),
|
||||
UpdateTime: strfmt.DateTime(r.UpdateTime),
|
||||
Permissions: perms,
|
||||
}
|
||||
}
|
||||
|
||||
// NewRobot ...
|
||||
func NewRobot(r *robot.Robot) *Robot {
|
||||
return &Robot{
|
||||
Robot: r,
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ import (
|
||||
"github.com/goharbor/harbor/src/pkg/project/metadata"
|
||||
"github.com/goharbor/harbor/src/pkg/quota/types"
|
||||
"github.com/goharbor/harbor/src/pkg/retention/policy"
|
||||
"github.com/goharbor/harbor/src/pkg/robot"
|
||||
"github.com/goharbor/harbor/src/pkg/robot2"
|
||||
"github.com/goharbor/harbor/src/pkg/user"
|
||||
"github.com/goharbor/harbor/src/replication"
|
||||
"github.com/goharbor/harbor/src/server/v2.0/handler/model"
|
||||
@ -48,7 +48,7 @@ func newProjectAPI() *projectAPI {
|
||||
repositoryCtl: repository.Ctl,
|
||||
projectCtl: project.Ctl,
|
||||
quotaCtl: quota.Ctl,
|
||||
robotMgr: robot.Mgr,
|
||||
robotMgr: robot2.Mgr,
|
||||
preheatCtl: preheat.Ctl,
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ type projectAPI struct {
|
||||
repositoryCtl repository.Controller
|
||||
projectCtl project.Controller
|
||||
quotaCtl quota.Controller
|
||||
robotMgr robot.Manager
|
||||
robotMgr robot2.Manager
|
||||
preheatCtl preheat.Controller
|
||||
}
|
||||
|
||||
|
259
src/server/v2.0/handler/robot.go
Normal file
259
src/server/v2.0/handler/robot.go
Normal file
@ -0,0 +1,259 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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/robot"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
"github.com/goharbor/harbor/src/lib"
|
||||
"github.com/goharbor/harbor/src/lib/errors"
|
||||
pkg "github.com/goharbor/harbor/src/pkg/robot2/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/robot"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func newRobotAPI() *robotAPI {
|
||||
return &robotAPI{
|
||||
robotCtl: robot.Ctl,
|
||||
}
|
||||
}
|
||||
|
||||
type robotAPI struct {
|
||||
BaseAPI
|
||||
robotCtl robot.Controller
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) CreateRobot(ctx context.Context, params operation.CreateRobotParams) middleware.Responder {
|
||||
if err := rAPI.validate(params.Robot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if err := rAPI.requireAccess(ctx, params.Robot.Level, params.Robot.Permissions[0].Namespace, rbac.ActionCreate); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
r := &robot.Robot{
|
||||
Robot: pkg.Robot{
|
||||
Name: params.Robot.Name,
|
||||
Description: params.Robot.Description,
|
||||
ExpiresAt: params.Robot.ExpiresAt,
|
||||
},
|
||||
Level: params.Robot.Level,
|
||||
}
|
||||
lib.JSONCopy(&r.Permissions, params.Robot.Permissions)
|
||||
|
||||
rid, err := rAPI.robotCtl.Create(ctx, r)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
created, err := rAPI.robotCtl.Get(ctx, rid, nil)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
location := fmt.Sprintf("%s/%d", strings.TrimSuffix(params.HTTPRequest.URL.Path, "/"), created.ID)
|
||||
return operation.NewCreateRobotCreated().WithLocation(location).WithPayload(&models.RobotCreated{
|
||||
ID: created.ID,
|
||||
Name: created.Name,
|
||||
Secret: created.Secret,
|
||||
CreationTime: strfmt.DateTime(created.CreationTime),
|
||||
})
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) DeleteRobot(ctx context.Context, params operation.DeleteRobotParams) middleware.Responder {
|
||||
if err := rAPI.RequireAuthenticated(ctx); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
r, err := rAPI.robotCtl.Get(ctx, params.RobotID, nil)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if err := rAPI.requireAccess(ctx, r.Level, r.ProjectID, rbac.ActionDelete); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if err := rAPI.robotCtl.Delete(ctx, params.RobotID); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
return operation.NewDeleteRobotOK()
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) ListRobot(ctx context.Context, params operation.ListRobotParams) middleware.Responder {
|
||||
if err := rAPI.RequireAuthenticated(ctx); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
query, err := rAPI.BuildQuery(ctx, params.Q, params.Page, params.PageSize)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
var projectID int64
|
||||
var level string
|
||||
// GET /api/v2.0/robots or GET /api/v2.0/robots?level=system to get all of system level robots.
|
||||
// GET /api/v2.0/robots?level=project&project_id=1
|
||||
if _, ok := query.Keywords["Level"]; ok {
|
||||
if !isValidLevel(query.Keywords["Level"].(string)) {
|
||||
return rAPI.SendError(ctx, errors.New(nil).WithMessage("bad request error level input").WithCode(errors.BadRequestCode))
|
||||
}
|
||||
level = query.Keywords["Level"].(string)
|
||||
if level == robot.LEVELPROJECT {
|
||||
if _, ok := query.Keywords["ProjectID"]; !ok {
|
||||
return rAPI.SendError(ctx, errors.BadRequestError(nil).WithMessage("must with project ID when to query project robots"))
|
||||
}
|
||||
pid, err := strconv.ParseInt(query.Keywords["ProjectID"].(string), 10, 64)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, errors.BadRequestError(nil).WithMessage("Project ID must be int type."))
|
||||
}
|
||||
projectID = pid
|
||||
}
|
||||
|
||||
} else {
|
||||
level = robot.LEVELSYSTEM
|
||||
projectID = 0
|
||||
query.Keywords["ProjectID"] = 0
|
||||
}
|
||||
|
||||
if err := rAPI.requireAccess(ctx, level, projectID, rbac.ActionList); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
total, err := rAPI.robotCtl.Count(ctx, query)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
robots, err := rAPI.robotCtl.List(ctx, query, &robot.Option{
|
||||
WithPermission: true,
|
||||
})
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
var results []*models.Robot
|
||||
for _, r := range robots {
|
||||
results = append(results, model.NewRobot(r).ToSwagger())
|
||||
}
|
||||
|
||||
return operation.NewListRobotOK().
|
||||
WithXTotalCount(total).
|
||||
WithLink(rAPI.Links(ctx, params.HTTPRequest.URL, total, query.PageNumber, query.PageSize).String()).
|
||||
WithPayload(results)
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) GetRobotByID(ctx context.Context, params operation.GetRobotByIDParams) middleware.Responder {
|
||||
if err := rAPI.RequireAuthenticated(ctx); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
r, err := rAPI.robotCtl.Get(ctx, params.RobotID, &robot.Option{
|
||||
WithPermission: true,
|
||||
})
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if err := rAPI.requireAccess(ctx, r.Level, r.ProjectID, rbac.ActionRead); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
return operation.NewGetRobotByIDOK().WithPayload(model.NewRobot(r).ToSwagger())
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) UpdateRobot(ctx context.Context, params operation.UpdateRobotParams) middleware.Responder {
|
||||
if err := rAPI.validate(params.Robot); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if err := rAPI.requireAccess(ctx, params.Robot.Level, params.Robot.Permissions[0].Namespace, rbac.ActionUpdate); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
r, err := rAPI.robotCtl.Get(ctx, params.RobotID, &robot.Option{
|
||||
WithPermission: true,
|
||||
})
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
if params.Robot.Level != r.Level || params.Robot.Name != r.Name {
|
||||
return rAPI.SendError(ctx, errors.BadRequestError(nil).WithMessage("cannot update the level or name of robot"))
|
||||
}
|
||||
|
||||
// refresh secret only
|
||||
if params.Robot.Secret != r.Secret && params.Robot.Secret != "" {
|
||||
key, err := config.SecretKey()
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
secret, err := utils.ReversibleEncrypt(params.Robot.Secret, key)
|
||||
if err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
r.Secret = secret
|
||||
if err := rAPI.robotCtl.Update(ctx, r); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
r.Description = params.Robot.Description
|
||||
r.ExpiresAt = params.Robot.ExpiresAt
|
||||
r.Disabled = params.Robot.Disable
|
||||
if len(params.Robot.Permissions) != 0 {
|
||||
lib.JSONCopy(&r.Permissions, params.Robot.Permissions)
|
||||
}
|
||||
|
||||
if err := rAPI.robotCtl.Update(ctx, r); err != nil {
|
||||
return rAPI.SendError(ctx, err)
|
||||
}
|
||||
|
||||
return operation.NewUpdateRobotOK()
|
||||
}
|
||||
|
||||
func (rAPI *robotAPI) requireAccess(ctx context.Context, level string, projectIDOrName interface{}, action rbac.Action) error {
|
||||
if level == robot.LEVELSYSTEM {
|
||||
return rAPI.RequireSysAdmin(ctx)
|
||||
} else if level == robot.LEVELPROJECT {
|
||||
return rAPI.RequireProjectAccess(ctx, projectIDOrName, action, rbac.ResourceRobot)
|
||||
}
|
||||
return errors.ForbiddenError(nil)
|
||||
}
|
||||
|
||||
// more validation
|
||||
func (rAPI *robotAPI) validate(r *models.RobotCreate) error {
|
||||
if !isValidLevel(r.Level) {
|
||||
return errors.New(nil).WithMessage("bad request error level input").WithCode(errors.BadRequestCode)
|
||||
}
|
||||
|
||||
if len(r.Permissions) == 0 {
|
||||
return errors.New(nil).WithMessage("bad request empty permission").WithCode(errors.BadRequestCode)
|
||||
}
|
||||
|
||||
if r.Level == robot.LEVELPROJECT {
|
||||
// to create a project robot, the permission must be only one project scope.
|
||||
if len(r.Permissions) > 1 {
|
||||
return errors.New(nil).WithMessage("bad request permission").WithCode(errors.BadRequestCode)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isValidLevel(l string) bool {
|
||||
switch l {
|
||||
case
|
||||
robot.LEVELSYSTEM,
|
||||
robot.LEVELPROJECT:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user