Skip to content

Commit

Permalink
feat(auth): request to resend verification email
Browse files Browse the repository at this point in the history
  • Loading branch information
olexsmir committed Aug 3, 2024
1 parent 519e795 commit 994d528
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 1 deletion.
35 changes: 34 additions & 1 deletion internal/service/usersrv/usersrv.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type UserServicer interface {
Logout(ctx context.Context, userID uuid.UUID) error

Verify(ctx context.Context, verificationKey string) error
// TODO: add resent verification email
ResendVerificationEmail(ctx context.Context, credentials dtos.SignInDTO) error

ParseToken(token string) (jwtutil.Payload, error)
CheckIfUserExists(ctx context.Context, userID uuid.UUID) (bool, error)
Expand Down Expand Up @@ -158,6 +158,39 @@ func (u *UserSrv) Verify(ctx context.Context, verificationKey string) error {
return u.userstore.MarkUserAsActivated(ctx, uid)
}

func (u *UserSrv) ResendVerificationEmail(ctx context.Context, inp dtos.SignInDTO) error {
hashedPassword, err := u.hasher.Hash(inp.Password)
if err != nil {
return err
}

user, err := u.userstore.GetUserByCredentials(ctx, inp.Email, hashedPassword)
if err != nil {
if errors.Is(err, models.ErrUserNotFound) {
return models.ErrUserWrongCredentials
}
return err
}

if user.Activated {
return models.ErrUserIsAlreeadyVerified
}

token, err := u.vertokrepo.GetTokenOrUpdateTokenByUserID(
ctx,
user.ID,
uuid.Must(uuid.NewV4()).String(),
time.Now().Add(u.verificationTokenTTL))
if err != nil {
return err
}

bgCtx, bgCancel := context.WithTimeout(context.Background(), 10*time.Second)
go u.sendVerificationEmail(bgCtx, bgCancel, inp.Email, token) //nolint:errcheck

return nil
}

func (u *UserSrv) ParseToken(token string) (jwtutil.Payload, error) {
return u.jwtTokenizer.Parse(token)
}
Expand Down
27 changes: 27 additions & 0 deletions internal/store/psql/vertokrepo/vertokrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ type VerificationTokenStorer interface {
token string,
usedAT time.Time,
) (uuid.UUID, error)

GetTokenOrUpdateTokenByUserID(
ctx context.Context,
userID uuid.UUID,
token string,
tokenExpirationTime time.Time,
) (string, error)
}

var _ VerificationTokenStorer = (*VerificationTokenRepo)(nil)
Expand Down Expand Up @@ -88,3 +95,23 @@ returning user_id`

return userID, err
}

func (r *VerificationTokenRepo) GetTokenOrUpdateTokenByUserID(
ctx context.Context,
userID uuid.UUID,
token string,
tokenExpirationTime time.Time,
) (string, error) {
query := `--sql
insert into verification_tokens (user_id, token, expires_at)
values ($1, $2, $3)
on conflict (user_id)
do update set
token = $2,
expires_at = $3
returning token`

var res string
err := r.db.QueryRow(ctx, query, userID, token, tokenExpirationTime).Scan(&res)
return res, err
}
1 change: 1 addition & 0 deletions internal/transport/http/apiv1/apiv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (a *APIV1) Routes(r *gin.RouterGroup) {
auth.POST("/signin", a.signInHandler)
auth.POST("/refresh-tokens", a.refreshTokensHandler)
auth.GET("/verify/:token", a.verifyHandler)
auth.POST("/resend-verification-email", a.resendVerificationEmailHandler)

authorized := auth.Group("/", a.authorizedMiddleware)
{
Expand Down
18 changes: 18 additions & 0 deletions internal/transport/http/apiv1/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@ func (a *APIV1) verifyHandler(c *gin.Context) {
c.Status(http.StatusOK)
}

func (a *APIV1) resendVerificationEmailHandler(c *gin.Context) {
var req signInRequest
if err := c.ShouldBindJSON(&req); err != nil {
newError(c, http.StatusBadRequest, "invalid request")
return
}

if err := a.usersrv.ResendVerificationEmail(c.Request.Context(), dtos.SignInDTO{
Email: req.Email,
Password: req.Password,
}); err != nil {
errorResponse(c, err)
return
}

c.Status(http.StatusOK)
}

func (a *APIV1) logOutHandler(c *gin.Context) {
if err := a.usersrv.Logout(c.Request.Context(), a.getUserID(c)); err != nil {
errorResponse(c, err)
Expand Down

0 comments on commit 994d528

Please sign in to comment.