mirror of https://github.com/goharbor/harbor.git
				
				
				
			add permission api (#19543)
The permission api targets to return the full set of permissons for robot to use. And only system and project admin have the access Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
		
							parent
							
								
									da949bfc3f
								
							
						
					
					
						commit
						5c02fd807e
					
				| 
						 | 
					@ -6140,7 +6140,31 @@ paths:
 | 
				
			||||||
        '401':
 | 
					        '401':
 | 
				
			||||||
          $ref: '#/responses/401'
 | 
					          $ref: '#/responses/401'
 | 
				
			||||||
        '500':
 | 
					        '500':
 | 
				
			||||||
          $ref: '#/responses/500'          
 | 
					          $ref: '#/responses/500'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /permissions:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      summary: Get system or project level permissions info.
 | 
				
			||||||
 | 
					      operationId: getPermissions
 | 
				
			||||||
 | 
					      description: |
 | 
				
			||||||
 | 
					        This endpoint is for retrieving resource and action info that only provides for admin user(system admin and project admin).
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - permissions
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - $ref: '#/parameters/requestId'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        '200':
 | 
				
			||||||
 | 
					          description: Get permissions successfully.
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            $ref: '#/definitions/Permissions'
 | 
				
			||||||
 | 
					        '401':
 | 
				
			||||||
 | 
					          $ref: '#/responses/401'
 | 
				
			||||||
 | 
					        '403':
 | 
				
			||||||
 | 
					          $ref: '#/responses/403'
 | 
				
			||||||
 | 
					        '404':
 | 
				
			||||||
 | 
					          $ref: '#/responses/404'
 | 
				
			||||||
 | 
					        '500':
 | 
				
			||||||
 | 
					          $ref: '#/responses/500'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
parameters:
 | 
					parameters:
 | 
				
			||||||
  query:
 | 
					  query:
 | 
				
			||||||
| 
						 | 
					@ -9397,6 +9421,19 @@ definitions:
 | 
				
			||||||
      action:
 | 
					      action:
 | 
				
			||||||
        type: string
 | 
					        type: string
 | 
				
			||||||
        description: The permission action
 | 
					        description: The permission action
 | 
				
			||||||
 | 
					  Permissions:
 | 
				
			||||||
 | 
					    type: object
 | 
				
			||||||
 | 
					    properties:
 | 
				
			||||||
 | 
					      system:
 | 
				
			||||||
 | 
					        type: array
 | 
				
			||||||
 | 
					        description: The system level permissions
 | 
				
			||||||
 | 
					        items:
 | 
				
			||||||
 | 
					          $ref: '#/definitions/Permission'
 | 
				
			||||||
 | 
					      project:
 | 
				
			||||||
 | 
					        type: array
 | 
				
			||||||
 | 
					        description: The project level permissions
 | 
				
			||||||
 | 
					        items:
 | 
				
			||||||
 | 
					          $ref: '#/definitions/Permission'
 | 
				
			||||||
  OIDCCliSecretReq:
 | 
					  OIDCCliSecretReq:
 | 
				
			||||||
    type: object
 | 
					    type: object
 | 
				
			||||||
    properties:
 | 
					    properties:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package rbac
 | 
					package rbac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/goharbor/harbor/src/pkg/permission/types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// const action variables
 | 
					// const action variables
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ActionAll = Action("*") // action match any other actions
 | 
						ActionAll = Action("*") // action match any other actions
 | 
				
			||||||
| 
						 | 
					@ -77,3 +79,150 @@ const (
 | 
				
			||||||
	ResourceJobServiceMonitor  = Resource("jobservice-monitor")
 | 
						ResourceJobServiceMonitor  = Resource("jobservice-monitor")
 | 
				
			||||||
	ResourceSecurityHub        = Resource("security-hub")
 | 
						ResourceSecurityHub        = Resource("security-hub")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						PoliciesMap = map[string][]*types.Policy{
 | 
				
			||||||
 | 
							"System": {
 | 
				
			||||||
 | 
								{Resource: ResourceAuditLog, Action: ActionList},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceProject, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceProject, Action: ActionCreate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationPolicy, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationPolicy, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationPolicy, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationPolicy, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationPolicy, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceReplication, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceReplication, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceReplication, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceReplication, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceReplication, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceReplicationAdapter, Action: ActionList},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceScanAll, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceScanAll, Action: ActionUpdate},
 | 
				
			||||||
 | 
								{Resource: ResourceScanAll, Action: ActionStop},
 | 
				
			||||||
 | 
								{Resource: ResourceScanAll, Action: ActionCreate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceSystemVolumes, Action: ActionRead},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionUpdate},
 | 
				
			||||||
 | 
								{Resource: ResourceGarbageCollection, Action: ActionStop},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionUpdate},
 | 
				
			||||||
 | 
								{Resource: ResourcePurgeAuditLog, Action: ActionStop},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceJobServiceMonitor, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceJobServiceMonitor, Action: ActionStop},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceTagRetention, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceTagRetention, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceTagRetention, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceTagRetention, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceTagRetention, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceLabel, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceLabel, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceLabel, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceLabel, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceLabel, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceExportCVE, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceExportCVE, Action: ActionCreate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceSecurityHub, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceSecurityHub, Action: ActionList},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceCatalog, Action: ActionRead},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Project": {
 | 
				
			||||||
 | 
								{Resource: ResourceLog, Action: ActionList},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceProject, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceProject, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceProject, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceMetadata, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceMetadata, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceMetadata, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceMetadata, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceMetadata, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceRepository, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceRepository, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceRepository, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceRepository, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceArtifact, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceArtifact, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceArtifact, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceArtifact, Action: ActionDelete},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceScan, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceScan, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceScan, Action: ActionStop},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceTag, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceTag, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceTag, Action: ActionDelete},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceAccessory, Action: ActionList},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceArtifactAddition, Action: ActionCreate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceArtifactLabel, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceArtifactLabel, Action: ActionDelete},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceScanner, Action: ActionRead},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourcePreatPolicy, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceImmutableTag, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceImmutableTag, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceImmutableTag, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceImmutableTag, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceNotificationPolicy, Action: ActionRead},
 | 
				
			||||||
 | 
								{Resource: ResourceNotificationPolicy, Action: ActionCreate},
 | 
				
			||||||
 | 
								{Resource: ResourceNotificationPolicy, Action: ActionDelete},
 | 
				
			||||||
 | 
								{Resource: ResourceNotificationPolicy, Action: ActionList},
 | 
				
			||||||
 | 
								{Resource: ResourceNotificationPolicy, Action: ActionUpdate},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{Resource: ResourceRegistry, Action: ActionPush},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,18 +32,20 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Controller defines the operation related to project member
 | 
					// Controller defines the operation related to project member
 | 
				
			||||||
