package middleware import ( "github.com/gofiber/fiber/v2" "github.com/google/uuid" "gorm.io/gorm" customMiddleware "netidhub-saas-be/app/middleware" ) // AddClientFilter adds client_id filter to GORM query // Enhanced to support multi-client access and super admin func AddClientFilter(db *gorm.DB, c *fiber.Ctx) *gorm.DB { if c == nil { return db } // Check if super admin if customMiddleware.IsSuperAdmin(c) { return db // No filtering for super admin } // 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) } // SetClientID sets client_id in the given struct if it has a ClientId field // Uses the current working client ID from context func SetClientID(c *fiber.Ctx, model interface{}) { if c == nil { return } // 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) if clientID != nil { if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok { setter.SetClientID(clientID) } } } // ValidateClientAccess validates if the current user has access to a resource // Enhanced to check against all accessible clients for multi-client users func ValidateClientAccess(db *gorm.DB, c *fiber.Ctx, tableName string, resourceID interface{}) error { if c == nil { return nil // Skip validation for background jobs } // 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") } var count int64 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 { return err } if count == 0 { return fiber.NewError(fiber.StatusForbidden, "Access denied to this resource") } return nil } // 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 }