Skip to content

Commit

Permalink
Refactor and add db pool
Browse files Browse the repository at this point in the history
  • Loading branch information
voltgizerz committed Jun 9, 2024
1 parent e5439ae commit bfc4094
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 41 deletions.
13 changes: 7 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ type (
}

Database struct {
Host string `env:"DATABASE_HOST" env-required:"true"`
PORT string `env:"DATABASE_PORT" env-required:"true"`
Username string `env:"DATABASE_USERNAME" env-required:"true"`
Password string `env:"DATABASE_PASSWORD" env-required:"true"`
Name string `env:"DATABASE_NAME" env-required:"true"`
PoolMax int `yaml:"pool_max" env-required:"true"`
Host string `env:"DATABASE_HOST" env-required:"true"`
PORT string `env:"DATABASE_PORT" env-required:"true"`
Username string `env:"DATABASE_USERNAME" env-required:"true"`
Password string `env:"DATABASE_PASSWORD" env-required:"true"`
Name string `env:"DATABASE_NAME" env-required:"true"`
MaxOpenConns int `yaml:"max_open_conns" env-required:"true"`
MaxIdleConns int `yaml:"max_idle_conns" env-required:"true"`
}
)

Expand Down
3 changes: 2 additions & 1 deletion config/yml/config.development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ app:
host: 'localhost:8080'

database:
pool_max: 2
max_open_conns: 10
max_idle_conns: 10

api:
port: 8080
11 changes: 7 additions & 4 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ func InitDatabase(ctx context.Context, cfg config.Database) *DatabaseOpts {
span, ctx := opentracing.StartSpanFromContext(ctx, "database.InitDatabase")
defer span.Finish()

dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s", cfg.Username, cfg.Password, cfg.Host, cfg.Name)

return &DatabaseOpts{
MasterDB: connectMySQL(ctx, cfg),
MasterDB: connectMySQL(ctx, dsn, cfg.MaxOpenConns, cfg.MaxIdleConns),
}
}

