Files
sfera-new/2025-09-19/CABINET_SECTIONS_SECURITY_ANALYSIS.md
Veronika Smirnova fe24b73634 fix: исправить критические ошибки системы партнерских заявок
КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ:
- Исправлено отображение входящих заявок (неправильное извлечение данных)
- Устранен ApolloError при принятии заявок (неправильная структура мутаций)
- Исправлено отображение контрагентов после принятия заявки
- Обновлены типы возврата GraphQL мутаций для соответствия резолверам

UI/UX УЛУЧШЕНИЯ:
- Обновлены все компоненты на темную glass-morphism тему
- Компактные карточки контрагентов (удалена избыточная информация)
- Удален дублирующий блок поиска новых партнеров

ЗАТРОНУТЫЕ ФАЙЛЫ:
- useCounterpartyData.ts: исправлено извлечение данных
- useCounterpartyActions.ts: исправлены структуры мутаций
- IncomingRequestsBlock.tsx: темная тема + исправления UI
- OutgoingRequestsBlock.tsx: темная тема
- CounterpartiesListBlock.tsx: компактные карточки + темная тема
- typedefs.ts: исправлены типы возврата мутаций

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 23:23:03 +03:00

9.0 KiB
Raw Blame History

🔍 АНАЛИЗ БЕЗОПАСНОСТИ РАЗДЕЛОВ С ОДИНАКОВЫМИ НАЗВАНИЯМИ В КАБИНЕТАХ

Дата: 2025-09-19
Контекст: 4 типа кабинетов (SELLER, FULFILLMENT, WHOLESALE, LOGIST) с одинаковыми названиями разделов


🚨 КЛЮЧЕВЫЕ ПРОБЛЕМЫ

1. ДУБЛИРОВАНИЕ МАРШРУТОВ БЕЗ ЗАЩИТЫ

Текущая структура:

ГЛОБАЛЬНЫЕ (БЕЗ ЗАЩИТЫ)          КАБИНЕТНЫЕ (С ЗАЩИТОЙ)
/economics/                  →    /seller/economics/
/partners/                   →    /fulfillment/partners/
/messenger/                  →    /wholesale/messenger/
/market/                     →    /logistics/market/

Проблема: Глобальные маршруты доступны ВСЕМ авторизованным пользователям независимо от их роли.

2. WRAPPER-КОМПОНЕНТЫ С ДИНАМИЧЕСКИМ РЕНДЕРИНГОМ

Пример: EconomicsPageWrapper

export function EconomicsPageWrapper() {
  const { user } = useAuthContext()

  // Роутинг по типу организации
  switch (user.organization.type) {
    case 'SELLER': return <SellerEconomicsPage />
    case 'FULFILLMENT': return <FulfillmentEconomicsPage />
    case 'WHOLESALE': return <WholesaleEconomicsPage />
    case 'LOGIST': return <LogistEconomicsPage />
  }
}

Риски:

  • Пользователь может получить доступ к чужим компонентам через глобальный маршрут /economics/
  • Нет проверки прав доступа на уровне маршрута
  • Логика безопасности размазана между маршрутами и компонентами

3. ОБЩИЕ КОМПОНЕНТЫ ДЛЯ ВСЕХ РОЛЕЙ

Примеры проблемных компонентов:

  • PartnersDashboard - используется всеми ролями без дифференциации
  • MessengerDashboard - единый компонент для всех типов организаций
  • MarketDashboard - общий маркет для всех

Что происходит внутри:

// MessengerDashboard использует GET_MY_COUNTERPARTIES
const counterparties = counterpartiesData?.myCounterparties || []

Проблема: Один компонент пытается обслужить разные бизнес-логики для разных типов организаций.

4. ИЗОЛЯЦИЯ ДАННЫХ НА УРОВНЕ API

Хорошо: API возвращает только myCounterparties - контрагентов текущей организации

Плохо: Но доступ к компонентам не ограничен по ролям на уровне UI


⚠️ КОНКРЕТНЫЕ РИСКИ

СЦЕНАРИЙ АТАКИ 1: Обход защиты через глобальные маршруты

1. Пользователь SELLER авторизован
2. Заходит на /economics/ (вместо /seller/economics/)
3. EconomicsPageWrapper показывает SellerEconomicsPage
4. Но через манипуляции может получить доступ к данным других ролей

СЦЕНАРИЙ АТАКИ 2: Доступ к функционалу других ролей

1. Логист заходит на /partners/
2. Видит PartnersDashboard со своими данными
3. Но интерфейс может содержать функции для других ролей
4. Потенциальная утечка бизнес-логики

