Files
techxcar/backend/internal/auth/middleware.go
T
Luciano Milani 5de37bb512 Inicial
2026-07-02 12:47:55 +01:00

75 lines
2.1 KiB
Go

package auth
import (
"strings"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/techxcar/backend/pkg/database"
)
func RequireAuth(secret string) fiber.Handler {
return func(c *fiber.Ctx) error {
authHeader := c.Get("Authorization")
if authHeader == "" {
return fiber.NewError(401, "autenticação necessária")
}
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" {
return fiber.NewError(401, "formato de autorização inválido")
}
claims, err := ValidateToken(parts[1], secret)
if err != nil {
return fiber.NewError(401, "token inválido ou expirado")
}
c.Locals("claims", claims)
return c.Next()
}
}
func RequireRole(roles ...string) fiber.Handler {
return func(c *fiber.Ctx) error {
claims, ok := c.Locals("claims").(*Claims)
if !ok {
return fiber.NewError(401, "autenticação necessária")
}
for _, role := range roles {
if claims.Role == role {
return c.Next()
}
}
return fiber.NewError(403, "acesso não autorizado")
}
}
// TenantMiddleware acquires a dedicated pgxpool connection per request,
// sets the tenant search_path, stores the connection in c.Locals("conn"),
// and releases the connection after the handler chain completes.
func TenantMiddleware(db *database.DB) fiber.Handler {
return func(c *fiber.Ctx) error {
claims, ok := c.Locals("claims").(*Claims)
if !ok || claims.TenantID == "" {
return c.Next()
}
conn, err := db.Pool.Acquire(c.Context())
if err != nil {
return fiber.NewError(500, "erro interno ao adquirir conexão")
}
schema := `"tenant_` + strings.ReplaceAll(claims.TenantID, "-", "_") + `"`
if _, err := conn.Exec(c.Context(), "SET search_path = "+schema+", public"); err != nil {
conn.Release()
return fiber.NewError(500, "erro interno ao definir schema")
}
c.Locals("conn", conn)
err = c.Next()
conn.Release()
return err
}
}
// GetConn returns the tenant-scoped connection stored by TenantMiddleware.
func GetConn(c *fiber.Ctx) *pgxpool.Conn {
conn, _ := c.Locals("conn").(*pgxpool.Conn)
return conn
}