From 3e0ff9da363f3cba76f8ad9e6dbf2ffefb513086 Mon Sep 17 00:00:00 2001 From: cukhoaimon Date: Thu, 1 Feb 2024 15:45:31 +0700 Subject: [PATCH] feat: add user table and unit test for it --- .idea/sqldialects.xml | 1 + db/query/user.sql | 13 ++++++++ db/sqlc/models.go | 9 ++++++ db/sqlc/querier.go | 2 ++ db/sqlc/user.sql.go | 66 ++++++++++++++++++++++++++++++++++++++++ db/sqlc/user.sql_test.go | 45 +++++++++++++++++++++++++++ utils/random.go | 13 ++++++-- 7 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 db/query/user.sql create mode 100644 db/sqlc/user.sql.go create mode 100644 db/sqlc/user.sql_test.go diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index dd349b0..b6f6d98 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -3,5 +3,6 @@ + \ No newline at end of file diff --git a/db/query/user.sql b/db/query/user.sql new file mode 100644 index 0000000..0ed71c2 --- /dev/null +++ b/db/query/user.sql @@ -0,0 +1,13 @@ +-- name: CreateUser :one +INSERT INTO users ( + "username", + "hashed_password", + "full_name", + "email" +) VALUES ( + $1, $2, $3, $4 +) RETURNING *; + +-- name: GetUser :one +SELECT * FROM users +WHERE username = $1 LIMIT 1; diff --git a/db/sqlc/models.go b/db/sqlc/models.go index 4db68dd..ae9f3fb 100644 --- a/db/sqlc/models.go +++ b/db/sqlc/models.go @@ -32,3 +32,12 @@ type Transfer struct { Amount int64 `json:"amount"` CreatedAt time.Time `json:"created_at"` } + +type User struct { + Username string `json:"username"` + HashedPassword string `json:"hashed_password"` + FullName string `json:"full_name"` + Email string `json:"email"` + PasswordChangedAt time.Time `json:"password_changed_at"` + CreatedAt time.Time `json:"created_at"` +} diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 7ae515b..0aa5519 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -13,11 +13,13 @@ type Querier interface { CreateAccount(ctx context.Context, arg CreateAccountParams) (Account, error) CreateEntry(ctx context.Context, arg CreateEntryParams) (Entry, error) CreateTransfer(ctx context.Context, arg CreateTransferParams) (Transfer, error) + CreateUser(ctx context.Context, arg CreateUserParams) (User, error) DeleteAccount(ctx context.Context, id int64) error GetAccount(ctx context.Context, id int64) (Account, error) GetAccountForUpdate(ctx context.Context, id int64) (Account, error) GetEntry(ctx context.Context, id int64) (Entry, error) GetTransfer(ctx context.Context, id int64) (Transfer, error) + GetUser(ctx context.Context, username string) (User, error) ListAccounts(ctx context.Context, arg ListAccountsParams) ([]Account, error) ListEntries(ctx context.Context, arg ListEntriesParams) ([]Entry, error) ListTransfers(ctx context.Context, arg ListTransfersParams) ([]Transfer, error) diff --git a/db/sqlc/user.sql.go b/db/sqlc/user.sql.go new file mode 100644 index 0000000..5eddaa9 --- /dev/null +++ b/db/sqlc/user.sql.go @@ -0,0 +1,66 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.25.0 +// source: user.sql + +package db + +import ( + "context" +) + +const createUser = `-- name: CreateUser :one +INSERT INTO users ( + "username", + "hashed_password", + "full_name", + "email" +) VALUES ( + $1, $2, $3, $4 +) RETURNING username, hashed_password, full_name, email, 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.QueryRowContext(ctx, createUser, + arg.Username, + arg.HashedPassword, + arg.FullName, + arg.Email, + ) + var i User + err := row.Scan( + &i.Username, + &i.HashedPassword, + &i.FullName, + &i.Email, + &i.PasswordChangedAt, + &i.CreatedAt, + ) + return i, err +} + +const getUser = `-- name: GetUser :one +SELECT username, hashed_password, full_name, email, 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.QueryRowContext(ctx, getUser, username) + var i User + err := row.Scan( + &i.Username, + &i.HashedPassword, + &i.FullName, + &i.Email, + &i.PasswordChangedAt, + &i.CreatedAt, + ) + return i, err +} diff --git a/db/sqlc/user.sql_test.go b/db/sqlc/user.sql_test.go new file mode 100644 index 0000000..d3578a3 --- /dev/null +++ b/db/sqlc/user.sql_test.go @@ -0,0 +1,45 @@ +package db + +import ( + "context" + "github.com/cukhoaimon/SimpleBank/utils" + "github.com/stretchr/testify/require" + "testing" +) + +func createRandomUser(t *testing.T) User { + arg := CreateUserParams{ + Username: utils.RandomOwner(), + HashedPassword: "secret", + FullName: utils.RandomOwner(), + Email: utils.RandomEmail(), + } + + user, err := testQuery.CreateUser(context.Background(), arg) + + require.Nil(t, err) + require.NotEmpty(t, user) + + require.Equal(t, arg.Username, user.Username) + require.Equal(t, arg.FullName, user.FullName) + require.Equal(t, arg.Email, user.Email) + require.Equal(t, arg.HashedPassword, user.HashedPassword) + + require.True(t, user.PasswordChangedAt.IsZero()) + require.NotZero(t, user.CreatedAt) + + return user +} + +func TestQueries_CreateUser(t *testing.T) { + createRandomUser(t) +} + +func TestQueries_GetUser(t *testing.T) { + want := createRandomUser(t) + + have, err := testQuery.GetUser(context.Background(), want.Username) + + require.Nil(t, err) + require.Equal(t, want, have) +} diff --git a/utils/random.go b/utils/random.go index 2c85b8e..1ef7b3a 100644 --- a/utils/random.go +++ b/utils/random.go @@ -1,6 +1,7 @@ package utils import ( + "fmt" "math/rand" "strings" "time" @@ -17,7 +18,7 @@ func RandomInt(min, max int64) int64 { return min + rand.Int63n(max-min+1) } -// RandomString +// RandomString return a random string with input length func RandomString(n int) string { var sb strings.Builder @@ -30,16 +31,24 @@ func RandomString(n int) string { return sb.String() } +// RandomOwner return a string length 6 func RandomOwner() string { return RandomString(6) } +// RandomMoney return an integer between 0-10000 func RandomMoney() int64 { return RandomInt(0, 10000) } +// RandomCurrency return supported currency func RandomCurrency() string { - currencies := []string{"USD", "VND", "EUR"} + currencies := []string{USD, VND, EUR} n := len(currencies) return currencies[rand.Intn(n)] } + +// RandomEmail return an email length 6 +func RandomEmail() string { + return fmt.Sprintf("%s@gmail.com", RandomOwner()) +}