func connectMySQL(ctx context.Context, cfg config.Database) *sqlx.DB {
func connectMySQL(ctx context.Context, dsn string, maxOpenConns, maxIdleConns int) *sqlx.DB {
span, _ := opentracing.StartSpanFromContext(ctx, "database.connectMySQL")
defer span.Finish()

dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s", cfg.Username, cfg.Password, cfg.Host, cfg.Name)

db, err := sqlx.Connect("mysql", dsn)
if err != nil {
logger.LogStdErr.Errorf("Failed to connect to MySQL: %s", err)
}

db.SetMaxOpenConns(maxOpenConns)
db.SetMaxIdleConns(maxIdleConns)

return db
}
32 changes: 23 additions & 9 deletions internal/app/api/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,46 @@ import (
"github.com/voltgizerz/POS-restaurant/internal/app/ports"
)

type Auth struct {
SecretKey string
const (
authType = "Bearer"
)

type AuthJWT struct {
SecretKey string
ExpireDurationInHour int
}

func NewAuthJWT(secretKey string) ports.IAuth {
return &Auth{
SecretKey: secretKey,
return &AuthJWT{
SecretKey: secretKey,
ExpireDurationInHour: 24,
}
}

func (a *Auth) CreateToken(user *entity.User) (string, error) {
func (a *AuthJWT) CreateToken(user *entity.User) (*entity.CreateTokenResponse, error) {
expiredAt := time.Now().Add(time.Hour * time.Duration(a.ExpireDurationInHour))

token := jwt.NewWithClaims(jwt.SigningMethodHS256,
jwt.MapClaims{
"id": user.ID,
"expired_at": time.Now().Add(time.Hour * 24).Unix(),
"expired_at": expiredAt.Unix(),
})

tokenString, err := token.SignedString(a.SecretKey)
if err != nil {
return "", err
return nil, err
}

resp := &entity.CreateTokenResponse{
Token: tokenString,
ExpiredAt: expiredAt,
TokenType: authType,
}

return tokenString, nil
return resp, nil
}

func (a *Auth) VerifyToken(tokenString string) error {
func (a *AuthJWT) VerifyToken(tokenString string) error {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return a.SecretKey, nil
})
Expand Down
8 changes: 4 additions & 4 deletions internal/app/api/handler/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type (
}
)

// sendErrorResponse generates and sends error response
func sendErrorResponse(c fiber.Ctx, statusCode int, errorMessage string) error {
// sendErrorResp generates and sends error response
func sendErrorResp(c fiber.Ctx, statusCode int, errorMessage string) error {
response := errorResponse{
Code: statusCode,
Message: errorMessage,
Expand All @@ -25,8 +25,8 @@ func sendErrorResponse(c fiber.Ctx, statusCode int, errorMessage string) error {
return c.Status(statusCode).JSON(response)
}

// sendSuccessResponse generates and sends success response with dynamic data
func sendSuccessResponse(c fiber.Ctx, statusCode int, message string, data interface{}) error {
// sendSuccessResp generates and sends success response with dynamic data
func sendSuccessResp(c fiber.Ctx, statusCode int, message string, data interface{}) error {
response := successResponse{
Code: statusCode,
Message: message,
Expand Down
14 changes: 7 additions & 7 deletions internal/app/api/handler/user_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/gofiber/fiber/v3"
"github.com/opentracing/opentracing-go"
"github.com/voltgizerz/POS-restaurant/internal/app/constants"
"github.com/voltgizerz/POS-restaurant/internal/app/interactor"
"github.com/voltgizerz/POS-restaurant/internal/app/ports"
)
Expand All @@ -29,29 +30,28 @@ func (h *UserHandler) Login(c fiber.Ctx) error {

err := c.Bind().Body(req)
if err != nil {
return sendErrorResponse(c, fiber.StatusBadRequest, "Invalid request body. Please provide both username and password.")
return sendErrorResp(c, fiber.StatusBadRequest, constants.ErrMsgInvalidUsernameAndPassword)
}

// Check if the username and password are provided
if req.Username == "" || req.Password == "" {
return sendErrorResponse(c, fiber.StatusBadRequest, "Username and password are required.")
return sendErrorResp(c, fiber.StatusBadRequest, constants.ErrMsgUsernameOrPasswordRequired)
}

dataUser, err := h.userService.Login(ctx, req.Username, req.Password)
if err != nil {
if err == sql.ErrNoRows {
return sendErrorResponse(c, fiber.StatusUnauthorized, "Username not found.")
return sendErrorResp(c, fiber.StatusUnauthorized, constants.ErrMsgUsernameNotFound)
}

return sendErrorResponse(c, fiber.StatusUnauthorized, "Invalid username or password.")
return sendErrorResp(c, fiber.StatusUnauthorized, constants.ErrMsgInvalidUsernameOrPassword)
}

token, err := h.authService.CreateToken(dataUser)
if err != nil {
return sendErrorResponse(c, fiber.StatusInternalServerError, "Failed create user token.")
return sendErrorResp(c, fiber.StatusInternalServerError, constants.ErrMsgInternalServerError)
}

return sendSuccessResponse(c, fiber.StatusOK, "Login successful.", token)
return sendSuccessResp(c, fiber.StatusOK, "Success", token)
}

func (h *UserHandler) Register(c fiber.Ctx) error {
Expand Down
10 changes: 10 additions & 0 deletions internal/app/constants/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package constants

const (
ErrMsgInvalidUsernameAndPassword = "Invalid request body. Please provide both username and password."
ErrMsgUsernameOrPasswordRequired = "Username and password are required."
ErrMsgUsernameNotFound = "Username not found."
ErrMsgInvalidUsernameOrPassword = "Invalid username or password."

ErrMsgInternalServerError = "Internal server error."
)
9 changes: 9 additions & 0 deletions internal/app/entity/auth_entity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package entity

import "time"

type CreateTokenResponse struct {
Token string `json:"token"`
TokenType string `json:"token_type"`
ExpiredAt time.Time `json:"expired_at"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "time"

type User struct {
ID int64 `json:"id"`
RoleID int64 `json:"role_id"`
Name string `json:"name"`
Username string `json:"username"`
Email string `json:"email"`
Expand All @@ -13,12 +14,12 @@ type User struct {
}

type UserORM struct {
ID int64 `db:"id"`
Name string `db:"name"`
Username string `db:"username"`
Email string `db:"email"`
Password string `db:"password_hashed"`
IsActive bool `db:"is_active"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
ID int64 `db:"id"`
Name string `db:"name"`
Username string `db:"username"`
Email string `db:"email"`
Password string `db:"password_hashed"`
IsActive bool `db:"is_active"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
6 changes: 4 additions & 2 deletions internal/app/ports/auth_ports.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package ports

import "github.com/voltgizerz/POS-restaurant/internal/app/entity"
import (
"github.com/voltgizerz/POS-restaurant/internal/app/entity"
)

type IAuth interface {
CreateToken(user *entity.User) (string, error)
CreateToken(user *entity.User) (*entity.CreateTokenResponse, error)
VerifyToken(tokenString string) error
}

0 comments on commit bfc4094

Please sign in to comment.