Forráskód Böngészése

update create and delete project handlers

Mohammed Nafees 3 éve
szülő
commit
b6693bde63

+ 68 - 32
api/server/handlers/project/create.go

@@ -1,6 +1,8 @@
 package project
 
 import (
+	"encoding/json"
+	"fmt"
 	"net/http"
 
 	"github.com/porter-dev/porter/api/server/handlers"
@@ -9,6 +11,7 @@ import (
 	"github.com/porter-dev/porter/api/server/shared/config"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/analytics"
+	"github.com/porter-dev/porter/internal/encryption"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
 )
@@ -43,14 +46,23 @@ func (p *ProjectCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		Name: request.Name,
 	}
 
-	var err error
-	proj, _, err = CreateProjectWithUser(p.Repo().Project(), proj, user)
+	proj, err := p.Repo().Project().CreateProject(proj)
 
 	if err != nil {
 		p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
 		return
 	}
 
+	err = createDefaultProjectRoles(proj.ID, user.ID, p.Repo())
+
+	if err != nil {
+		// we need to first delete the default project roles we just created
+		deleteAllProjectRoles(proj.ID, p.Repo())
+
+		p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
 	// create onboarding flow set to the first step
 	_, err = p.Repo().Onboarding().CreateProjectOnboarding(&models.Onboarding{
 		ProjectID:   proj.ID,
@@ -92,36 +104,60 @@ func (p *ProjectCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 	}))
 }
 
-func CreateProjectWithUser(
-	projectRepo repository.ProjectRepository,
-	proj *models.Project,
-	user *models.User,
-) (*models.Project, *models.Role, error) {
-	proj, err := projectRepo.CreateProject(proj)
-
-	if err != nil {
-		return nil, nil, err
-	}
-
-	// create a new Role with the user as the admin
-	role, err := projectRepo.CreateProjectRole(proj, &models.Role{
-		Role: types.Role{
-			UserID:    user.ID,
-			ProjectID: proj.ID,
-			Kind:      types.RoleAdmin,
-		},
-	})
-
-	if err != nil {
-		return nil, nil, err
-	}
-
-	// read the project again to get the model with the role attached
-	proj, err = projectRepo.ReadProject(proj.ID)
-
-	if err != nil {
-		return nil, nil, err
+func createDefaultProjectRoles(projectID, userID uint, repo repository.Repository) error {
+	for _, kind := range []types.RoleKind{types.RoleAdmin, types.RoleDeveloper, types.RoleViewer} {
+		uid, err := encryption.GenerateRandomBytes(16)
+
+		if err != nil {
+			return err
+		}
+
+		var policyBytes []byte
+
+		switch kind {
+		case types.RoleAdmin:
+			policyBytes, err = json.Marshal(types.AdminPolicy)
+
+			if err != nil {
+				return err
+			}
+		case types.RoleDeveloper:
+			policyBytes, err = json.Marshal(types.DeveloperPolicy)
+
+			if err != nil {
+				return err
+			}
+		case types.RoleViewer:
+			policyBytes, err = json.Marshal(types.ViewerPolicy)
+
+			if err != nil {
+				return err
+			}
+		}
+
+		policy, err := repo.Policy().CreatePolicy(&models.Policy{
+			UniqueID:        uid,
+			ProjectID:       projectID,
+			CreatedByUserID: userID,
+			Name:            fmt.Sprintf("%s-project-role-policy", kind),
+			PolicyBytes:     policyBytes,
+		})
+
+		if err != nil {
+			return err
+		}
+
+		_, err = repo.ProjectRole().CreateProjectRole(&models.ProjectRole{
+			UniqueID:  fmt.Sprintf("%d-%s", projectID, kind),
+			ProjectID: projectID,
+			PolicyUID: policy.UniqueID,
+			Name:      string(kind),
+		})
+
+		if err != nil {
+			return err
+		}
 	}
 
-	return proj, role, nil
+	return nil
 }

+ 21 - 0
api/server/handlers/project/delete.go

@@ -9,6 +9,7 @@ import (
 	"github.com/porter-dev/porter/api/server/shared/config"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/repository"
 )
 
 type ProjectDeleteHandler struct {
@@ -28,6 +29,8 @@ func (p *ProjectDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 	user, _ := r.Context().Value(types.UserScope).(*models.User)
 	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 
+	deleteAllProjectRoles(proj.ID, p.Repo())
+
 	proj, err := p.Repo().Project().DeleteProject(proj)
 
 	if err != nil {
@@ -44,3 +47,21 @@ func (p *ProjectDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		p.HandleAPIErrorNoWrite(w, r, apierrors.NewErrInternal(err))
 	}
 }
+
+func deleteAllProjectRoles(projectID uint, repo repository.Repository) {
+	policies, err := repo.Policy().ListPoliciesByProjectID(projectID)
+
+	if err == nil {
+		for _, policy := range policies {
+			repo.Policy().DeletePolicy(policy)
+		}
+	}
+
+	roles, err := repo.ProjectRole().ListProjectRoles(projectID)
+
+	if err == nil {
+		for _, role := range roles {
+			repo.ProjectRole().DeleteProjectRole(role)
+		}
+	}
+}

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

@@ -51,6 +51,13 @@ func (c *DeleteProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
+	if role.IsDefaultRole() {
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
+			fmt.Errorf("cannot delete default project role"), http.StatusConflict,
+		))
+		return
+	}
+
 	if len(role.Users) > 0 {
 		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
 			fmt.Errorf("role has one or more users assigned"), http.StatusPreconditionFailed,

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

@@ -58,7 +58,7 @@ func (c *UpdateProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
-	if request.Name != "" && request.Name != role.Name {
+	if !role.IsDefaultRole() && request.Name != "" && request.Name != role.Name {
 		if request.Name == string(types.RoleAdmin) ||
 			request.Name == string(types.RoleDeveloper) ||
 			request.Name == string(types.RoleViewer) {
@@ -87,7 +87,7 @@ func (c *UpdateProjectRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		}
 	}
 
-	if request.Policy != nil {
+	if !role.IsDefaultRole() && request.Policy != nil {
 		policy, err := c.Repo().Policy().ReadPolicy(project.ID, role.PolicyUID)
 
 		if err != nil {

+ 1 - 1
cmd/migrate/migrate_legacy_rbac/migrate.go

@@ -154,7 +154,7 @@ func createNewRole(
 	newPolicy, err := policyRepo.CreatePolicy(&models.Policy{
 		UniqueID:    uid,
 		ProjectID:   projectID,
-		Name:        fmt.Sprintf("%d-%s-project-role-policy", projectID, kind),
+		Name:        fmt.Sprintf("%s-project-role-policy", kind),
 		PolicyBytes: policyBytes,
 	})
 

+ 8 - 0
internal/models/project_role.go

@@ -1,6 +1,8 @@
 package models
 
 import (
+	"fmt"
+
 	"github.com/porter-dev/porter/api/types"
 	"gorm.io/gorm"
 )
@@ -31,3 +33,9 @@ func (role *ProjectRole) ToProjectRoleType(policy *types.PolicyDocument) *types.
 
 	return res
 }
+
+func (role *ProjectRole) IsDefaultRole() bool {
+	return role.UniqueID == fmt.Sprintf("%d-%s", role.ProjectID, types.RoleAdmin) ||
+		role.UniqueID == fmt.Sprintf("%d-%s", role.ProjectID, types.RoleDeveloper) ||
+		role.UniqueID == fmt.Sprintf("%d-%s", role.ProjectID, types.RoleViewer)
+}