2025-11-17 12:17:44 +07:00

105 lines
2.3 KiB
Go

package middleware
import (
"lost-and-found/internal/config"
"lost-and-found/internal/repositories"
"lost-and-found/internal/utils"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// JWTMiddleware validates JWT token
func JWTMiddleware(db *gorm.DB) gin.HandlerFunc {
return func(ctx *gin.Context) {
// Get token from Authorization header
authHeader := ctx.GetHeader("Authorization")
if authHeader == "" {
utils.ErrorResponse(ctx, http.StatusUnauthorized, "Authorization header required", "")
ctx.Abort()
return
}
// Check if Bearer token
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
utils.ErrorResponse(ctx, http.StatusUnauthorized, "Invalid authorization format", "")
ctx.Abort()
return
}
tokenString := parts[1]
// Validate token
claims, err := config.ValidateToken(tokenString)
if err != nil {
utils.ErrorResponse(ctx, http.StatusUnauthorized, "Invalid or expired token", err.Error())
ctx.Abort()
return
}
// Get user from database
userRepo := repositories.NewUserRepository(db)
user, err := userRepo.FindByID(claims.UserID)
if err != nil {
utils.ErrorResponse(ctx, http.StatusUnauthorized, "User not found", "")
ctx.Abort()
return
}
// Check if user is blocked
if user.IsBlocked() {
utils.ErrorResponse(ctx, http.StatusForbidden, "Account is blocked", "")
ctx.Abort()
return
}
// Set user in context
ctx.Set("user", user)
ctx.Set("user_id", user.ID)
ctx.Set("user_role", user.Role.Name)
ctx.Next()
}
}
// OptionalJWTMiddleware validates JWT token if present (for public routes that can benefit from auth)
func OptionalJWTMiddleware(db *gorm.DB) gin.HandlerFunc {
return func(ctx *gin.Context) {
authHeader := ctx.GetHeader("Authorization")
if authHeader == "" {
ctx.Next()
return
}
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
ctx.Next()
return
}
tokenString := parts[1]
claims, err := config.ValidateToken(tokenString)
if err != nil {
ctx.Next()
return
}
userRepo := repositories.NewUserRepository(db)
user, err := userRepo.FindByID(claims.UserID)
if err != nil {
ctx.Next()
return
}
if !user.IsBlocked() {
ctx.Set("user", user)
ctx.Set("user_id", user.ID)
ctx.Set("user_role", user.Role.Name)
}
ctx.Next()
}
}