deployment_target.go 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package authz
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "github.com/porter-dev/porter/api/server/shared/apierrors"
  8. "github.com/porter-dev/porter/api/server/shared/config"
  9. "github.com/porter-dev/porter/api/types"
  10. "github.com/porter-dev/porter/internal/models"
  11. "gorm.io/gorm"
  12. )
  13. // DeploymentTargetScopedFactory is a factory for generating deployment target middleware
  14. type DeploymentTargetScopedFactory struct {
  15. config *config.Config
  16. }
  17. // NewDeploymentTargetScopedFactory returns a new DeploymentTargetScopedFactory
  18. func NewDeploymentTargetScopedFactory(
  19. config *config.Config,
  20. ) *DeploymentTargetScopedFactory {
  21. return &DeploymentTargetScopedFactory{config}
  22. }
  23. // Middleware checks that the request is scoped to a deployment target
  24. func (p *DeploymentTargetScopedFactory) Middleware(next http.Handler) http.Handler {
  25. return &DeploymentTargetScopedMiddleware{next, p.config}
  26. }
  27. // DeploymentTargetScopedMiddleware checks that the request is scoped to a deployment target
  28. type DeploymentTargetScopedMiddleware struct {
  29. next http.Handler
  30. config *config.Config
  31. }
  32. // ServeHTTP checks that the request is scoped to a deployment target
  33. func (p *DeploymentTargetScopedMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  34. // read the project to check scopes
  35. proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  36. // get the deployment target identifier from the URL param context
  37. reqScopes, _ := r.Context().Value(types.RequestScopeCtxKey).(map[types.PermissionScope]*types.RequestAction)
  38. deploymentTargetIdentifier := reqScopes[types.DeploymentTargetScope].Resource.Name
  39. deploymentTargetDB, err := p.config.Repo.DeploymentTarget().DeploymentTarget(proj.ID, deploymentTargetIdentifier)
  40. if err != nil {
  41. if !errors.Is(err, gorm.ErrRecordNotFound) {
  42. apierrors.HandleAPIError(p.config.Logger, p.config.Alerter, w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError), true)
  43. return
  44. }
  45. err := fmt.Errorf("deployment target with identifier %s not found in project %d", deploymentTargetIdentifier, proj.ID)
  46. apierrors.HandleAPIError(p.config.Logger, p.config.Alerter, w, r, apierrors.NewErrPassThroughToClient(err, http.StatusForbidden), true)
  47. return
  48. }
  49. deploymentTarget := types.DeploymentTarget{
  50. ID: deploymentTargetDB.ID,
  51. ProjectID: uint(deploymentTargetDB.ProjectID),
  52. ClusterID: uint(deploymentTargetDB.ClusterID),
  53. Name: deploymentTargetDB.VanityName,
  54. Namespace: deploymentTargetDB.Selector,
  55. IsPreview: deploymentTargetDB.Preview,
  56. IsDefault: deploymentTargetDB.IsDefault,
  57. CreatedAtUTC: deploymentTargetDB.CreatedAt.UTC(),
  58. UpdatedAtUTC: deploymentTargetDB.UpdatedAt.UTC(),
  59. }
  60. ctx := NewDeploymentTargetContext(r.Context(), deploymentTarget)
  61. r = r.Clone(ctx)
  62. p.next.ServeHTTP(w, r)
  63. }
  64. // NewDeploymentTargetContext returns a new context with the deployment target
  65. func NewDeploymentTargetContext(ctx context.Context, deploymentTarget types.DeploymentTarget) context.Context {
  66. return context.WithValue(ctx, types.DeploymentTargetScope, deploymentTarget)
  67. }