email_verify.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package user
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "github.com/porter-dev/porter/api/server/handlers"
  7. "github.com/porter-dev/porter/api/server/shared"
  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/notifier"
  13. )
  14. type VerifyEmailInitiateHandler struct {
  15. handlers.PorterHandler
  16. }
  17. func NewVerifyEmailInitiateHandler(
  18. config *config.Config,
  19. ) *VerifyEmailInitiateHandler {
  20. return &VerifyEmailInitiateHandler{
  21. PorterHandler: handlers.NewDefaultPorterHandler(config, nil, nil),
  22. }
  23. }
  24. func (v *VerifyEmailInitiateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  25. user, _ := r.Context().Value(types.UserScope).(*models.User)
  26. pwReset, rawToken, err := CreatePWResetTokenForEmail(
  27. v.Repo().PWResetToken(),
  28. v.HandleAPIError,
  29. w,
  30. r,
  31. &types.InitiateResetUserPasswordRequest{
  32. Email: user.Email,
  33. },
  34. )
  35. if err != nil {
  36. return
  37. }
  38. queryVals := url.Values{
  39. "token": []string{rawToken},
  40. "token_id": []string{fmt.Sprintf("%d", pwReset.ID)},
  41. }
  42. err = v.Config().UserNotifier.SendEmailVerification(
  43. &notifier.SendEmailVerificationOpts{
  44. Email: user.Email,
  45. URL: fmt.Sprintf("%s/api/email/verify/finalize?%s", v.Config().ServerConf.ServerURL, queryVals.Encode()),
  46. },
  47. )
  48. if err != nil {
  49. v.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  50. return
  51. }
  52. }
  53. type VerifyEmailFinalizeHandler struct {
  54. handlers.PorterHandlerReader
  55. }
  56. func NewVerifyEmailFinalizeHandler(
  57. config *config.Config,
  58. decoderValidator shared.RequestDecoderValidator,
  59. ) *VerifyEmailFinalizeHandler {
  60. return &VerifyEmailFinalizeHandler{
  61. PorterHandlerReader: handlers.NewDefaultPorterHandler(config, decoderValidator, nil),
  62. }
  63. }
  64. func (v *VerifyEmailFinalizeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  65. user, _ := r.Context().Value(types.UserScope).(*models.User)
  66. request := &types.VerifyEmailFinalizeRequest{}
  67. if err := v.DecodeAndValidateNoWrite(r, request); err != nil {
  68. http.Redirect(w, r, "/dashboard?error="+url.QueryEscape(err.Error()), 302)
  69. return
  70. }
  71. token, err := VerifyToken(
  72. v.Repo().PWResetToken(),
  73. handlers.IgnoreAPIError,
  74. w,
  75. r,
  76. &request.VerifyTokenFinalizeRequest,
  77. user.Email,
  78. )
  79. if err != nil {
  80. http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Email verification error: valid token required"), 302)
  81. return
  82. }
  83. user.EmailVerified = true
  84. user, err = v.Repo().User().UpdateUser(user)
  85. if err != nil {
  86. http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Could not verify email address"), 302)
  87. return
  88. }
  89. // invalidate the token
  90. token.IsValid = false
  91. _, err = v.Repo().PWResetToken().UpdatePWResetToken(token)
  92. if err != nil {
  93. http.Redirect(w, r, "/dashboard?error="+url.QueryEscape("Could not verify email address"), 302)
  94. return
  95. }
  96. http.Redirect(w, r, "/dashboard", 302)
  97. return
  98. }