Inicial
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user