From 0d9c56858370e6a2820f4d925944e97bd65a061b Mon Sep 17 00:00:00 2001 From: Aidan Traboulay Date: Mon, 9 Dec 2024 15:44:22 -0400 Subject: [PATCH 1/2] add resend verfication email handler --- backend/internal/server/auth.go | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/backend/internal/server/auth.go b/backend/internal/server/auth.go index e3deab5..178bd57 100644 --- a/backend/internal/server/auth.go +++ b/backend/internal/server/auth.go @@ -25,6 +25,7 @@ func (s *Server) setupAuthRoutes() { auth.POST("/signin", s.handleSignin, mw.ValidateRequestBody(reflect.TypeOf(SigninRequest{}))) auth.GET("/verify-email", s.handleVerifyEmail) auth.GET("/ami-verified", s.handleEmailVerifiedStatus) + auth.POST("/resend-verification", s.handleResendVerificationEmail, mw.ValidateRequestBody(reflect.TypeOf(ResendVerificationEmailRequest{}))) } func (s *Server) handleSignup(c echo.Context) error { @@ -228,6 +229,55 @@ func (s *Server) handleVerifyEmail(c echo.Context) error { }) } +func (s *Server) handleResendVerificationEmail(c echo.Context) error { + req, ok := c.Get(mw.REQUEST_BODY_KEY).(*ResendVerificationEmailRequest) + if !ok { + return echo.NewHTTPError(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + + ctx := c.Request().Context() + user, err := s.queries.GetUserByEmail(ctx, req.Email) + if err != nil { + return echo.NewHTTPError(http.StatusNotFound, "user not found") + } + + if user.EmailVerified { + return echo.NewHTTPError(http.StatusBadRequest, "email already verified") + } + + err = s.queries.DeleteVerifyEmailTokenByEmail(ctx, req.Email) + if err != nil { + log.Error().Err(err).Str("email", req.Email).Msg("Failed to delete existing verification tokens") + return echo.NewHTTPError(http.StatusInternalServerError, "failed to process request") + } + + exp := time.Now().Add(time.Minute * 30) + token, err := s.queries.CreateVerifyEmailToken(ctx, db.CreateVerifyEmailTokenParams{ + Email: req.Email, + ExpiresAt: exp, + }) + if err != nil { + log.Error().Err(err).Str("email", req.Email).Msg("Failed to verify email token in db") + return echo.NewHTTPError(http.StatusInternalServerError, "failed to create verification token") + } + + tokenStr, err := jwt.GenerateVerifyEmailToken(req.Email, token.ID, exp) + if err != nil { + log.Error().Err(err).Str("email", req.Email).Msg("Failed to generate signed verify email token") + return echo.NewHTTPError(http.StatusInternalServerError, "failed to generate verification token") + } + + err = service.SendVerficationEmail(ctx, req.Email, tokenStr) + if err != nil { + log.Error().Err(err).Str("email", req.Email).Msg("Failed to send verification email") + return echo.NewHTTPError(http.StatusInternalServerError, "failed to send verification email") + } + + return c.JSON(http.StatusOK, map[string]bool{ + "success": true, + }) +} + /* handleEmailVerifiedStatus checks for the email_verified column of the given email. If the email does not exist in the users table, it returns false. The same goes From 042336932ec3ecd1443a611015b8955fb0066fd6 Mon Sep 17 00:00:00 2001 From: Aidan Traboulay Date: Mon, 9 Dec 2024 15:44:46 -0400 Subject: [PATCH 2/2] add resend email verification request type --- backend/internal/server/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/internal/server/types.go b/backend/internal/server/types.go index 5e5b0d5..7acf600 100644 --- a/backend/internal/server/types.go +++ b/backend/internal/server/types.go @@ -206,6 +206,10 @@ type EmailVerifiedStatusResponse struct { Verified bool `json:"verified"` } +type ResendVerificationEmailRequest struct { + Email string `json:"email" validate:"required,email"` +} + type CreateProjectFileRequest struct { FileType string `json:"file_type" validate:"required"` FileURL string `json:"file_url" validate:"required,url,s3_url"`