|
|
@@ -6,6 +6,7 @@ import (
|
|
|
"strconv"
|
|
|
|
|
|
"github.com/go-chi/chi"
|
|
|
+ "github.com/porter-dev/porter/api/types"
|
|
|
"github.com/porter-dev/porter/internal/forms"
|
|
|
"github.com/porter-dev/porter/internal/models"
|
|
|
)
|
|
|
@@ -83,6 +84,78 @@ func (app *App) HandleCreateProject(w http.ResponseWriter, r *http.Request) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// HandleGetProjectRoles lists the roles available to the project. For now, these
|
|
|
+// roles are static.
|
|
|
+func (app *App) HandleGetProjectRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
+ roles := []string{models.RoleAdmin, models.RoleDeveloper, models.RoleViewer}
|
|
|
+
|
|
|
+ w.WriteHeader(http.StatusOK)
|
|
|
+
|
|
|
+ if err := json.NewEncoder(w).Encode(&roles); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+type Collaborator struct {
|
|
|
+ ID uint `json:"id"`
|
|
|
+ Kind string `json:"kind"`
|
|
|
+ UserID uint `json:"user_id"`
|
|
|
+ Email string `json:"email"`
|
|
|
+ ProjectID uint `json:"project_id"`
|
|
|
+}
|
|
|
+
|
|
|
+// HandleListProjectCollaborators lists the collaborators in the project
|
|
|
+func (app *App) HandleListProjectCollaborators(w http.ResponseWriter, r *http.Request) {
|
|
|
+ id, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ roles, err := app.Repo.Project.ListProjectRoles(uint(id))
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorRead(err, ErrProjectDataRead, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ res := make([]*Collaborator, 0)
|
|
|
+ roleMap := make(map[uint]*models.Role)
|
|
|
+ idArr := make([]uint, 0)
|
|
|
+
|
|
|
+ for _, role := range roles {
|
|
|
+ roleCp := role
|
|
|
+ roleMap[role.UserID] = &roleCp
|
|
|
+ idArr = append(idArr, role.UserID)
|
|
|
+ }
|
|
|
+
|
|
|
+ users, err := app.Repo.User.ListUsersByIDs(idArr)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorRead(err, ErrProjectDataRead, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, user := range users {
|
|
|
+ res = append(res, &Collaborator{
|
|
|
+ ID: roleMap[user.ID].ID,
|
|
|
+ Kind: roleMap[user.ID].Kind,
|
|
|
+ UserID: roleMap[user.ID].UserID,
|
|
|
+ Email: user.Email,
|
|
|
+ ProjectID: roleMap[user.ID].ProjectID,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ w.WriteHeader(http.StatusOK)
|
|
|
+
|
|
|
+ if err := json.NewEncoder(w).Encode(res); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// HandleReadProject returns an externalized Project (models.ProjectExternal)
|
|
|
// based on an ID
|
|
|
func (app *App) HandleReadProject(w http.ResponseWriter, r *http.Request) {
|
|
|
@@ -110,6 +183,92 @@ func (app *App) HandleReadProject(w http.ResponseWriter, r *http.Request) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// HandleReadProjectPolicy returns the policy document given the current user
|
|
|
+func (app *App) HandleReadProjectPolicy(w http.ResponseWriter, r *http.Request) {
|
|
|
+ id, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ userID, err := app.getUserIDFromRequest(r)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorInternal(err, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ role, err := app.Repo.Project.ReadProjectRole(uint(id), userID)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorRead(err, ErrProjectDataRead, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // case on the role to get the policy document
|
|
|
+ var policy types.Policy
|
|
|
+ switch role.Kind {
|
|
|
+ case models.RoleAdmin:
|
|
|
+ policy = types.AdminPolicy
|
|
|
+ case models.RoleDeveloper:
|
|
|
+ policy = types.DeveloperPolicy
|
|
|
+ case models.RoleViewer:
|
|
|
+ policy = types.ViewerPolicy
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := json.NewEncoder(w).Encode(policy); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// HandleUpdateProjectRole updates a project role with a new "kind"
|
|
|
+func (app *App) HandleUpdateProjectRole(w http.ResponseWriter, r *http.Request) {
|
|
|
+ id, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ userID, err := strconv.ParseUint(chi.URLParam(r, "user_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ role, err := app.Repo.Project.ReadProjectRole(uint(id), uint(userID))
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ form := &forms.UpdateProjectRoleForm{}
|
|
|
+
|
|
|
+ // decode from JSON to form value
|
|
|
+ if err := json.NewDecoder(r.Body).Decode(form); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ role.Kind = form.Kind
|
|
|
+
|
|
|
+ role, err = app.Repo.Project.UpdateProjectRole(uint(id), role)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorRead(err, ErrProjectDataRead, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := json.NewEncoder(w).Encode(role.Externalize()); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// HandleDeleteProject deletes a project from the db, reading from the project_id
|
|
|
// in the URL param
|
|
|
func (app *App) HandleDeleteProject(w http.ResponseWriter, r *http.Request) {
|
|
|
@@ -143,3 +302,40 @@ func (app *App) HandleDeleteProject(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// HandleDeleteProjectRole deletes a project role from the db, reading from the project_id
|
|
|
+// in the URL param
|
|
|
+func (app *App) HandleDeleteProjectRole(w http.ResponseWriter, r *http.Request) {
|
|
|
+ id, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ userID, err := strconv.ParseUint(chi.URLParam(r, "user_id"), 0, 64)
|
|
|
+
|
|
|
+ if err != nil || id == 0 {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ role, err := app.Repo.Project.ReadProjectRole(uint(id), uint(userID))
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ role, err = app.Repo.Project.DeleteProjectRole(uint(id), uint(userID))
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ app.handleErrorRead(err, ErrProjectDataRead, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := json.NewEncoder(w).Encode(role.Externalize()); err != nil {
|
|
|
+ app.handleErrorFormDecoding(err, ErrProjectDecode, w)
|
|
|
+ return
|
|
|
+ }
|
|
|
+}
|