add user and password hash
This commit is contained in:
parent
85dd2a3134
commit
d05b501360
3
Makefile
3
Makefile
@ -9,9 +9,8 @@ migratedown:
|
||||
mock-generate:
|
||||
mockgen -package mockdb -destination db/mock/store.go git.nochill.in/nochill/naice_pos/db/sqlc Store
|
||||
|
||||
|
||||
sqlc:
|
||||
sqlc generate
|
||||
sqlc generate && make mock-generate
|
||||
|
||||
test:
|
||||
go test -v -cover ./...
|
||||
|
@ -109,7 +109,7 @@ func TestGetProductApi(t *testing.T) {
|
||||
func randomProduct() db.Product {
|
||||
return db.Product{
|
||||
ID: uuid.New(),
|
||||
MerchantID: uuid.MustParse("d9b0e126-991e-46ac-8c61-5efdd605f75d"),
|
||||
MerchantID: uuid.MustParse("a848090f-0409-4386-9caa-929ae6874dbb"),
|
||||
Name: util.RandomString(5),
|
||||
SellingPrice: util.RandomFloat(1000, 99999),
|
||||
PurchasePrice: util.RandomFloat(999, 9999),
|
||||
|
@ -14,6 +14,7 @@ func NewServer(store db.Store) *Server {
|
||||
server := &Server{store: store}
|
||||
router := gin.Default()
|
||||
|
||||
router.POST("/merchants", server.createUser)
|
||||
router.POST("/products", server.createProduct)
|
||||
router.PATCH("/products", server.updateProduct)
|
||||
router.GET("/product/:id", server.getProduct)
|
||||
|
69
api/user.go
Normal file
69
api/user.go
Normal file
@ -0,0 +1,69 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
db "git.nochill.in/nochill/naice_pos/db/sqlc"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
type createUserRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Fullname string `json:"fullname" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
OutletName string `json:"outlet_name" binding:"required"`
|
||||
}
|
||||
|
||||
type createUserResponse struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Email string `json:"email"`
|
||||
Fullname string `json:"fullname"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
Outlet db.Merchant `json:"outlet"`
|
||||
}
|
||||
|
||||
func (server *Server) createUser(ctx *gin.Context) {
|
||||
var req createUserRequest
|
||||
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
ctx.JSON(http.StatusBadRequest, errorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
arg := db.UserMerchantTxParams{
|
||||
Email: req.Email,
|
||||
Fullname: req.Fullname,
|
||||
Password: req.Password,
|
||||
OutletName: req.OutletName,
|
||||
}
|
||||
|
||||
user, err := server.store.CreateUserMerchantTx(ctx, arg)
|
||||
if err != nil {
|
||||
if pqErr, ok := err.(*pq.Error); ok {
|
||||
switch pqErr.Code.Name() {
|
||||
case "foreign_key_violation", "unique_violation":
|
||||
ctx.JSON(http.StatusConflict, errorResponse(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
res := createUserResponse{
|
||||
ID: user.OwnerProfile.ID,
|
||||
IndexID: user.OwnerProfile.IndexID,
|
||||
Email: user.OwnerProfile.Email,
|
||||
Fullname: user.OwnerProfile.Fullname,
|
||||
CreatedAt: sql.NullTime{Valid: true, Time: user.OutletProfile.CreatedAt.Time},
|
||||
UpdatedAt: sql.NullTime{Valid: true, Time: user.OutletProfile.UpdatedAt.Time},
|
||||
Outlet: user.OutletProfile,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
1
api/user_test.go
Normal file
1
api/user_test.go
Normal file
@ -0,0 +1 @@
|
||||
package api
|
@ -3,7 +3,7 @@ CREATE TABLE users(
|
||||
"index_id" bigserial not null,
|
||||
"email" varchar unique not null,
|
||||
"password" varchar not null,
|
||||
"fullname" varchar,
|
||||
"fullname" varchar not null,
|
||||
"created_at" timestamp default(now()),
|
||||
"updated_at" timestamp default(now())
|
||||
);
|
||||
|
@ -51,6 +51,21 @@ func (mr *MockStoreMockRecorder) CreateCustomers(arg0, arg1 interface{}) *gomock
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCustomers", reflect.TypeOf((*MockStore)(nil).CreateCustomers), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateMerchant mocks base method.
|
||||
func (m *MockStore) CreateMerchant(arg0 context.Context, arg1 db.CreateMerchantParams) (db.Merchant, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateMerchant", arg0, arg1)
|
||||
ret0, _ := ret[0].(db.Merchant)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateMerchant indicates an expected call of CreateMerchant.
|
||||
func (mr *MockStoreMockRecorder) CreateMerchant(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMerchant", reflect.TypeOf((*MockStore)(nil).CreateMerchant), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateProduct mocks base method.
|
||||
func (m *MockStore) CreateProduct(arg0 context.Context, arg1 db.CreateProductParams) (db.Product, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -111,6 +126,36 @@ func (mr *MockStoreMockRecorder) CreateSuppliers(arg0, arg1 interface{}) *gomock
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSuppliers", reflect.TypeOf((*MockStore)(nil).CreateSuppliers), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateUser mocks base method.
|
||||
func (m *MockStore) CreateUser(arg0 context.Context, arg1 db.CreateUserParams) (db.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateUser", arg0, arg1)
|
||||
ret0, _ := ret[0].(db.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateUser indicates an expected call of CreateUser.
|
||||
func (mr *MockStoreMockRecorder) CreateUser(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateUserMerchantTx mocks base method.
|
||||
func (m *MockStore) CreateUserMerchantTx(arg0 context.Context, arg1 db.UserMerchantTxParams) (db.UserMerchantTxResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateUserMerchantTx", arg0, arg1)
|
||||
ret0, _ := ret[0].(db.UserMerchantTxResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateUserMerchantTx indicates an expected call of CreateUserMerchantTx.
|
||||
func (mr *MockStoreMockRecorder) CreateUserMerchantTx(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUserMerchantTx", reflect.TypeOf((*MockStore)(nil).CreateUserMerchantTx), arg0, arg1)
|
||||
}
|
||||
|
||||
// CustomersList mocks base method.
|
||||
func (m *MockStore) CustomersList(arg0 context.Context, arg1 db.CustomersListParams) ([]db.Customer, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -198,6 +243,21 @@ func (mr *MockStoreMockRecorder) GetMerchantByUserId(arg0, arg1 interface{}) *go
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMerchantByUserId", reflect.TypeOf((*MockStore)(nil).GetMerchantByUserId), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetPasswordByEmail mocks base method.
|
||||
func (m *MockStore) GetPasswordByEmail(arg0 context.Context, arg1 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPasswordByEmail", arg0, arg1)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetPasswordByEmail indicates an expected call of GetPasswordByEmail.
|
||||
func (mr *MockStoreMockRecorder) GetPasswordByEmail(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPasswordByEmail", reflect.TypeOf((*MockStore)(nil).GetPasswordByEmail), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetProduct mocks base method.
|
||||
func (m *MockStore) GetProduct(arg0 context.Context, arg1 uuid.UUID) (db.Product, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@ -228,6 +288,21 @@ func (mr *MockStoreMockRecorder) GetStockForUpdateStock(arg0, arg1 interface{})
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStockForUpdateStock", reflect.TypeOf((*MockStore)(nil).GetStockForUpdateStock), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetUserById mocks base method.
|
||||
func (m *MockStore) GetUserById(arg0 context.Context, arg1 uuid.UUID) (db.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserById", arg0, arg1)
|
||||
ret0, _ := ret[0].(db.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserById indicates an expected call of GetUserById.
|
||||
func (mr *MockStoreMockRecorder) GetUserById(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserById", reflect.TypeOf((*MockStore)(nil).GetUserById), arg0, arg1)
|
||||
}
|
||||
|
||||
// ListProducts mocks base method.
|
||||
func (m *MockStore) ListProducts(arg0 context.Context, arg1 db.ListProductsParams) ([]db.Product, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -1,3 +1,8 @@
|
||||
-- name: CreateMerchant :one
|
||||
INSERT INTO merchants (name,owner_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetMerchantById :one
|
||||
SELECT * FROM merchants
|
||||
WHERE id = $1;
|
@ -9,11 +9,9 @@ RETURNING *;
|
||||
-- name: GetPasswordByEmail :one
|
||||
SELECT password
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
RETURNING password;
|
||||
WHERE email = $1;
|
||||
|
||||
-- name: GetUserById :one
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
WHERE id = $1;
|
@ -1,7 +1,7 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: merchant.sql
|
||||
// source: merchants.sql
|
||||
|
||||
package db
|
||||
|
||||
@ -11,6 +11,31 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createMerchant = `-- name: CreateMerchant :one
|
||||
INSERT INTO merchants (name,owner_id)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, index_id, name, owner_id, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateMerchantParams struct {
|
||||
Name string `json:"name"`
|
||||
OwnerID uuid.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateMerchant(ctx context.Context, arg CreateMerchantParams) (Merchant, error) {
|
||||
row := q.db.QueryRowContext(ctx, createMerchant, arg.Name, arg.OwnerID)
|
||||
var i Merchant
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Name,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getMerchantById = `-- name: GetMerchantById :one
|
||||
SELECT id, index_id, name, owner_id, created_at, updated_at FROM merchants
|
||||
WHERE id = $1
|
1
db/sqlc/merchants_test.go
Normal file
1
db/sqlc/merchants_test.go
Normal file
@ -0,0 +1 @@
|
||||
package db
|
@ -114,7 +114,7 @@ type User struct {
|
||||
IndexID int64 `json:"index_id"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Fullname sql.NullString `json:"fullname"`
|
||||
Fullname string `json:"fullname"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func createRandomProduct(t *testing.T) (Product, CreateProductParams) {
|
||||
stock := util.RandomFloat(10, 10000)
|
||||
|
||||
arg := CreateProductParams{
|
||||
MerchantID: uuid.MustParse("d9b0e126-991e-46ac-8c61-5efdd605f75d"),
|
||||
MerchantID: uuid.MustParse("a848090f-0409-4386-9caa-929ae6874dbb"),
|
||||
Name: util.RandomString(10),
|
||||
SellingPrice: sellingPrice,
|
||||
PurchasePrice: purchasePrice,
|
||||
|
@ -12,18 +12,22 @@ import (
|
||||
|
||||
type Querier interface {
|
||||
CreateCustomers(ctx context.Context, arg CreateCustomersParams) (Customer, error)
|
||||
CreateMerchant(ctx context.Context, arg CreateMerchantParams) (Merchant, error)
|
||||
CreateProduct(ctx context.Context, arg CreateProductParams) (Product, error)
|
||||
CreatePurchaseOrder(ctx context.Context, arg CreatePurchaseOrderParams) (PurchaseOrder, error)
|
||||
CreatePurchaseOrderDetail(ctx context.Context, arg CreatePurchaseOrderDetailParams) (PurchaseOrderDetail, error)
|
||||
CreateSuppliers(ctx context.Context, arg CreateSuppliersParams) (Supplier, error)
|
||||
CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
|
||||
CustomersList(ctx context.Context, arg CustomersListParams) ([]Customer, error)
|
||||
DeleteCustomer(ctx context.Context, id uuid.UUID) error
|
||||
DeleteProduct(ctx context.Context, id uuid.UUID) error
|
||||
DeleteSupplier(ctx context.Context, id uuid.UUID) error
|
||||
GetMerchantById(ctx context.Context, id uuid.UUID) (Merchant, error)
|
||||
GetMerchantByUserId(ctx context.Context, ownerID uuid.UUID) (Merchant, error)
|
||||
GetPasswordByEmail(ctx context.Context, email string) (string, error)
|
||||
GetProduct(ctx context.Context, id uuid.UUID) (Product, error)
|
||||
GetStockForUpdateStock(ctx context.Context, id uuid.UUID) (Product, error)
|
||||
GetUserById(ctx context.Context, id uuid.UUID) (User, error)
|
||||
ListProducts(ctx context.Context, arg ListProductsParams) ([]Product, error)
|
||||
SuppliersList(ctx context.Context, arg SuppliersListParams) ([]Supplier, error)
|
||||
UpdateCustomer(ctx context.Context, id uuid.UUID) (Customer, error)
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
type Store interface {
|
||||
Querier
|
||||
PurchaseOrderTx(ctx context.Context, arg PurchasoOrderTxParams) (PurchaseOrderTxResult, error)
|
||||
CreateUserMerchantTx(ctx context.Context, arg UserMerchantTxParams) (UserMerchantTxResult, error)
|
||||
}
|
||||
|
||||
type SQLStore struct {
|
||||
@ -126,3 +127,46 @@ func (store *SQLStore) PurchaseOrderTx(ctx context.Context, arg PurchasoOrderTxP
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
type UserMerchantTxParams struct {
|
||||
Email string `json:"email"`
|
||||
Fullname string `json:"fullname"`
|
||||
Password string `json:"password"`
|
||||
OutletName string `json:"outlet_name"`
|
||||
}
|
||||
|
||||
type UserMerchantTxResult struct {
|
||||
OwnerProfile User `json:"owner_profile"`
|
||||
OutletProfile Merchant `json:"outlet_profile"`
|
||||
}
|
||||
|
||||
func (store *SQLStore) CreateUserMerchantTx(ctx context.Context, arg UserMerchantTxParams) (UserMerchantTxResult, error) {
|
||||
var result UserMerchantTxResult
|
||||
err := store.execTx(ctx, func(q *Queries) error {
|
||||
var err error
|
||||
|
||||
result.OwnerProfile, err = q.CreateUser(ctx, CreateUserParams{
|
||||
Email: arg.Email,
|
||||
Password: arg.Password,
|
||||
Fullname: arg.Fullname,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result.OutletProfile, err = q.CreateMerchant(ctx, CreateMerchantParams{
|
||||
Name: arg.OutletName,
|
||||
OwnerID: result.OwnerProfile.ID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return result, err
|
||||
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ func TestPurchaseOrder(t *testing.T) {
|
||||
|
||||
products = append(products, purchaseProducts_1, purchaseProducts_2)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
tries := 3
|
||||
|
||||
for i := 0; i < tries; i++ {
|
||||
go func() {
|
||||
result, err := store.PurchaseOrderTx(context.Background(), PurchasoOrderTxParams{
|
||||
MerchantID: supplier.MerchantID,
|
||||
@ -61,7 +63,7 @@ func TestPurchaseOrder(t *testing.T) {
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
for i := 0; i < tries; i++ {
|
||||
err := <-errs
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -75,3 +77,38 @@ func TestPurchaseOrder(t *testing.T) {
|
||||
require.NotZero(t, purchaseOrder.PaidNominal, product1.PurchasePrice+product2.PurchasePrice)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUserMerchant(t *testing.T) {
|
||||
store := NewStore(testDB)
|
||||
|
||||
errs := make(chan error)
|
||||
results := make(chan UserMerchantTxResult)
|
||||
|
||||
tries := 3
|
||||
|
||||
for i := 0; i < tries; i++ {
|
||||
randString := util.RandomString(10)
|
||||
password, err := util.HashPassword(randString)
|
||||
require.NoError(t, err)
|
||||
|
||||
go func() {
|
||||
result, err := store.CreateUserMerchantTx(context.Background(), UserMerchantTxParams{
|
||||
Email: util.RandomEmail(),
|
||||
Fullname: util.RandomString(6),
|
||||
Password: password,
|
||||
OutletName: util.RandomString(6),
|
||||
})
|
||||
errs <- err
|
||||
results <- result
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < tries; i++ {
|
||||
err := <-errs
|
||||
require.NoError(t, err)
|
||||
|
||||
result := <-results
|
||||
require.NotEmpty(t, result)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
func createRandomSupplier(t *testing.T) (Supplier, CreateSuppliersParams) {
|
||||
arg := CreateSuppliersParams{
|
||||
MerchantID: uuid.MustParse("d9b0e126-991e-46ac-8c61-5efdd605f75d"),
|
||||
MerchantID: uuid.MustParse("a848090f-0409-4386-9caa-929ae6874dbb"),
|
||||
Name: util.RandomString(10),
|
||||
}
|
||||
|
||||
|
76
db/sqlc/users.sql.go
Normal file
76
db/sqlc/users.sql.go
Normal file
@ -0,0 +1,76 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: users.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const createUser = `-- name: CreateUser :one
|
||||
INSERT INTO users (
|
||||
email,
|
||||
password,
|
||||
fullname
|
||||
) VALUES ($1, $2, $3)
|
||||
RETURNING id, index_id, email, password, fullname, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateUserParams struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Fullname string `json:"fullname"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, createUser, arg.Email, arg.Password, arg.Fullname)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Email,
|
||||
&i.Password,
|
||||
&i.Fullname,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getPasswordByEmail = `-- name: GetPasswordByEmail :one
|
||||
SELECT password
|
||||
FROM users
|
||||
WHERE email = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetPasswordByEmail(ctx context.Context, email string) (string, error) {
|
||||
row := q.db.QueryRowContext(ctx, getPasswordByEmail, email)
|
||||
var password string
|
||||
err := row.Scan(&password)
|
||||
return password, err
|
||||
}
|
||||
|
||||
const getUserById = `-- name: GetUserById :one
|
||||
SELECT id, index_id, email, password, fullname, created_at, updated_at
|
||||
FROM users
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserById(ctx context.Context, id uuid.UUID) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserById, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IndexID,
|
||||
&i.Email,
|
||||
&i.Password,
|
||||
&i.Fullname,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
7
db/sqlc/users_test.go
Normal file
7
db/sqlc/users_test.go
Normal file
@ -0,0 +1,7 @@
|
||||
package db
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetUserByID(t *testing.T) {
|
||||
|
||||
}
|
2
go.mod
2
go.mod
@ -11,6 +11,7 @@ require (
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/tabbed/pqtype v0.1.1
|
||||
golang.org/x/crypto v0.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -42,7 +43,6 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.10 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
|
19
util/password.go
Normal file
19
util/password.go
Normal file
@ -0,0 +1,19 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to hash password: %w", err)
|
||||
}
|
||||
return string(hashedPassword), nil
|
||||
}
|
||||
|
||||
func CheckPassword(password string, hashedPassword string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||
}
|
23
util/password_test.go
Normal file
23
util/password_test.go
Normal file
@ -0,0 +1,23 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func TestPasswordUtil(t *testing.T) {
|
||||
password := RandomString(10)
|
||||
|
||||
hashedPassword, err := HashPassword(password)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, hashedPassword)
|
||||
|
||||
err = CheckPassword(password, hashedPassword)
|
||||
require.NoError(t, err)
|
||||
|
||||
wrongPassword := RandomString(5)
|
||||
err = CheckPassword(wrongPassword, hashedPassword)
|
||||
require.EqualError(t, err, bcrypt.ErrMismatchedHashAndPassword.Error())
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
@ -38,3 +39,7 @@ func RandomString(n int) string {
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func RandomEmail() string {
|
||||
return fmt.Sprintf("%s@mail.com", RandomString(5))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user