Skip to content

Commit

Permalink
prevent creating user without sending verification email
Browse files Browse the repository at this point in the history
  • Loading branch information
aradwann committed Jan 6, 2024
1 parent ce62c92 commit 9a7b622
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 17 deletions.
15 changes: 15 additions & 0 deletions db/mock/store.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions db/store/exec_tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package db

import (
"context"
"fmt"
)

// ExecTx executes a function within a database transaction
func (store *SQLStore) execTx(ctx context.Context, fn func(*Queries) error) error {
tx, err := store.db.Begin()
if err != nil {
return err
}

q := New(tx)
err = fn(q)
if err != nil {
if rbErr := tx.Rollback(); rbErr != nil {
return fmt.Errorf("tx err: %v, rb err: %v", err, rbErr)
}
return err
}

return tx.Commit()
}
3 changes: 3 additions & 0 deletions db/store/store.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package db

import (
"context"
"database/sql"
)

// SQLStore provides all functions to execute db queries and transactions
type Store interface {
Querier
CreateUserTx(ctx context.Context, arg CreateUserTxParams) (CreateUserTxResult, error)
// VerifyEmailTx(ctx context.Context, arg VerifyEmailTxParams) (VerifyEmailTxResult, error)
}

// SQLStore provides all functions to execute db queries and transactions
Expand Down
29 changes: 29 additions & 0 deletions db/store/tx_create_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package db

import "context"

type CreateUserTxParams struct {
CreateUserParams
AfterCreate func(user User) error
}

type CreateUserTxResult struct {
User User
}

func (store *SQLStore) CreateUserTx(ctx context.Context, arg CreateUserTxParams) (CreateUserTxResult, error) {
var result CreateUserTxResult

err := store.execTx(ctx, func(q *Queries) error {
var err error

result.User, err = q.CreateUser(ctx, arg.CreateUserParams)
if err != nil {
return err
}
return arg.AfterCreate(result.User)

})

return result, err
}
36 changes: 19 additions & 17 deletions gapi/rpc_create_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,36 @@ func (server *Server) CreateUser(ctx context.Context, req *pb.CreateUserRequest)
return nil, status.Errorf(codes.Internal, "failed to hash password: %s", err)
}

arg := db.CreateUserParams{
Username: req.GetUsername(),
HashedPassword: hashedPassword,
FullName: req.GetFullName(),
Email: req.GetEmail(),
arg := db.CreateUserTxParams{
CreateUserParams: db.CreateUserParams{
Username: req.GetUsername(),
HashedPassword: hashedPassword,
FullName: req.GetFullName(),
Email: req.GetEmail(),
},
AfterCreate: func(user db.User) error {
taskPayload := &worker.PayloadSendVerifyEmail{Username: user.Username}
opts := []asynq.Option{
asynq.MaxRetry(10),
asynq.ProcessIn(10 * time.Second),
asynq.Queue(worker.QueueCritical),
}
return server.taskDistributor.DistributeTaskSendVerifyEmail(ctx, taskPayload, opts...)

},
}

user, err := server.store.CreateUser(ctx, arg)
result, err := server.store.CreateUserTx(ctx, arg)
if err != nil {
if db.ErrorCode(err) == db.UniqueViolation {
return nil, status.Errorf(codes.AlreadyExists, "username already exsits")
}
return nil, status.Errorf(codes.Internal, "failed to create user: %s", err)
}
// Send verification email
taskPayload := &worker.PayloadSendVerifyEmail{Username: user.Username}
opts := []asynq.Option{
asynq.MaxRetry(10),
asynq.ProcessIn(10 * time.Second),
asynq.Queue(worker.QueueCritical),
}
err = server.taskDistributor.DistributeTaskSendVerifyEmail(ctx, taskPayload, opts...)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to distribute the task to send verify email: %s", err)

}
rsp := &pb.CreateUserResponse{
User: convertUser(user),
User: convertUser(result.User),
}
return rsp, nil
}
Expand Down

0 comments on commit 9a7b622

Please sign in to comment.