invite_respond.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package user
  2. import (
  3. "errors"
  4. fmt "fmt"
  5. "net/http"
  6. "github.com/porter-dev/porter/api/server/shared"
  7. "github.com/porter-dev/porter/api/server/handlers"
  8. "github.com/porter-dev/porter/api/server/shared/apierrors"
  9. "github.com/porter-dev/porter/api/server/shared/config"
  10. "github.com/porter-dev/porter/api/types"
  11. "github.com/porter-dev/porter/internal/models"
  12. "github.com/porter-dev/porter/internal/telemetry"
  13. "gorm.io/gorm"
  14. )
  15. type InviteResponseHandler struct {
  16. handlers.PorterHandlerReader
  17. }
  18. func NewInviteResponseHandler(
  19. config *config.Config,
  20. decoderValidator shared.RequestDecoderValidator,
  21. ) http.Handler {
  22. return &InviteResponseHandler{
  23. PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, nil),
  24. }
  25. }
  26. type InviteResponseRequest struct {
  27. AcceptedInviteIds []uint `json:"accepted_invite_ids"`
  28. DeclinedInviteIds []uint `json:"declined_invite_ids"`
  29. }
  30. func (c *InviteResponseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. ctx, span := telemetry.NewSpan(r.Context(), "serve-invite-response")
  32. defer span.End()
  33. user, _ := ctx.Value(types.UserScope).(*models.User)
  34. request := &InviteResponseRequest{}
  35. if ok := c.DecodeAndValidate(w, r, request); !ok {
  36. err := telemetry.Error(ctx, span, nil, "error decoding and validating request")
  37. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  38. return
  39. }
  40. invites, err := c.Repo().Invite().ListInvitesByEmail(user.Email)
  41. if err != nil {
  42. err = telemetry.Error(ctx, span, err, "error listing invites by email")
  43. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  44. return
  45. }
  46. // create a map of pending invites by id
  47. invitesById := map[uint]*models.Invite{}
  48. for _, invite := range invites {
  49. // only consider pending invites
  50. if invite.Status == models.InvitePending {
  51. invitesById[invite.ID] = invite
  52. }
  53. }
  54. fmt.Println("dgt invitesById", invitesById)
  55. // accept invites and create roles in project
  56. for _, id := range request.AcceptedInviteIds {
  57. if invite, ok := invitesById[id]; ok {
  58. fmt.Println("dgt invite found", invite)
  59. project, err := c.Repo().Project().ReadProject(invite.ProjectID)
  60. if err != nil {
  61. // if the project is not found, skip
  62. if errors.Is(err, gorm.ErrRecordNotFound) {
  63. continue
  64. }
  65. err = telemetry.Error(ctx, span, err, "error reading project")
  66. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  67. return
  68. }
  69. fmt.Println("dgt project found", project)
  70. if invite.Kind == "" {
  71. invite.Kind = models.RoleDeveloper
  72. }
  73. role := &models.Role{
  74. Role: types.Role{
  75. UserID: user.ID,
  76. ProjectID: invite.ProjectID,
  77. Kind: types.RoleKind(invite.Kind),
  78. },
  79. }
  80. if _, err := c.Repo().Project().ReadProjectRole(project.ID, user.ID); err != nil {
  81. fmt.Println("dgt role not found")
  82. if !errors.Is(err, gorm.ErrRecordNotFound) {
  83. err = telemetry.Error(ctx, span, err, "error reading project role")
  84. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  85. return
  86. }
  87. fmt.Println("edgt role creating")
  88. telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "new-role", Value: true})
  89. // only create if no role is found yet
  90. if role, err = c.Repo().Project().CreateProjectRole(project, role); err != nil {
  91. err = telemetry.Error(ctx, span, err, "error creating project role")
  92. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  93. return
  94. }
  95. fmt.Println("dgt role created")
  96. }
  97. // update the invite
  98. invite.UserID = user.ID
  99. invite.Status = models.InviteAccepted
  100. if _, err = c.Repo().Invite().UpdateInvite(invite); err != nil {
  101. err = telemetry.Error(ctx, span, err, "error updating invite")
  102. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  103. return
  104. }
  105. }
  106. }
  107. // decline invites
  108. for _, id := range request.DeclinedInviteIds {
  109. if invite, ok := invitesById[id]; ok {
  110. invite.Status = models.InviteDeclined
  111. if _, err = c.Repo().Invite().UpdateInvite(invite); err != nil {
  112. err = telemetry.Error(ctx, span, err, "error updating invite")
  113. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  114. return
  115. }
  116. }
  117. }
  118. return
  119. }