СЦЕНАРИЙ АТАКИ 3: Путаница в данных

1. Пользователь с несколькими ролями (если такое возможно)
2. Заходит на глобальный маршрут
3. Непредсказуемое поведение wrapper-компонентов
4. Отображение некорректных данных

ПРАВИЛЬНОЕ РЕШЕНИЕ

ВАРИАНТ 1: УДАЛИТЬ ГЛОБАЛЬНЫЕ МАРШРУТЫ

Преимущества:

  • Невозможно обойти защиту
  • Четкая изоляция кабинетов
  • Простота понимания структуры

Недостатки:

  • Нужно обновить все ссылки в приложении
  • Может сломать закладки пользователей

ВАРИАНТ 2: ЗАЩИТИТЬ ГЛОБАЛЬНЫЕ МАРШРУТЫ

// /app/economics/page.tsx
export default function EconomicsPage() {
  const { user } = useAuthContext()

  // Автоматический редирект на правильный кабинет
  if (user?.organization?.type) {
    redirect(`/${user.organization.type.toLowerCase()}/economics/`)
  }

  return <div>Загрузка...</div>
}

Преимущества:

  • Обратная совместимость
  • Автоматическая навигация
  • Защита от неавторизованного доступа

ВАРИАНТ 3: РОЛЬ-СПЕЦИФИЧНЫЕ КОМПОНЕНТЫ

Вместо общих компонентов создать специфичные для каждой роли:

PartnersDashboard → SellerPartnersDashboard
                 → FulfillmentPartnersDashboard
                 → WholesalePartnersDashboard
                 → LogistPartnersDashboard

Преимущества:

  • Четкая бизнес-логика для каждой роли
  • Невозможно показать чужой функционал
  • Легче тестировать и поддерживать

🛡️ РЕКОМЕНДУЕМАЯ АРХИТЕКТУРА

1. СТРУКТУРА МАРШРУТОВ

/seller/
  ├── home/          (✅ protected with useRoleGuard)
  ├── economics/     (✅ protected with useRoleGuard)
  ├── partners/      (✅ protected with useRoleGuard)
  └── messenger/     (✅ protected with useRoleGuard)

/fulfillment/
  ├── home/          (✅ protected with useRoleGuard)
  ├── economics/     (✅ protected with useRoleGuard)
  ├── partners/      (✅ protected with useRoleGuard)
  └── messenger/     (✅ protected with useRoleGuard)

❌ УДАЛИТЬ ИЛИ ЗАЩИТИТЬ:
/economics/
/partners/
/messenger/
/market/

2. ЗАЩИТА НА УРОВНЕ LAYOUT

// /app/seller/layout.tsx
export default function SellerLayout({ children }) {
  useRoleGuard('SELLER') // Защита всего кабинета

  return (
    <AuthGuard>
      {children}
    </AuthGuard>
  )
}

3. СПЕЦИФИЧНЫЕ КОМПОНЕНТЫ

// Вместо общего PartnersDashboard
export function SellerPartnersDashboard() {
  // Логика только для селлеров
}

export function FulfillmentPartnersDashboard() {
  // Логика только для фулфилмента
}

📋 ПЛАН ДЕЙСТВИЙ

ЭТАП 1: НЕМЕДЛЕННО (Сегодня)

  1. Добавить редиректы в глобальные страницы:
// /app/economics/page.tsx
if (user?.organization?.type) {
  redirect(`/${user.organization.type.toLowerCase()}/economics/`)
}
  1. Добавить useRoleGuard в wrapper-компоненты:
export function EconomicsPageWrapper() {
  // Добавить проверку перед switch
  if (!user?.organization?.type) {
    redirect('/login')
  }
}

ЭТАП 2: КРАТКОСРОЧНО (1-3 дня)

  1. Создать layout-защиту для каждого кабинета
  2. Провести аудит всех ссылок на глобальные маршруты
  3. Создать карту редиректов для обратной совместимости

ЭТАП 3: ДОЛГОСРОЧНО (1-2 недели)

  1. Разделить общие компоненты на роль-специфичные
  2. Удалить глобальные маршруты после миграции
  3. Создать автоматические тесты для проверки доступа

🎯 ИТОГ

Текущая ситуация: Опасная архитектура с возможностью обхода защиты через глобальные маршруты.

Решение: Либо полностью удалить глобальные маршруты, либо добавить автоматические редиректы на роль-специфичные страницы.

Приоритет: 🔴 КРИТИЧЕСКИЙ - исправить в течение 1-2 дней