Răsfoiți Sursa

add more validation

Mohammed Nafees 3 ani în urmă
părinte
comite
4bbbb26a94

+ 7 - 0
api/server/handlers/project_role/create.go

@@ -35,6 +35,13 @@ func (c *CreateProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 	user, _ := r.Context().Value(types.UserScope).(*models.User)
 
+	if !project.AdvancedRBACEnabled {
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
+			errors.New("advanced RBAC is not enabled for this project"), http.StatusPreconditionFailed,
+		))
+		return
+	}
+
 	request := &types.CreateProjectRoleRequest{}
 
 	if ok := c.DecodeAndValidate(w, r, request); !ok {

+ 7 - 0
api/server/handlers/project_role/delete.go

@@ -32,6 +32,13 @@ func NewDeleteProjectRoleHandler(
 func (c *DeleteProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 
+	if !project.AdvancedRBACEnabled {
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
+			errors.New("advanced RBAC is not enabled for this project"), http.StatusPreconditionFailed,
+		))
+		return
+	}
+
 	roleUID, reqErr := requestutils.GetURLParamString(r, types.URLParamProjectRoleID)
 
 	if reqErr != nil {

+ 2 - 9
api/server/handlers/project_role/update.go

@@ -58,14 +58,7 @@ func (c *UpdateProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
-	if role.IsDefaultRole() {
-		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
-			fmt.Errorf("cannot update default project roles"), http.StatusBadRequest,
-		))
-		return
-	}
-
-	if request.Name != "" && request.Name != role.Name {
+	if project.AdvancedRBACEnabled && !role.IsDefaultRole() && request.Name != "" && request.Name != role.Name {
 		if request.Name == string(types.RoleAdmin) ||
 			request.Name == string(types.RoleDeveloper) ||
 			request.Name == string(types.RoleViewer) {
@@ -110,7 +103,7 @@ func (c *UpdateProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		}
 	}
 
-	if request.Policy != nil {
+	if project.AdvancedRBACEnabled && !role.IsDefaultRole() && request.Policy != nil {
 		policy, err := c.Repo().Policy().ReadPolicy(project.ID, role.PolicyUID)
 
 		if err != nil {

+ 1 - 0
api/types/project.go

@@ -9,6 +9,7 @@ type Project struct {
 	ManagedInfraEnabled bool    `json:"managed_infra_enabled"`
 	APITokensEnabled    bool    `json:"api_tokens_enabled"`
 	StacksEnabled       bool    `json:"stacks_enabled"`
+	AdvancedRBACEnabled bool    `json:"advanced_rbac_enabled"`
 }
 
 type FeatureFlags struct {

+ 2 - 0
internal/models/project.go

@@ -63,6 +63,7 @@ type Project struct {
 	ManagedInfraEnabled bool
 	StacksEnabled       bool
 	APITokensEnabled    bool
+	AdvancedRBACEnabled bool
 }
 
 // ToProjectType generates an external types.Project to be shared over REST
@@ -82,5 +83,6 @@ func (p *Project) ToProjectType() *types.Project {
 		ManagedInfraEnabled: p.ManagedInfraEnabled,
 		StacksEnabled:       p.StacksEnabled,
 		APITokensEnabled:    p.APITokensEnabled,
+		AdvancedRBACEnabled: p.AdvancedRBACEnabled,
 	}
 }

+ 18 - 1
internal/repository/gorm/project_role.go

@@ -1,6 +1,9 @@
 package gorm
 
 import (
+	"fmt"
+
+	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
 	"gorm.io/gorm"
@@ -18,6 +21,16 @@ func NewProjectRoleRepository(db *gorm.DB) repository.ProjectRoleRepository {
 }
 
 func (repo *ProjectRoleRepository) CreateProjectRole(role *models.ProjectRole) (*models.ProjectRole, error) {
+	proj := &models.Project{}
+
+	if err := repo.db.Where("id = ?", role.ProjectID).First(proj).Error; err != nil {
+		return nil, fmt.Errorf("error creating role for project: %w", err)
+	}
+
+	if !role.IsDefaultRole() && !proj.AdvancedRBACEnabled {
+		return nil, fmt.Errorf("advanced RBAC is not enabled for this project")
+	}
+
 	if err := repo.db.Create(role).Error; err != nil {
 		return nil, err
 	}
@@ -99,10 +112,14 @@ func (repo *ProjectRoleRepository) UpdateUsersInProjectRole(projectID uint, role
 func (repo *ProjectRoleRepository) ClearUsersInProjectRole(projectID uint, roleUID string) error {
 	role := &models.ProjectRole{}
 
-	if err := repo.db.Where("project_id = ? AND unique_id = ?", projectID, roleUID).First(role).Error; err != nil {
+	if err := repo.db.Preload("Users").Where("project_id = ? AND unique_id = ?", projectID, roleUID).First(role).Error; err != nil {
 		return err
 	}
 
+	if role.UniqueID == fmt.Sprintf("%d-%s", role.ProjectID, types.RoleAdmin) && len(role.Users) == 1 {
+		return fmt.Errorf("cannot remove the last admin from this project")
+	}
+
 	assoc := repo.db.Model(&role).Association("Users")
 
 	if assoc.Error != nil {