type Controller interface {
 | 
					type Controller interface {
 | 
				
			||||||
	// Get get the project member with ID
 | 
						// Get gets the project member with ID
 | 
				
			||||||
	Get(ctx context.Context, projectNameOrID interface{}, memberID int) (*models.Member, error)
 | 
						Get(ctx context.Context, projectNameOrID interface{}, memberID int) (*models.Member, error)
 | 
				
			||||||
	// Create add project member to project
 | 
						// Create add project member to project
 | 
				
			||||||
	Create(ctx context.Context, projectNameOrID interface{}, req Request) (int, error)
 | 
						Create(ctx context.Context, projectNameOrID interface{}, req Request) (int, error)
 | 
				
			||||||
	// Delete member from project
 | 
						// Delete member from project
 | 
				
			||||||
	Delete(ctx context.Context, projectNameOrID interface{}, memberID int) error
 | 
						Delete(ctx context.Context, projectNameOrID interface{}, memberID int) error
 | 
				
			||||||
	// List list all project members with condition
 | 
						// List lists all project members with condition
 | 
				
			||||||
	List(ctx context.Context, projectNameOrID interface{}, entityName string, query *q.Query) ([]*models.Member, error)
 | 
						List(ctx context.Context, projectNameOrID interface{}, entityName string, query *q.Query) ([]*models.Member, error)
 | 
				
			||||||
	// UpdateRole update the project member role
 | 
						// UpdateRole update the project member role
 | 
				
			||||||
	UpdateRole(ctx context.Context, projectNameOrID interface{}, memberID int, role int) error
 | 
						UpdateRole(ctx context.Context, projectNameOrID interface{}, memberID int, role int) error
 | 
				
			||||||
	// Count get the total amount of project members
 | 
						// Count get the total amount of project members
 | 
				
			||||||
	Count(ctx context.Context, projectNameOrID interface{}, query *q.Query) (int, error)
 | 
						Count(ctx context.Context, projectNameOrID interface{}, query *q.Query) (int, error)
 | 
				
			||||||
 | 
						// IsProjectAdmin judges if the user is a project admin of any project
 | 
				
			||||||
 | 
						IsProjectAdmin(ctx context.Context, memberID int) (bool, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Request - Project Member Request
 | 
					// Request - Project Member Request
 | 
				
			||||||
| 
						 | 
					@ -258,3 +260,12 @@ func (c *controller) Delete(ctx context.Context, projectNameOrID interface{}, me
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return c.mgr.Delete(ctx, p.ProjectID, memberID)
 | 
						return c.mgr.Delete(ctx, p.ProjectID, memberID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *controller) IsProjectAdmin(ctx context.Context, memberID int) (bool, error) {
 | 
				
			||||||
 | 
						members, err := c.projectMgr.ListAdminRolesOfUser(ctx, memberID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return len(members) > 0, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
package member
 | 
					package member
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,6 +96,13 @@ func (suite *MemberControllerTestSuite) TestAddProjectMemberWithUserGroup() {
 | 
				
			||||||
	suite.NoError(err)
 | 
						suite.NoError(err)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (suite *MemberControllerTestSuite) TestIsProjectAdmin() {
 | 
				
			||||||
 | 
						mock.OnAnything(suite.projectMgr, "ListAdminRolesOfUser").Return([]models.Member{models.Member{ID: 2, ProjectID: 2}}, nil)
 | 
				
			||||||
 | 
						ok, err := suite.controller.IsProjectAdmin(context.Background(), 2)
 | 
				
			||||||
 | 
						suite.NoError(err)
 | 
				
			||||||
 | 
						suite.True(ok)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMemberControllerTestSuite(t *testing.T) {
 | 
					func TestMemberControllerTestSuite(t *testing.T) {
 | 
				
			||||||
	suite.Run(t, &MemberControllerTestSuite{})
 | 
						suite.Run(t, &MemberControllerTestSuite{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,10 @@ func (m *Manager) ListRoles(ctx context.Context, projectID int64, userID int, gr
 | 
				
			||||||
	return m.delegator.ListRoles(ctx, projectID, userID, groupIDs...)
 | 
						return m.delegator.ListRoles(ctx, projectID, userID, groupIDs...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Manager) ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error) {
 | 
				
			||||||
 | 
						return m.delegator.ListAdminRolesOfUser(ctx, userID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Delete(ctx context.Context, id int64) error {
 | 
					func (m *Manager) Delete(ctx context.Context, id int64) error {
 | 
				
			||||||
	p, err := m.Get(ctx, id)
 | 
						p, err := m.Get(ctx, id)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,20 +28,22 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DAO is the data access object interface for project
 | 
					// DAO is the data access object interface for project
 | 
				
			||||||
type DAO interface {
 | 
					type DAO interface {
 | 
				
			||||||
	// Create create a project instance
 | 
						// Create creates a project instance
 | 
				
			||||||
	Create(ctx context.Context, project *models.Project) (int64, error)
 | 
						Create(ctx context.Context, project *models.Project) (int64, error)
 | 
				
			||||||
	// Count returns the total count of projects according to the query
 | 
						// Count returns the total count of projects according to the query
 | 
				
			||||||
	Count(ctx context.Context, query *q.Query) (total int64, err error)
 | 
						Count(ctx context.Context, query *q.Query) (total int64, err error)
 | 
				
			||||||
	// Delete delete the project instance by id
 | 
						// Delete deletes the project instance by id
 | 
				
			||||||
	Delete(ctx context.Context, id int64) error
 | 
						Delete(ctx context.Context, id int64) error
 | 
				
			||||||
	// Get get project instance by id
 | 
						// Get gets project instance by id
 | 
				
			||||||
	Get(ctx context.Context, id int64) (*models.Project, error)
 | 
						Get(ctx context.Context, id int64) (*models.Project, error)
 | 
				
			||||||
	// GetByName get project instance by name
 | 
						// GetByName get project instance by name
 | 
				
			||||||
	GetByName(ctx context.Context, name string) (*models.Project, error)
 | 
						GetByName(ctx context.Context, name string) (*models.Project, error)
 | 
				
			||||||
	// List list projects
 | 
						// List lists projects
 | 
				
			||||||
	List(ctx context.Context, query *q.Query) ([]*models.Project, error)
 | 
						List(ctx context.Context, query *q.Query) ([]*models.Project, error)
 | 
				
			||||||
	// Lists the roles of user for the specific project
 | 
						// ListRoles the roles of user for the specific project
 | 
				
			||||||
	ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error)
 | 
						ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error)
 | 
				
			||||||
 | 
						// ListAdminRolesOfUser returns the roles of user for the all projects
 | 
				
			||||||
 | 
						ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New returns an instance of the default DAO
 | 
					// New returns an instance of the default DAO
 | 
				
			||||||
| 
						 | 
					@ -51,7 +53,7 @@ func New() DAO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type dao struct{}
 | 
					type dao struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create create a project instance
 | 
					// Create creates a project instance
 | 
				
			||||||
func (d *dao) Create(ctx context.Context, project *models.Project) (int64, error) {
 | 
					func (d *dao) Create(ctx context.Context, project *models.Project) (int64, error) {
 | 
				
			||||||
	var projectID int64
 | 
						var projectID int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +107,7 @@ func (d *dao) Count(ctx context.Context, query *q.Query) (total int64, err error
 | 
				
			||||||
	return qs.Count()
 | 
						return qs.Count()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Delete delete the project instance by id
 | 
					// Delete deletes the project instance by id
 | 
				
			||||||
func (d *dao) Delete(ctx context.Context, id int64) error {
 | 
					func (d *dao) Delete(ctx context.Context, id int64) error {
 | 
				
			||||||
	project, err := d.Get(ctx, id)
 | 
						project, err := d.Get(ctx, id)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -124,7 +126,7 @@ func (d *dao) Delete(ctx context.Context, id int64) error {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get get project instance by id
 | 
					// Get gets project instance by id
 | 
				
			||||||
func (d *dao) Get(ctx context.Context, id int64) (*models.Project, error) {
 | 
					func (d *dao) Get(ctx context.Context, id int64) (*models.Project, error) {
 | 
				
			||||||
	o, err := orm.FromContext(ctx)
 | 
						o, err := orm.FromContext(ctx)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -199,3 +201,20 @@ func (d *dao) ListRoles(ctx context.Context, projectID int64, userID int, groupI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return roles, nil
 | 
						return roles, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *dao) ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error) {
 | 
				
			||||||
 | 
						o, err := orm.FromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sql := `select b.* from project as a left join project_member as b on a.project_id = b.project_id where a.deleted = 'f' and b.entity_id = ? and b.entity_type = 'u' and b.role = 1;`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var members []models.Member
 | 
				
			||||||
 | 
						_, err = o.Raw(sql, userID).QueryRows(&members)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return members, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,13 +28,13 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Manager is used for project management
 | 
					// Manager is used for project management
 | 
				
			||||||
type Manager interface {
 | 
					type Manager interface {
 | 
				
			||||||
	// Create create project instance
 | 
						// Create creates project instance
 | 
				
			||||||
	Create(ctx context.Context, project *models.Project) (int64, error)
 | 
						Create(ctx context.Context, project *models.Project) (int64, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Count returns the total count of projects according to the query
 | 
						// Count returns the total count of projects according to the query
 | 
				
			||||||
	Count(ctx context.Context, query *q.Query) (total int64, err error)
 | 
						Count(ctx context.Context, query *q.Query) (total int64, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete delete the project instance by id
 | 
						// Delete deletes the project instance by id
 | 
				
			||||||
	Delete(ctx context.Context, id int64) error
 | 
						Delete(ctx context.Context, id int64) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the project specified by the ID or name
 | 
						// Get the project specified by the ID or name
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,9 @@ type Manager interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ListRoles returns the roles of user for the specific project
 | 
						// ListRoles returns the roles of user for the specific project
 | 
				
			||||||
	ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error)
 | 
						ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ListAdminRolesOfUser returns the roles of user for the all projects
 | 
				
			||||||
 | 
						ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New returns a default implementation of Manager
 | 
					// New returns a default implementation of Manager
 | 
				
			||||||
| 
						 | 
					@ -64,7 +67,7 @@ type manager struct {
 | 
				
			||||||
	dao dao.DAO
 | 
						dao dao.DAO
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create create project instance
 | 
					// Create creates project instance
 | 
				
			||||||
func (m *manager) Create(ctx context.Context, project *models.Project) (int64, error) {
 | 
					func (m *manager) Create(ctx context.Context, project *models.Project) (int64, error) {
 | 
				
			||||||
	if project.OwnerID <= 0 {
 | 
						if project.OwnerID <= 0 {
 | 
				
			||||||
		return 0, errors.BadRequestError(nil).WithMessage("Owner is missing when creating project %s", project.Name)
 | 
							return 0, errors.BadRequestError(nil).WithMessage("Owner is missing when creating project %s", project.Name)
 | 
				
			||||||
| 
						 | 
					@ -115,7 +118,12 @@ func (m *manager) List(ctx context.Context, query *q.Query) ([]*models.Project,
 | 
				
			||||||
	return m.dao.List(ctx, query)
 | 
						return m.dao.List(ctx, query)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Lists the roles of user for the specific project
 | 
					// ListRoles the roles of user for the specific project
 | 
				
			||||||
func (m *manager) ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error) {
 | 
					func (m *manager) ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error) {
 | 
				
			||||||
	return m.dao.ListRoles(ctx, projectID, userID, groupIDs...)
 | 
						return m.dao.ListRoles(ctx, projectID, userID, groupIDs...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListAdminRolesOfUser returns the roles of user for the all projects
 | 
				
			||||||
 | 
					func (m *manager) ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error) {
 | 
				
			||||||
 | 
						return m.dao.ListAdminRolesOfUser(ctx, userID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,6 +70,7 @@ func New() http.Handler {
 | 
				
			||||||
		JobserviceAPI:         newJobServiceAPI(),
 | 
							JobserviceAPI:         newJobServiceAPI(),
 | 
				
			||||||
		ScheduleAPI:           newScheduleAPI(),
 | 
							ScheduleAPI:           newScheduleAPI(),
 | 
				
			||||||
		SecurityhubAPI:        newSecurityAPI(),
 | 
							SecurityhubAPI:        newSecurityAPI(),
 | 
				
			||||||
 | 
							PermissionsAPI:        newPermissionsAPIAPI(),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal(err)
 | 
							log.Fatal(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,109 @@
 | 
				
			||||||
 | 
					// 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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-openapi/runtime/middleware"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/common/rbac"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/common/security"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/controller/member"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/controller/user"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/lib/errors"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/pkg/permission/types"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/server/v2.0/models"
 | 
				
			||||||
 | 
						"github.com/goharbor/harbor/src/server/v2.0/restapi/operations/permissions"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type permissionsAPI struct {
 | 
				
			||||||
 | 
						BaseAPI
 | 
				
			||||||
 | 
						uc user.Controller
 | 
				
			||||||
 | 
						mc member.Controller
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newPermissionsAPIAPI() *permissionsAPI {
 | 
				
			||||||
 | 
						return &permissionsAPI{
 | 
				
			||||||
 | 
							uc: user.Ctl,
 | 
				
			||||||
 | 
							mc: member.NewController(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *permissionsAPI) GetPermissions(ctx context.Context, params permissions.GetPermissionsParams) middleware.Responder {
 | 
				
			||||||
 | 
						secCtx, ok := security.FromContext(ctx)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return p.SendError(ctx, errors.UnauthorizedError(errors.New("security context not found")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !secCtx.IsAuthenticated() {
 | 
				
			||||||
 | 
							return p.SendError(ctx, errors.UnauthorizedError(nil).WithMessage(secCtx.GetUsername()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var isSystemAdmin bool
 | 
				
			||||||
 | 
						var isProjectAdmin bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if secCtx.IsSysAdmin() {
 | 
				
			||||||
 | 
							isSystemAdmin = true
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							user, err := p.uc.GetByName(ctx, secCtx.GetUsername())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return p.SendError(ctx, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							is, err := p.mc.IsProjectAdmin(ctx, user.UserID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return p.SendError(ctx, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							isProjectAdmin = is
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !isSystemAdmin && !isProjectAdmin {
 | 
				
			||||||
 | 
							return p.SendError(ctx, errors.ForbiddenError(errors.New("only admins(system and project) can access permissions")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sysPermissions := make([]*types.Policy, 0)
 | 
				
			||||||
 | 
						proPermissions := rbac.PoliciesMap["Project"]
 | 
				
			||||||
 | 
						if isSystemAdmin {
 | 
				
			||||||
 | 
							// project admin cannot see the system level permissions
 | 
				
			||||||
 | 
							sysPermissions = rbac.PoliciesMap["System"]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return permissions.NewGetPermissionsOK().WithPayload(p.convertPermissions(sysPermissions, proPermissions))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *permissionsAPI) convertPermissions(system, project []*types.Policy) *models.Permissions {
 | 
				
			||||||
 | 
						res := &models.Permissions{}
 | 
				
			||||||
 | 
						if len(system) > 0 {
 | 
				
			||||||
 | 
							var sysPermission []*models.Permission
 | 
				
			||||||
 | 
							for _, item := range system {
 | 
				
			||||||
 | 
								sysPermission = append(sysPermission, &models.Permission{
 | 
				
			||||||
 | 
									Resource: item.Resource.String(),
 | 
				
			||||||
 | 
									Action:   item.Action.String(),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							res.System = sysPermission
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(project) > 0 {
 | 
				
			||||||
 | 
							var proPermission []*models.Permission
 | 
				
			||||||
 | 
							for _, item := range project {
 | 
				
			||||||
 | 
								proPermission = append(proPermission, &models.Permission{
 | 
				
			||||||
 | 
									Resource: item.Resource.String(),
 | 
				
			||||||
 | 
									Action:   item.Action.String(),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							res.Project = proPermission
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -130,6 +130,32 @@ func (_m *Manager) List(ctx context.Context, query *q.Query) ([]*models.Project,
 | 
				
			||||||
	return r0, r1
 | 
						return r0, r1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListAdminRolesOfUser provides a mock function with given fields: ctx, userID
 | 
				
			||||||
 | 
					func (_m *Manager) ListAdminRolesOfUser(ctx context.Context, userID int) ([]models.Member, error) {
 | 
				
			||||||
 | 
						ret := _m.Called(ctx, userID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var r0 []models.Member
 | 
				
			||||||
 | 
						var r1 error
 | 
				
			||||||
 | 
						if rf, ok := ret.Get(0).(func(context.Context, int) ([]models.Member, error)); ok {
 | 
				
			||||||
 | 
							return rf(ctx, userID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if rf, ok := ret.Get(0).(func(context.Context, int) []models.Member); ok {
 | 
				
			||||||
 | 
							r0 = rf(ctx, userID)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if ret.Get(0) != nil {
 | 
				
			||||||
 | 
								r0 = ret.Get(0).([]models.Member)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if rf, ok := ret.Get(1).(func(context.Context, int) error); ok {
 | 
				
			||||||
 | 
							r1 = rf(ctx, userID)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							r1 = ret.Error(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r0, r1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListRoles provides a mock function with given fields: ctx, projectID, userID, groupIDs
 | 
					// ListRoles provides a mock function with given fields: ctx, projectID, userID, groupIDs
 | 
				
			||||||
func (_m *Manager) ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error) {
 | 
					func (_m *Manager) ListRoles(ctx context.Context, projectID int64, userID int, groupIDs ...int) ([]int, error) {
 | 
				
			||||||
	_va := make([]interface{}, len(groupIDs))
 | 
						_va := make([]interface{}, len(groupIDs))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue