onasty/internal/store/psql/vertokrepo/vertokrepo.go(view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
package vertokrepo
import (
"context"
"time"
"github.com/gofrs/uuid/v5"
"github.com/henvic/pgq"
"github.com/olexsmir/onasty/internal/models"
"github.com/olexsmir/onasty/internal/store/psqlutil"
)
type VerificationTokenStorer interface {
Create(
ctx context.Context,
token string,
userID uuid.UUID,
createdAt, expiresAt time.Time,
) error
GetUserIDByTokenAndMarkAsUsed(
ctx context.Context,
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)
type VerificationTokenRepo struct {
db *psqlutil.DB
}
func New(db *psqlutil.DB) *VerificationTokenRepo {
return &VerificationTokenRepo{
db: db,
}
}
func (r *VerificationTokenRepo) Create(
ctx context.Context,
token string,
userID uuid.UUID,
createdAt, expiresAt time.Time,
) error {
query, aggs, err := pgq.
Insert("verification_tokens").
Columns("user_id", "token", "created_at", "expires_at").
Values(userID, token, createdAt, expiresAt).
SQL()
if err != nil {
return err
}
_, err = r.db.Exec(ctx, query, aggs...)
return err
}
func (r *VerificationTokenRepo) GetUserIDByTokenAndMarkAsUsed(
ctx context.Context,
token string,
usedAt time.Time,
) (uuid.UUID, error) {
tx, err := r.db.Begin(ctx)
if err != nil {
return uuid.Nil, err
}
defer tx.Rollback(ctx) //nolint:errcheck
var isUsed bool
err = tx.QueryRow(ctx, "select used_at is not null from verification_tokens where token = $1", token).
Scan(&isUsed)
if err != nil {
return uuid.Nil, err
}
if isUsed {
return uuid.Nil, models.ErrUserIsAlreadyVerified
}
query := `--sql
update verification_tokens
set used_at = $1
where token = $2
returning user_id`
var userID uuid.UUID
err = tx.QueryRow(ctx, query, usedAt, token).Scan(&userID)
if err != nil {
return uuid.Nil, err
}
return userID, tx.Commit(ctx)
}
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
}
|