
КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ: - Исправлено отображение входящих заявок (неправильное извлечение данных) - Устранен 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>
9.0 KiB
🔍 АНАЛИЗ БЕЗОПАСНОСТИ РАЗДЕЛОВ С ОДИНАКОВЫМИ НАЗВАНИЯМИ В КАБИНЕТАХ
Дата: 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: НЕМЕДЛЕННО (Сегодня)
- Добавить редиректы в глобальные страницы:
// /app/economics/page.tsx
if (user?.organization?.type) {
redirect(`/${user.organization.type.toLowerCase()}/economics/`)
}
- Добавить useRoleGuard в wrapper-компоненты:
export function EconomicsPageWrapper() {
// Добавить проверку перед switch
if (!user?.organization?.type) {
redirect('/login')
}
}
ЭТАП 2: КРАТКОСРОЧНО (1-3 дня)
- Создать layout-защиту для каждого кабинета
- Провести аудит всех ссылок на глобальные маршруты
- Создать карту редиректов для обратной совместимости
ЭТАП 3: ДОЛГОСРОЧНО (1-2 недели)
- Разделить общие компоненты на роль-специфичные
- Удалить глобальные маршруты после миграции
- Создать автоматические тесты для проверки доступа
🎯 ИТОГ
Текущая ситуация: Опасная архитектура с возможностью обхода защиты через глобальные маршруты.
Решение: Либо полностью удалить глобальные маршруты, либо добавить автоматические редиректы на роль-специфичные страницы.
Приоритет: 🔴 КРИТИЧЕСКИЙ - исправить в течение 1-2 дней