package api import ( "errors" "fmt" "net/http" "strings" "github.com/FernandoJVideira/api_tmpl/internal/auth" "github.com/FernandoJVideira/api_tmpl/internal/domain/role" "github.com/FernandoJVideira/api_tmpl/internal/handlers/http/response" "github.com/gin-gonic/gin" ) const ( authHeaderKey = "authorization" authTypeBearer = "bearer" authorizationPayloadKey = "authorization_payload" ) func authMiddleware(tokenMaker auth.Maker, accessibleRoles []string) gin.HandlerFunc { return func(ctx *gin.Context) { authorizationHeader := ctx.GetHeader(authHeaderKey) if len(authorizationHeader) == 0 { err := errors.New("authorization header is not provided") resp := response.JSONResponse{ Success: false, Error: err.Error(), } ctx.AbortWithStatusJSON(http.StatusUnauthorized, resp) return } // Split fields := strings.Fields(authorizationHeader) if len(fields) < 2 { err := errors.New("invalid authorization header format") resp := response.JSONResponse{ Success: false, Error: err.Error(), } ctx.AbortWithStatusJSON(http.StatusUnauthorized, resp) } authType := strings.ToLower(fields[0]) if authType != authTypeBearer { err := fmt.Errorf("unsupported authorization type %s", authType) resp := response.JSONResponse{ Success: false, Error: err.Error(), } ctx.AbortWithStatusJSON(http.StatusUnauthorized, resp) return } accessToken := fields[1] payload, err := tokenMaker.VerifyToken(accessToken) if err != nil { resp := response.JSONResponse{ Success: false, Error: err.Error(), } ctx.AbortWithStatusJSON(http.StatusUnauthorized, resp) return } if !role.HasPermission(payload.Role, accessibleRoles) { err := fmt.Errorf("permission denied") resp := response.JSONResponse{ Success: false, Error: err.Error(), } ctx.AbortWithStatusJSON(http.StatusForbidden, resp) return } ctx.Set(authorizationPayloadKey, payload) ctx.Next() } }