
КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ: - Исправлено отображение входящих заявок (неправильное извлечение данных) - Устранен 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>
259 lines
9.0 KiB
Markdown
259 lines
9.0 KiB
Markdown
# 🔍 АНАЛИЗ БЕЗОПАСНОСТИ РАЗДЕЛОВ С ОДИНАКОВЫМИ НАЗВАНИЯМИ В КАБИНЕТАХ
|
||
|
||
> **Дата:** 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 дней
|