kontenhumas-be/utils/middleware/client_utils.go

141 lines
3.6 KiB
Go
Raw Normal View History

2025-09-28 01:53:09 +00:00
package middleware
import (
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"gorm.io/gorm"
2025-09-30 13:34:56 +00:00
customMiddleware "netidhub-saas-be/app/middleware"
2025-09-28 01:53:09 +00:00
)
// AddClientFilter adds client_id filter to GORM query
2025-09-30 13:34:56 +00:00
// Enhanced to support multi-client access and super admin
2025-09-28 01:53:09 +00:00
func AddClientFilter(db *gorm.DB, c *fiber.Ctx) *gorm.DB {
if c == nil {
return db
}
2025-09-30 13:34:56 +00:00
// Check if super admin
if customMiddleware.IsSuperAdmin(c) {
return db // No filtering for super admin
2025-09-28 01:53:09 +00:00
}
2025-09-30 13:34:56 +00:00
// Get accessible client IDs
accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c)
if accessibleClientIDs == nil {
// Super admin or no restriction
return db
}
if len(accessibleClientIDs) == 0 {
// User has no client access - return empty result
return db.Where("1 = 0")
}
if len(accessibleClientIDs) == 1 {
// Single client access (backward compatible)
return db.Where("client_id = ?", accessibleClientIDs[0])
}
// Multiple client access
return db.Where("client_id IN ?", accessibleClientIDs)
2025-09-28 01:53:09 +00:00
}
// SetClientID sets client_id in the given struct if it has a ClientId field
2025-09-30 13:34:56 +00:00
// Uses the current working client ID from context
2025-09-28 01:53:09 +00:00
func SetClientID(c *fiber.Ctx, model interface{}) {
if c == nil {
return
}
2025-09-30 13:34:56 +00:00
// Try to get current client ID first (multi-client support)
currentClientID := customMiddleware.GetCurrentClientID(c)
if currentClientID != nil {
if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok {
setter.SetClientID(currentClientID)
}
return
}
// Fallback to old GetClientID (backward compatibility)
clientID := customMiddleware.GetClientID(c)
2025-09-28 01:53:09 +00:00
if clientID != nil {
if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok {
setter.SetClientID(clientID)
}
}
}
2025-09-30 13:34:56 +00:00
// ValidateClientAccess validates if the current user has access to a resource
// Enhanced to check against all accessible clients for multi-client users
2025-09-28 01:53:09 +00:00
func ValidateClientAccess(db *gorm.DB, c *fiber.Ctx, tableName string, resourceID interface{}) error {
if c == nil {
return nil // Skip validation for background jobs
}
2025-09-30 13:34:56 +00:00
// Super admin has access to everything
if customMiddleware.IsSuperAdmin(c) {
return nil
}
accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c)
if accessibleClientIDs == nil {
// Super admin case (should not reach here, but for safety)
return nil
}
if len(accessibleClientIDs) == 0 {
return fiber.NewError(fiber.StatusForbidden, "No client access configured")
2025-09-28 01:53:09 +00:00
}
var count int64
2025-09-30 13:34:56 +00:00
var err error
if len(accessibleClientIDs) == 1 {
// Single client (backward compatible)
err = db.Table(tableName).
Where("id = ? AND client_id = ?", resourceID, accessibleClientIDs[0]).
Count(&count).Error
} else {
// Multiple clients
err = db.Table(tableName).
Where("id = ? AND client_id IN ?", resourceID, accessibleClientIDs).
Count(&count).Error
}
if err != nil {
2025-09-28 01:53:09 +00:00
return err
}
if count == 0 {
return fiber.NewError(fiber.StatusForbidden, "Access denied to this resource")
}
return nil
}
2025-09-30 13:34:56 +00:00
// FilterByCurrentClient filters query by the current working client only
// Different from AddClientFilter - this only filters by the ACTIVE client
func FilterByCurrentClient(db *gorm.DB, c *fiber.Ctx) *gorm.DB {
if c == nil {
return db
}
// Super admin with no specific client selected
if customMiddleware.IsSuperAdmin(c) {
currentClientID := customMiddleware.GetCurrentClientID(c)
if currentClientID == nil {
return db // No filter
}
return db.Where("client_id = ?", currentClientID)
}
// Regular user - filter by current client
currentClientID := customMiddleware.GetCurrentClientID(c)
if currentClientID != nil {
return db.Where("client_id = ?", currentClientID)
}
return db
}