Просмотр исходного кода

use project roles instead of legacy roles

Mohammed Nafees 3 лет назад
Родитель
Сommit
31535cad96

+ 32 - 20
api/server/authz/policy/loader.go

@@ -23,12 +23,12 @@ type PolicyDocumentLoader interface {
 
 // RepoPolicyDocumentLoader loads policy documents by reading from the repository database
 type RepoPolicyDocumentLoader struct {
-	projRepo   repository.ProjectRepository
-	policyRepo repository.PolicyRepository
+	projRoleRepo repository.ProjectRoleRepository
+	policyRepo   repository.PolicyRepository
 }
 
-func NewBasicPolicyDocumentLoader(projRepo repository.ProjectRepository, policyRepo repository.PolicyRepository) *RepoPolicyDocumentLoader {
-	return &RepoPolicyDocumentLoader{projRepo, policyRepo}
+func NewBasicPolicyDocumentLoader(projRoleRepo repository.ProjectRoleRepository, policyRepo repository.PolicyRepository) *RepoPolicyDocumentLoader {
+	return &RepoPolicyDocumentLoader{projRoleRepo, policyRepo}
 }
 
 func (b *RepoPolicyDocumentLoader) LoadPolicyDocuments(
@@ -51,30 +51,42 @@ func (b *RepoPolicyDocumentLoader) LoadPolicyDocuments(
 	} else if opts.ProjectID != 0 && opts.UserID != 0 {
 		userID := opts.UserID
 		projectID := opts.ProjectID
-		// read role and case on role "kind"
-		role, err := b.projRepo.ReadProjectRole(projectID, userID)
 
-		if err != nil && err == gorm.ErrRecordNotFound {
+		roles, err := b.projRoleRepo.ListAllRolesForUser(projectID, userID)
+
+		if err != nil {
+			return nil, apierrors.NewErrInternal(err)
+		} else if len(roles) == 0 {
 			return nil, apierrors.NewErrForbidden(
-				fmt.Errorf("user %d does not have a role in project %d", userID, projectID),
+				fmt.Errorf("user does not have any roles assigned in this project"),
 			)
-		} else if err != nil {
-			return nil, apierrors.NewErrInternal(err)
 		}
 
-		// load role based on role kind
-		switch role.Kind {
-		case types.RoleAdmin:
-			return types.AdminPolicy, nil
-		case types.RoleDeveloper:
-			return types.DeveloperPolicy, nil
-		case types.RoleViewer:
-			return types.ViewerPolicy, nil
-		default:
+		var policies []*types.PolicyDocument
+
+		for _, role := range roles {
+			policy, err := b.policyRepo.ReadPolicy(projectID, role.PolicyUID)
+
+			if err != nil {
+				return nil, apierrors.NewErrInternal(err)
+			}
+
+			policyType, err := policy.ToAPIPolicyType()
+
+			if err != nil {
+				return nil, apierrors.NewErrInternal(err)
+			}
+
+			policies = append(policies, policyType.Policy...)
+		}
+
+		if len(policies) == 0 {
 			return nil, apierrors.NewErrForbidden(
-				fmt.Errorf("%s role not supported for user %d, project %d", string(role.Kind), userID, projectID),
+				fmt.Errorf("user does not have any roles assigned in this project"),
 			)
 		}
+
+		return policies, nil
 	}
 
 	return nil, apierrors.NewErrForbidden(

+ 1 - 1
api/server/handlers/project/get_policy.go

@@ -30,7 +30,7 @@ func (p *ProjectGetPolicyHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
 	user, _ := r.Context().Value(types.UserScope).(*models.User)
 	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 
-	policyDocLoader := policy.NewBasicPolicyDocumentLoader(p.Config().Repo.Project(), p.Config().Repo.Policy())
+	policyDocLoader := policy.NewBasicPolicyDocumentLoader(p.Config().Repo.ProjectRole(), p.Config().Repo.Policy())
 
 	policyDocs, err := policyDocLoader.LoadPolicyDocuments(&policy.PolicyLoaderOpts{
 		UserID:    user.ID,

+ 1 - 1
api/server/router/router.go

@@ -223,7 +223,7 @@ func registerRoutes(config *config.Config, routes []*router.Route) {
 	stackFactory := authz.NewStackScopedFactory(config)
 
 	// Policy doc loader loads the policy documents for a specific project.
-	policyDocLoader := policy.NewBasicPolicyDocumentLoader(config.Repo.Project(), config.Repo.Policy())
+	policyDocLoader := policy.NewBasicPolicyDocumentLoader(config.Repo.ProjectRole(), config.Repo.Policy())
 
 	// set up logging middleware to log information about the request
 	loggerMw := middleware.NewRequestLoggerMiddleware(config.Logger)

+ 20 - 0
internal/repository/gorm/project_role.go

@@ -45,6 +45,26 @@ func (repo *ProjectRoleRepository) ListProjectRoles(projectID uint) ([]*models.P
 	return roles, nil
 }
 
+func (repo *ProjectRoleRepository) ListAllRolesForUser(projectID, userID uint) ([]*models.ProjectRole, error) {
+	projectRoles := []*models.ProjectRole{}
+
+	if err := repo.db.Where("project_id = ?", userID).Find(&projectRoles).Error; err != nil {
+		return nil, err
+	}
+
+	var res []*models.ProjectRole
+
+	for _, role := range projectRoles {
+		if count := repo.db.Model(role).Where("id = ?", userID).Association("Users").Count(); count == 0 {
+			continue
+		} else {
+			res = append(res, role)
+		}
+	}
+
+	return res, nil
+}
+
 func (repo *ProjectRoleRepository) UpdateUsersInProjectRole(projectID uint, roleUID string, userIDs []uint) error {
 	users := []*models.User{}
 

+ 1 - 0
internal/repository/project_role.go

@@ -7,6 +7,7 @@ type ProjectRoleRepository interface {
 	CreateProjectRole(role *models.ProjectRole) (*models.ProjectRole, error)
 	ReadProjectRole(projectID uint, roleUID string) (*models.ProjectRole, error)
 	ListProjectRoles(projectID uint) ([]*models.ProjectRole, error)
+	ListAllRolesForUser(projectID, userID uint) ([]*models.ProjectRole, error)
 	UpdateUsersInProjectRole(projectID uint, roleUID string, userIDs []uint) error
 	UpdateProjectRole(role *models.ProjectRole) (*models.ProjectRole, error)
 	DeleteProjectRole(role *models.ProjectRole) (*models.ProjectRole, error)

+ 4 - 0
internal/repository/test/project_role.go

@@ -24,6 +24,10 @@ func (repo *ProjectRoleRepository) ListProjectRoles(projectID uint) ([]*models.P
 	panic("not implemented")
 }
 
+func (repo *ProjectRoleRepository) ListAllRolesForUser(projectID, userID uint) ([]*models.ProjectRole, error) {
+	panic("not implemented")
+}
+
 func (repo *ProjectRoleRepository) UpdateUsersInProjectRole(projectID uint, roleUID string, userIDs []uint) error {
 	panic("not implemented")
 }

+ 5 - 0
internal/repository/test/repository.go

@@ -8,6 +8,7 @@ type TestRepository struct {
 	user                      repository.UserRepository
 	session                   repository.SessionRepository
 	project                   repository.ProjectRepository
+	projectRole               repository.ProjectRoleRepository
 	cluster                   repository.ClusterRepository
 	helmRepo                  repository.HelmRepoRepository
 	registry                  repository.RegistryRepository
@@ -60,6 +61,10 @@ func (t *TestRepository) Project() repository.ProjectRepository {
 	return t.project
 }
 
+func (t *TestRepository) ProjectRole() repository.ProjectRoleRepository {
+	return t.projectRole
+}
+
 func (t *TestRepository) Cluster() repository.ClusterRepository {
 	return t.cluster
 }