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>
This commit is contained in:
258
2025-09-19/CABINET_SECTIONS_SECURITY_ANALYSIS.md
Normal file
258
2025-09-19/CABINET_SECTIONS_SECURITY_ANALYSIS.md
Normal file
@ -0,0 +1,258 @@
|
||||
# 🔍 АНАЛИЗ БЕЗОПАСНОСТИ РАЗДЕЛОВ С ОДИНАКОВЫМИ НАЗВАНИЯМИ В КАБИНЕТАХ
|
||||
|
||||
> **Дата:** 2025-09-19
|
||||
> **Контекст:** 4 типа кабинетов (SELLER, FULFILLMENT, WHOLESALE, LOGIST) с одинаковыми названиями разделов
|
||||
|
||||
---
|
||||
|
||||
## 🚨 КЛЮЧЕВЫЕ ПРОБЛЕМЫ
|
||||
|
||||
### 1. ДУБЛИРОВАНИЕ МАРШРУТОВ БЕЗ ЗАЩИТЫ
|
||||
|
||||
**Текущая структура:**
|
||||
|
||||
```
|
||||
ГЛОБАЛЬНЫЕ (БЕЗ ЗАЩИТЫ) КАБИНЕТНЫЕ (С ЗАЩИТОЙ)
|
||||
/economics/ → /seller/economics/
|
||||
/partners/ → /fulfillment/partners/
|
||||
/messenger/ → /wholesale/messenger/
|
||||
/market/ → /logistics/market/
|
||||
```
|
||||
|
||||
**Проблема:** Глобальные маршруты доступны ВСЕМ авторизованным пользователям независимо от их роли.
|
||||
|
||||
### 2. WRAPPER-КОМПОНЕНТЫ С ДИНАМИЧЕСКИМ РЕНДЕРИНГОМ
|
||||
|
||||
**Пример: EconomicsPageWrapper**
|
||||
|
||||
```typescript
|
||||
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` - общий маркет для всех
|
||||
|
||||
**Что происходит внутри:**
|
||||
|
||||
```typescript
|
||||
// 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: ЗАЩИТИТЬ ГЛОБАЛЬНЫЕ МАРШРУТЫ
|
||||
|
||||
```typescript
|
||||
// /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
|
||||
|
||||
```typescript
|
||||
// /app/seller/layout.tsx
|
||||
export default function SellerLayout({ children }) {
|
||||
useRoleGuard('SELLER') // Защита всего кабинета
|
||||
|
||||
return (
|
||||
<AuthGuard>
|
||||
{children}
|
||||
</AuthGuard>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. СПЕЦИФИЧНЫЕ КОМПОНЕНТЫ
|
||||
|
||||
```typescript
|
||||
// Вместо общего PartnersDashboard
|
||||
export function SellerPartnersDashboard() {
|
||||
// Логика только для селлеров
|
||||
}
|
||||
|
||||
export function FulfillmentPartnersDashboard() {
|
||||
// Логика только для фулфилмента
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 ПЛАН ДЕЙСТВИЙ
|
||||
|
||||
### ЭТАП 1: НЕМЕДЛЕННО (Сегодня)
|
||||
|
||||
1. **Добавить редиректы в глобальные страницы:**
|
||||
|
||||
```typescript
|
||||
// /app/economics/page.tsx
|
||||
if (user?.organization?.type) {
|
||||
redirect(`/${user.organization.type.toLowerCase()}/economics/`)
|
||||
}
|
||||
```
|
||||
|
||||
2. **Добавить useRoleGuard в wrapper-компоненты:**
|
||||
|
||||
```typescript
|
||||
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 дней
|
Reference in New Issue
Block a user