create.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //go:build ee
  2. // +build ee
  3. package invite
  4. import (
  5. "fmt"
  6. "net/http"
  7. "time"
  8. "github.com/porter-dev/porter/api/server/handlers"
  9. "github.com/porter-dev/porter/api/server/shared"
  10. "github.com/porter-dev/porter/api/server/shared/apierrors"
  11. "github.com/porter-dev/porter/api/server/shared/config"
  12. "github.com/porter-dev/porter/api/types"
  13. "github.com/porter-dev/porter/internal/models"
  14. "github.com/porter-dev/porter/internal/notifier"
  15. "github.com/porter-dev/porter/internal/oauth"
  16. )
  17. type InviteCreateHandler struct {
  18. handlers.PorterHandlerReadWriter
  19. }
  20. func NewInviteCreateHandler(
  21. config *config.Config,
  22. decoderValidator shared.RequestDecoderValidator,
  23. writer shared.ResultWriter,
  24. ) http.Handler {
  25. return &InviteCreateHandler{
  26. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  27. }
  28. }
  29. func (c *InviteCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  30. user, _ := r.Context().Value(types.UserScope).(*models.User)
  31. project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  32. request := &types.CreateInviteRequest{}
  33. if ok := c.DecodeAndValidate(w, r, request); !ok {
  34. return
  35. }
  36. // create invite model
  37. invite, err := CreateInviteWithProject(request, project.ID)
  38. if err != nil {
  39. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  40. return
  41. }
  42. // write to database
  43. invite, err = c.Repo().Invite().CreateInvite(invite)
  44. if err != nil {
  45. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  46. return
  47. }
  48. // app.Logger.Info().Msgf("New invite created: %d", invite.ID)
  49. if err := c.Config().UserNotifier.SendProjectInviteEmail(
  50. &notifier.SendProjectInviteEmailOpts{
  51. InviteeEmail: request.Email,
  52. URL: fmt.Sprintf("%s/api/projects/%d/invites/%s", c.Config().ServerConf.ServerURL, project.ID, invite.Token),
  53. Project: project.Name,
  54. ProjectOwnerEmail: user.Email,
  55. },
  56. ); err != nil {
  57. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  58. return
  59. }
  60. res := types.CreateInviteResponse{
  61. Invite: invite.ToInviteType(),
  62. }
  63. c.WriteResult(w, r, res)
  64. }
  65. func CreateInviteWithProject(invite *types.CreateInviteRequest, projectID uint) (*models.Invite, error) {
  66. // generate a token and an expiry time
  67. expiry := time.Now().Add(7 * 24 * time.Hour)
  68. return &models.Invite{
  69. Email: invite.Email,
  70. Kind: invite.Kind,
  71. Expiry: &expiry,
  72. ProjectID: projectID,
  73. Token: oauth.CreateRandomState(),
  74. }, nil
  75. }