I try to atuhorize with jwt, but I get the problem which is when I check email with value email from claims I get the Error 500. That problem because the db is not ready.
This is the code
package route
package route
import (
"go_fiber/controller"
"go_fiber/middleware"
"github.com/gofiber/fiber/v2"
)
func RouteInit(app *fiber.App, userController controller.UserController) {
app.Get("/users", middleware.AuthMiddleware, userController.FindAll)
app.Post("/login", userController.Login)
}
package app
package app
import (
"database/sql"
"fmt"
"go_fiber/helper"
"os"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/joho/godotenv"
)
func NewDB() *sql.DB {
var (
username = envVariable("DB_USERNAME")
password = envVariable("DB_PASSWORD")
host = envVariable("DB_HOST")
port = envVariable("DB_PORT")
db_name = envVariable("DB_NAME")
)
dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=True", username, password, host, port, db_name)
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
}
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxIdleTime(5 * time.Minute)
db.SetConnMaxLifetime(60 * time.Minute)
return db
}
package main
package main
import (
"go_fiber/app"
"go_fiber/controller"
"go_fiber/exception"
"go_fiber/repository"
"go_fiber/route"
"go_fiber/service"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
)
func main(){
var db = app.NewDB()
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
defer func() {
if err := recover(); err != nil {
exception.ErrorHandler(c, err)
}
}()
return c.Next()
})
validator := validator.New()
userRepository := repository.NewUserRepository()
userService := service.NewUserService(userRepository, db, validator)
userController := controller.NewUserController(userService)
route.RouteInit(app, userController)
app.Listen(":3000")
}
package middleware
package middleware
import (
"database/sql"
"errors"
"fmt"
"go_fiber/exception"
"log"
"os"
"time"
"github.com/gofiber/fiber/v2"
"github.com/golang-jwt/jwt/v4"
)
func AuthMiddleware(c *fiber.Ctx) error{
tokenString := c.Cookies("Authorization")
log.Printf("(middleware) token : %v", tokenString)
if tokenString == "" {
panic(exception.NewUserUnauthorized(errors.New("User Unauthorized").Error()))
}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method :%v", token.Header["sub"])
}
return []byte(os.Getenv("SECRET")), nil
})
log.Printf("(middleware) token : %v", token)
log.Printf("(middleware) error : %v", err)
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
if float64(time.Now().Unix()) > claims["exp"].(float64) {
panic(exception.NewUserUnauthorized(errors.New("User Unauthorized").Error()))
}
log.Printf("(middleware) claims : %v", claims)
log.Printf("(middleware) ok : %v", ok)
var DB *sql.DB
tx, err := DB.Begin()
log.Printf("(middleware) tx : %v", tx)
log.Printf("(middleware) error : %v", err)
query :=`
SELECT email FROM users
WHERE email = ?
LIMIT 1
`
log.Printf("(middleware) query : %v", query)
user, err := tx.QueryContext(c.Context(), query, claims["sub"])
log.Printf("(middleware) user : %v", user)
log.Printf("(middleware) error : %v", err)
if err != nil {
panic(exception.NewUserUnauthorized(errors.New("User Unauthorized").Error()))
}
c.Locals("user", user)
c.Next()
}else {
panic(exception.NewUserUnauthorized(errors.New("User Unauthorized").Error()))
}
return nil
}
and this part the problem code
var DB *sql.DB
tx, err := DB.Begin()
log.Printf("(middleware) tx : %v", tx) // No detect in terminal
this the ouput from log
2023/02/12 10:00:04 (middleware) token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzYxNzEzOTIsInN1YiI6IkphZmFyQGdtYWlsLmNvbSJ9.6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8
2023/02/12 10:00:04 (middleware) token : &{eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzYxNzEzOTIsInN1YiI6IkphZmFyQGdtYWlsLmNvbSJ9.6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8 0xc0000a6780 map[alg:HS256 typ:JWT] map[exp:1.676171392e+09 sub:John@gmail.com] 6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8 true}
2023/02/12 10:00:04 (middleware) error : <nil>
2023/02/12 10:00:04 (middleware) claims : map[exp:1.676171392e+09 sub:John@gmail.com]
2023/02/12 10:00:04 (middleware) ok : true
So, How to fix that problem to access db if different package?
You should pass the DB handler down through your route registration to the middleware.
Change your AuthMiddleware so that it is returned by a function that takes db *sql.DB as an argument:
func NewAuthMiddleware(db *sql.DB) fiber.Handler {
return func(c *fiber.Ctx) error {
// The rest of your function is here and has access to db
}
}
You then need to call NewAuthMiddleware in your RouteInit function
func RouteInit(app *fiber.App, userController controller.UserController, db *sql.DB) {
app.Get("/users", middleware.NewAuthMiddleware(db), userController.FindAll)
app.Post("/login", userController.Login)
}
Then in your main function pass in the db to RouteInit()
func main() {
// ... as before
route.RouteInit(app, userController, db)
}