feat: 0.0.1
This commit is contained in:
146 files changed
+10444
No files matched your search
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
const (
|
||||
ForeignKeyViolation = "23503"
|
||||
UniqueViolation = "23505"
|
||||
CheckViolation = "23514"
|
||||
)
|
||||
|
||||
var ErrRecordNotFound = pgx.ErrNoRows
|
||||
|
||||
var ErrUniqueViolation = &pgconn.PgError{
|
||||
Code: UniqueViolation,
|
||||
}
|
||||
var ErrForeignKeyViolation = &pgconn.PgError{
|
||||
Code: ForeignKeyViolation,
|
||||
}
|
||||
var ErrCheckViolation = &pgconn.PgError{
|
||||
Code: CheckViolation,
|
||||
}
|
||||
|
||||
func ErrorCode(err error) string {
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) {
|
||||
return pgErr.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// execTx executes a function within a database transaction
|
||||
func (store *PostgresStore) execTx(ctx context.Context, fn func(*Queries) error) error {
|
||||
tx, err := store.connPool.Begin(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q := New(tx)
|
||||
|
||||
err = fn(q)
|
||||
if err != nil {
|
||||
if rbErr := tx.Rollback(ctx); rbErr != nil {
|
||||
return fmt.Errorf("tx err: %v, rb err: %v", err, rbErr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/FernandoJVideira/simple_bank/internal/config"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
)
|
||||
|
||||
var testStore Store
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
config, err := config.LoadTestConfig("../../..")
|
||||
if err != nil {
|
||||
log.Fatal("cannot load config:", err)
|
||||
}
|
||||
|
||||
connPool, err := pgxpool.New(context.Background(), config.DBAddr)
|
||||
if err != nil {
|
||||
log.Fatal("cannot connect to db:", err)
|
||||
}
|
||||
|
||||
testStore = NewPostgresStore(connPool)
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Username string `json:"username"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
ClientIp string `json:"client_ip"`
|
||||
IsBlocked bool `json:"is_blocked"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
HashedPassword string `json:"hashed_password"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
IsEmailVerified bool `json:"is_email_verified"`
|
||||
PasswordChangedAt time.Time `json:"password_changed_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type VerifyEmail struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
SecretCode string `json:"secret_code"`
|
||||
IsUsed bool `json:"is_used"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error)
|
||||
CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
|
||||
CreateVerifyEmail(ctx context.Context, arg CreateVerifyEmailParams) (VerifyEmail, error)
|
||||
GetSession(ctx context.Context, id uuid.UUID) (Session, error)
|
||||
GetUser(ctx context.Context, username string) (User, error)
|
||||
UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error)
|
||||
UpdateVerifyEmail(ctx context.Context, arg UpdateVerifyEmailParams) (VerifyEmail, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
||||
@@ -0,0 +1,83 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: sessions.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createSession = `-- name: CreateSession :one
|
||||
INSERT INTO sessions (
|
||||
id,
|
||||
username,
|
||||
refresh_token,
|
||||
user_agent,
|
||||
client_ip,
|
||||
is_blocked,
|
||||
expires_at
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
)
|
||||
RETURNING id, username, refresh_token, user_agent, client_ip, is_blocked, expires_at, created_at
|
||||
`
|
||||
|
||||
type CreateSessionParams struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Username string `json:"username"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
ClientIp string `json:"client_ip"`
|
||||
IsBlocked bool `json:"is_blocked"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error) {
|
||||
row := q.db.QueryRow(ctx, createSession,
|
||||
arg.ID,
|
||||
arg.Username,
|
||||
arg.RefreshToken,
|
||||
arg.UserAgent,
|
||||
arg.ClientIp,
|
||||
arg.IsBlocked,
|
||||
arg.ExpiresAt,
|
||||
)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.RefreshToken,
|
||||
&i.UserAgent,
|
||||
&i.ClientIp,
|
||||
&i.IsBlocked,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSession = `-- name: GetSession :one
|
||||
SELECT id, username, refresh_token, user_agent, client_ip, is_blocked, expires_at, created_at FROM sessions
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSession(ctx context.Context, id uuid.UUID) (Session, error) {
|
||||
row := q.db.QueryRow(ctx, getSession, id)
|
||||
var i Session
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.RefreshToken,
|
||||
&i.UserAgent,
|
||||
&i.ClientIp,
|
||||
&i.IsBlocked,
|
||||
&i.ExpiresAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
Querier
|
||||
CreateUserTx(ctx context.Context, arg CreateUserTxParams) (CreateUserTxResult, error)
|
||||
VerifyEmailTx(ctx context.Context, arg VerifyEmailTxParams) (VerifyEmailTxResult, error)
|
||||
}
|
||||
|
||||
// PostgresStore provides all functions to execute db queries and transactions
|
||||
type PostgresStore struct {
|
||||
*Queries
|
||||
connPool *pgxpool.Pool
|
||||
}
|
||||
|
||||
// NewPostgresStore creates a new Store
|
||||
func NewPostgresStore(connPool *pgxpool.Pool) Store {
|
||||
return &PostgresStore{
|
||||
connPool: connPool,
|
||||
Queries: New(connPool),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type CreateUserTxParams struct {
|
||||
CreateUserParams
|
||||
AfterCreate func(user User) error
|
||||
}
|
||||
|
||||
type CreateUserTxResult struct {
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
func (store *PostgresStore) 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
|
||||
}
|
||||
|
||||
log.Info().Msgf("user %s created successfully", result.User.Username)
|
||||
|
||||
return arg.AfterCreate(result.User)
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type VerifyEmailTxParams struct {
|
||||
EmailID int64
|
||||
SecretCode string
|
||||
}
|
||||
|
||||
type VerifyEmailTxResult struct {
|
||||
User User
|
||||
VerifyEmail VerifyEmail
|
||||
}
|
||||
|
||||
func (store *PostgresStore) VerifyEmailTx(ctx context.Context, arg VerifyEmailTxParams) (VerifyEmailTxResult, error) {
|
||||
var result VerifyEmailTxResult
|
||||
|
||||
err := store.execTx(ctx, func(q *Queries) error {
|
||||
var err error
|
||||
|
||||
result.VerifyEmail, err = q.UpdateVerifyEmail(ctx, UpdateVerifyEmailParams{
|
||||
ID: arg.EmailID,
|
||||
SecretCode: arg.SecretCode,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result.User, err = q.UpdateUser(ctx, UpdateUserParams{
|
||||
Username: result.VerifyEmail.Username,
|
||||
IsEmailVerified: pgtype.Bool{
|
||||
Bool: true,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
|
||||
return err
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: user.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createUser = `-- name: CreateUser :one
|
||||
INSERT INTO users (
|
||||
username,
|
||||
hashed_password,
|
||||
full_name,
|
||||
email
|
||||
) VALUES (
|
||||
$1, $2, $3, $4
|
||||
)
|
||||
RETURNING username, role, hashed_password, full_name, email, is_email_verified, password_changed_at, created_at
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
Username string `json:"username"`
|
||||
HashedPassword string `json:"hashed_password"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
|
||||
row := q.db.QueryRow(ctx, createUser,
|
||||
arg.Username,
|
||||
arg.HashedPassword,
|
||||
arg.FullName,
|
||||
arg.Email,
|
||||
)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.Role,
|
||||
&i.HashedPassword,
|
||||
&i.FullName,
|
||||
&i.Email,
|
||||
&i.IsEmailVerified,
|
||||
&i.PasswordChangedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUser = `-- name: GetUser :one
|
||||
SELECT username, role, hashed_password, full_name, email, is_email_verified, password_changed_at, created_at FROM users
|
||||
WHERE username = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUser(ctx context.Context, username string) (User, error) {
|
||||
row := q.db.QueryRow(ctx, getUser, username)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.Role,
|
||||
&i.HashedPassword,
|
||||
&i.FullName,
|
||||
&i.Email,
|
||||
&i.IsEmailVerified,
|
||||
&i.PasswordChangedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateUser = `-- name: UpdateUser :one
|
||||
UPDATE users
|
||||
SET
|
||||
hashed_password = COALESCE($1, hashed_password),
|
||||
password_changed_at = COALESCE($2, password_changed_at),
|
||||
full_name = COALESCE($3, full_name),
|
||||
email = COALESCE($4, email),
|
||||
is_email_verified = COALESCE($5, is_email_verified)
|
||||
WHERE username = $6
|
||||
RETURNING username, role, hashed_password, full_name, email, is_email_verified, password_changed_at, created_at
|
||||
`
|
||||
|
||||
type UpdateUserParams struct {
|
||||
HashedPassword pgtype.Text `json:"hashed_password"`
|
||||
PasswordChangedAt pgtype.Timestamptz `json:"password_changed_at"`
|
||||
FullName pgtype.Text `json:"full_name"`
|
||||
Email pgtype.Text `json:"email"`
|
||||
IsEmailVerified pgtype.Bool `json:"is_email_verified"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error) {
|
||||
row := q.db.QueryRow(ctx, updateUser,
|
||||
arg.HashedPassword,
|
||||
arg.PasswordChangedAt,
|
||||
arg.FullName,
|
||||
arg.Email,
|
||||
arg.IsEmailVerified,
|
||||
arg.Username,
|
||||
)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.Username,
|
||||
&i.Role,
|
||||
&i.HashedPassword,
|
||||
&i.FullName,
|
||||
&i.Email,
|
||||
&i.IsEmailVerified,
|
||||
&i.PasswordChangedAt,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/FernandoJVideira/simple_bank/internal/security"
|
||||
"github.com/FernandoJVideira/simple_bank/pkg/testutil"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func createRandomUser(t *testing.T) User {
|
||||
hashedPassword, err := security.HashPassword(testutil.RandomString(6))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create the user
|
||||
arg := CreateUserParams{
|
||||
Username: testutil.RandomOwner(),
|
||||
HashedPassword: hashedPassword,
|
||||
FullName: testutil.RandomOwner(),
|
||||
Email: testutil.RandomEmail(),
|
||||
}
|
||||
user, err := testStore.CreateUser(context.Background(), arg)
|
||||
require.NoError(t, err) // -> Err should be nil
|
||||
require.NotEmpty(t, user)
|
||||
|
||||
require.Equal(t, arg.Username, user.Username)
|
||||
require.Equal(t, arg.HashedPassword, user.HashedPassword)
|
||||
require.Equal(t, arg.FullName, user.FullName)
|
||||
require.Equal(t, arg.Email, user.Email)
|
||||
|
||||
require.True(t, user.PasswordChangedAt.IsZero())
|
||||
require.NotZero(t, user.CreatedAt)
|
||||
return user
|
||||
}
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
createRandomUser(t)
|
||||
}
|
||||
|
||||
func TestGetUser(t *testing.T) {
|
||||
user1 := createRandomUser(t)
|
||||
user2, err := testStore.GetUser(context.Background(), user1.Username)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, user2)
|
||||
|
||||
require.Equal(t, user1.Username, user2.Username)
|
||||
require.Equal(t, user1.HashedPassword, user2.HashedPassword)
|
||||
require.Equal(t, user1.FullName, user2.FullName)
|
||||
require.Equal(t, user1.Email, user2.Email)
|
||||
require.WithinDuration(t, user1.CreatedAt, user2.CreatedAt, time.Second)
|
||||
}
|
||||
|
||||
func TestUpdateUserOnlyFullName(t *testing.T) {
|
||||
oldUser := createRandomUser(t)
|
||||
|
||||
newFullName := testutil.RandomOwner()
|
||||
updatedUser, err := testStore.UpdateUser(context.Background(), UpdateUserParams{
|
||||
Username: oldUser.Username,
|
||||
FullName: pgtype.Text{
|
||||
String: newFullName,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, oldUser.FullName, updatedUser.FullName)
|
||||
require.Equal(t, newFullName, updatedUser.FullName)
|
||||
require.Equal(t, oldUser.HashedPassword, updatedUser.HashedPassword)
|
||||
require.Equal(t, oldUser.Email, updatedUser.Email)
|
||||
}
|
||||
|
||||
func TestUpdateUserOnlyEmail(t *testing.T) {
|
||||
oldUser := createRandomUser(t)
|
||||
|
||||
newEmail := testutil.RandomEmail()
|
||||
updatedUser, err := testStore.UpdateUser(context.Background(), UpdateUserParams{
|
||||
Username: oldUser.Username,
|
||||
Email: pgtype.Text{
|
||||
String: newEmail,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, oldUser.Email, updatedUser.Email)
|
||||
require.Equal(t, newEmail, updatedUser.Email)
|
||||
require.Equal(t, oldUser.HashedPassword, updatedUser.HashedPassword)
|
||||
require.Equal(t, oldUser.FullName, updatedUser.FullName)
|
||||
}
|
||||
|
||||
func TestUpdateUserOnlyPassword(t *testing.T) {
|
||||
oldUser := createRandomUser(t)
|
||||
|
||||
newPassword, err := security.HashPassword(testutil.RandomString(6))
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedUser, err := testStore.UpdateUser(context.Background(), UpdateUserParams{
|
||||
Username: oldUser.Username,
|
||||
HashedPassword: pgtype.Text{
|
||||
String: newPassword,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, oldUser.HashedPassword, updatedUser.HashedPassword)
|
||||
require.Equal(t, newPassword, updatedUser.HashedPassword)
|
||||
require.Equal(t, oldUser.FullName, updatedUser.FullName)
|
||||
require.Equal(t, oldUser.Email, updatedUser.Email)
|
||||
}
|
||||
|
||||
func TestUpdateUserAllFields(t *testing.T) {
|
||||
oldUser := createRandomUser(t)
|
||||
|
||||
newFullName := testutil.RandomOwner()
|
||||
newEmail := testutil.RandomEmail()
|
||||
newPassword, err := security.HashPassword(testutil.RandomString(6))
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedUser, err := testStore.UpdateUser(context.Background(), UpdateUserParams{
|
||||
Username: oldUser.Username,
|
||||
FullName: pgtype.Text{
|
||||
String: newFullName,
|
||||
Valid: true,
|
||||
},
|
||||
Email: pgtype.Text{
|
||||
String: newEmail,
|
||||
Valid: true,
|
||||
},
|
||||
HashedPassword: pgtype.Text{
|
||||
String: newPassword,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEqual(t, oldUser.FullName, updatedUser.FullName)
|
||||
require.Equal(t, newFullName, updatedUser.FullName)
|
||||
|
||||
require.NotEqual(t, oldUser.HashedPassword, updatedUser.HashedPassword)
|
||||
require.Equal(t, newPassword, updatedUser.HashedPassword)
|
||||
|
||||
require.NotEqual(t, oldUser.Email, updatedUser.Email)
|
||||
require.Equal(t, newEmail, updatedUser.Email)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: verify_email.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createVerifyEmail = `-- name: CreateVerifyEmail :one
|
||||
INSERT INTO verify_emails (
|
||||
username,
|
||||
email,
|
||||
secret_code
|
||||
) VALUES (
|
||||
$1, $2, $3
|
||||
)
|
||||
RETURNING id, username, email, secret_code, is_used, created_at, expired_at
|
||||
`
|
||||
|
||||
type CreateVerifyEmailParams struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
SecretCode string `json:"secret_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateVerifyEmail(ctx context.Context, arg CreateVerifyEmailParams) (VerifyEmail, error) {
|
||||
row := q.db.QueryRow(ctx, createVerifyEmail, arg.Username, arg.Email, arg.SecretCode)
|
||||
var i VerifyEmail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.Email,
|
||||
&i.SecretCode,
|
||||
&i.IsUsed,
|
||||
&i.CreatedAt,
|
||||
&i.ExpiredAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateVerifyEmail = `-- name: UpdateVerifyEmail :one
|
||||
UPDATE verify_emails
|
||||
SET
|
||||
is_used = TRUE
|
||||
WHERE
|
||||
id = $1
|
||||
AND secret_code = $2
|
||||
AND is_used = FALSE
|
||||
AND expired_at > NOW()
|
||||
RETURNING id, username, email, secret_code, is_used, created_at, expired_at
|
||||
`
|
||||
|
||||
type UpdateVerifyEmailParams struct {
|
||||
ID int64 `json:"id"`
|
||||
SecretCode string `json:"secret_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateVerifyEmail(ctx context.Context, arg UpdateVerifyEmailParams) (VerifyEmail, error) {
|
||||
row := q.db.QueryRow(ctx, updateVerifyEmail, arg.ID, arg.SecretCode)
|
||||
var i VerifyEmail
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.Email,
|
||||
&i.SecretCode,
|
||||
&i.IsUsed,
|
||||
&i.CreatedAt,
|
||||
&i.ExpiredAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
Reference in new issue
Block a user