Files
sfera-new/2025-09-19/GLOBAL_ROUTES_ELIMINATION_PLAN.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

483 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🚨 ПЛАН УСТРАНЕНИЯ ГЛОБАЛЬНЫХ МАРШРУТОВ И СОЗДАНИЯ РОЛЬ-СПЕЦИФИЧНЫХ КОМПОНЕНТОВ
> **Дата:** 2025-09-19
> **Приоритет:** 🔴 КРИТИЧЕСКИЙ
> **Статус:** В реализации
> **Цель:** Устранить критические уязвимости безопасности через удаление глобальных маршрутов
---
## 🔍 РЕЗУЛЬТАТЫ МАКСИМАЛЬНОЙ ДИАГНОСТИКИ
### ОБНАРУЖЕННЫЕ ГЛОБАЛЬНЫЕ МАРШРУТЫ
**10 критических глобальных page.tsx файлов:**
```bash
src/app/economics/page.tsx ❌ УЯЗВИМОСТЬ
src/app/partners/page.tsx ❌ УЯЗВИМОСТЬ
src/app/market/page.tsx ❌ УЯЗВИМОСТЬ
src/app/messenger/page.tsx ❌ УЯЗВИМОСТЬ
src/app/services/page.tsx ❌ УЯЗВИМОСТЬ
src/app/settings/page.tsx ❌ УЯЗВИМОСТЬ
src/app/warehouse/page.tsx ❌ УЯЗВИМОСТЬ
src/app/exchange/page.tsx ❌ УЯЗВИМОСТЬ
src/app/supplies/page.tsx ❌ УЯЗВИМОСТЬ
src/app/employees/page.tsx ❌ УЯЗВИМОСТЬ
```
### ОБНАРУЖЕННЫЕ ССЫЛКИ НА ГЛОБАЛЬНЫЕ МАРШРУТЫ
**Опасная ссылка в messenger-empty-state.tsx:**
```typescript
// src/components/messenger/messenger-empty-state.tsx:12
router.push('/market') // ❌ Ведет на глобальный маршрут!
```
### АНАЛИЗ УЯЗВИМОСТИ
**Сценарий атаки:**
```
1. Пользователь LOGIST авторизован ✅
2. Заходит на /partners/ ❌ (обходит useRoleGuard)
3. Видит PartnersDashboard со всеми табами ❌
4. Получает доступ к интерфейсу других ролей ❌
```
**Критичность:** 🔴 Высокая - возможность обхода роль-специфичной защиты
---
## 🎯 ДЕТАЛЬНЫЙ ПЛАН УСТРАНЕНИЯ
### ЭТАП 1: БЕЗОПАСНОЕ УДАЛЕНИЕ ГЛОБАЛЬНЫХ МАРШРУТОВ
#### 1.1 ПОДГОТОВКА К УДАЛЕНИЮ
**Создать бэкап:**
```bash
mkdir backup-global-routes-$(date +%Y%m%d)
cp src/app/economics/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/partners/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/market/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/messenger/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/services/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/settings/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/warehouse/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/exchange/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/supplies/page.tsx backup-global-routes-$(date +%Y%m%d)/
cp src/app/employees/page.tsx backup-global-routes-$(date +%Y%m%d)/
```
#### 1.2 БЕЗОПАСНОЕ УДАЛЕНИЕ
**Последовательность удаления (от менее к более критичным):**
1. **Второстепенные разделы:**
```bash
rm src/app/services/page.tsx
rm src/app/settings/page.tsx
rm src/app/warehouse/page.tsx
rm src/app/exchange/page.tsx
rm src/app/employees/page.tsx
```
2. **Основные разделы:**
```bash
rm src/app/supplies/page.tsx
rm src/app/economics/page.tsx
```
3. **Критичные разделы (после создания замены):**
```bash
rm src/app/partners/page.tsx
rm src/app/market/page.tsx
rm src/app/messenger/page.tsx
```
### ЭТАП 2: СОЗДАНИЕ РОЛЬ-СПЕЦИФИЧНЫХ КОМПОНЕНТОВ
#### 2.1 PARTNERS - ПЕРВЫЙ ПРИОРИТЕТ
**Анализ текущего PartnersDashboard:**
```typescript
// Текущие табы (одинаковые для всех ролей):
- Мои контрагенты
- Фулфилмент
- Селлеры
- Логистика
- Поставщик
- Рефералы
```
**Создание роль-специфичных компонентов:**
**A. SellerPartners:**
```typescript
// src/components/partners/seller-partners.tsx
export function SellerPartners() {
const { user } = useAuthContext()
// Дополнительная защита
if (user?.organization?.type !== 'SELLER') {
console.error('Security violation: wrong role in SellerPartners')
redirect('/login')
}
return (
<Tabs defaultValue="my-counterparties">
<TabsList>
<TabsTrigger value="my-counterparties">Мои партнеры</TabsTrigger>
<TabsTrigger value="find-fulfillment">Найти фулфилмент</TabsTrigger>
<TabsTrigger value="find-suppliers">Найти поставщиков</TabsTrigger>
<TabsTrigger value="referrals">Рефералы</TabsTrigger>
</TabsList>
<TabsContent value="my-counterparties">
<MarketCounterparties /> {/* Показывает только партнеров селлера */}
</TabsContent>
<TabsContent value="find-fulfillment">
<MarketFulfillment /> {/* Поиск фулфилмент-центров */}
</TabsContent>
<TabsContent value="find-suppliers">
<MarketSuppliers /> {/* Поиск поставщиков */}
</TabsContent>
<TabsContent value="referrals">
<ReferralsTab /> {/* Реферальная система */}
</TabsContent>
</Tabs>
)
}
```
**B. FulfillmentPartners:**
```typescript
// src/components/partners/fulfillment-partners.tsx
export function FulfillmentPartners() {
const { user } = useAuthContext()
if (user?.organization?.type !== 'FULFILLMENT') {
console.error('Security violation: wrong role in FulfillmentPartners')
redirect('/login')
}
return (
<Tabs defaultValue="sellers">
<TabsList>
<TabsTrigger value="sellers">Селлеры</TabsTrigger>
<TabsTrigger value="suppliers">Поставщики</TabsTrigger>
<TabsTrigger value="logistics">Логистика</TabsTrigger>
<TabsTrigger value="incoming-requests">Заявки</TabsTrigger>
</TabsList>
<TabsContent value="sellers">
<MarketSellers /> {/* Управление селлерами */}
</TabsContent>
<TabsContent value="suppliers">
<MarketSuppliers /> {/* Поставщики расходников */}
</TabsContent>
<TabsContent value="logistics">
<MarketLogistics /> {/* Логистические партнеры */}
</TabsContent>
</Tabs>
)
}
```
**C. WholesalePartners:**
```typescript
// src/components/partners/wholesale-partners.tsx
export function WholesalePartners() {
const { user } = useAuthContext()
if (user?.organization?.type !== 'WHOLESALE') {
console.error('Security violation: wrong role in WholesalePartners')
redirect('/login')
}
return (
<Tabs defaultValue="clients">
<TabsList>
<TabsTrigger value="clients">Клиенты</TabsTrigger>
<TabsTrigger value="incoming-orders">Входящие заказы</TabsTrigger>
<TabsTrigger value="logistics">Логистика</TabsTrigger>
</TabsList>
<TabsContent value="clients">
<MarketCounterparties /> {/* Клиенты поставщика */}
</TabsContent>
<TabsContent value="incoming-orders">
{/* Компонент для обработки входящих заказов */}
<WholesaleIncomingOrders />
</TabsContent>
</Tabs>
)
}
```
**D. LogistPartners:**
```typescript
// src/components/partners/logist-partners.tsx
export function LogistPartners() {
const { user } = useAuthContext()
if (user?.organization?.type !== 'LOGIST') {
console.error('Security violation: wrong role in LogistPartners')
redirect('/login')
}
return (
<Tabs defaultValue="routes">
<TabsList>
<TabsTrigger value="routes">Маршруты</TabsTrigger>
<TabsTrigger value="clients">Клиенты</TabsTrigger>
<TabsTrigger value="pricing">Тарифы</TabsTrigger>
</TabsList>
<TabsContent value="routes">
{/* Агрегированные маршруты без коммерческой информации */}
<LogisticsRoutes />
</TabsContent>
</Tabs>
)
}
```
#### 2.2 MESSENGER - ВТОРОЙ ПРИОРИТЕТ
**Анализ текущего MessengerDashboard:**
- Общий компонент для всех ролей
- Показывает myCounterparties для каждой роли
- Логика мессенджера одинакова, но контрагенты разные
**Создание роль-специфичных мессенджеров:**
```typescript
// src/components/messenger/seller-messenger.tsx
export function SellerMessenger() {
const { user } = useAuthContext()
if (user?.organization?.type !== 'SELLER') {
redirect('/login')
}
// Специфичная логика для селлера
return <MessengerDashboard />
}
```
#### 2.3 MARKET - ТРЕТИЙ ПРИОРИТЕТ
**Создание роль-специфичных компонентов маркета:**
```typescript
// src/components/market/seller-market.tsx
export function SellerMarket() {
return (
<Tabs defaultValue="products">
<TabsTrigger value="products">Товары</TabsTrigger>
<TabsTrigger value="requests">Мои заявки</TabsTrigger>
</Tabs>
)
}
// src/components/market/wholesale-market.tsx
export function WholesaleMarket() {
return (
<Tabs defaultValue="catalog">
<TabsTrigger value="catalog">Каталог</TabsTrigger>
<TabsTrigger value="incoming-requests">Входящие заявки</TabsTrigger>
</Tabs>
)
}
```
### ЭТАП 3: ОБНОВЛЕНИЕ КАБИНЕТНЫХ МАРШРУТОВ
**Обновление файлов page.tsx в кабинетах:**
```typescript
// src/app/seller/partners/page.tsx
export default function SellerPartnersPage() {
useRoleGuard('SELLER')
return (
<AuthGuard>
<SellerPartners /> {/* ← Новый роль-специфичный компонент */}
</AuthGuard>
)
}
// src/app/fulfillment/partners/page.tsx
export default function FulfillmentPartnersPage() {
useRoleGuard('FULFILLMENT')
return (
<AuthGuard>
<FulfillmentPartners />
</AuthGuard>
)
}
```
### ЭТАП 4: ИСПРАВЛЕНИЕ ССЫЛОК
**Найти и исправить все ссылки на глобальные маршруты:**
```typescript
// src/components/messenger/messenger-empty-state.tsx
// БЫЛО:
router.push('/market')
// СТАЛО:
const { user } = useAuthContext()
const userType = user?.organization?.type?.toLowerCase()
router.push(`/${userType}/market`)
```
### ЭТАП 5: ТЕСТИРОВАНИЕ БЕЗОПАСНОСТИ
#### 5.1 АВТОМАТИЧЕСКИЕ ТЕСТЫ
**Создать тесты для проверки роль-специфичного доступа:**
```typescript
// tests/security/role-access.test.ts
describe('Role-specific access control', () => {
test('SELLER cannot access FULFILLMENT components', () => {
const sellerUser = { organization: { type: 'SELLER' } }
expect(() => {
render(<FulfillmentPartners />, { user: sellerUser })
}).toThrow('Security violation')
})
test('Global routes return 404', () => {
expect(fetch('/partners')).resolves.toHaveStatus(404)
expect(fetch('/economics')).resolves.toHaveStatus(404)
})
})
```
#### 5.2 РУЧНОЕ ТЕСТИРОВАНИЕ
**Проверить каждую роль:**
1. **SELLER:**
- ✅ `/seller/partners/` доступен
- ❌ `/partners/` возвращает 404
- ❌ Нельзя зайти на `/fulfillment/partners/`
2. **FULFILLMENT:**
- ✅ `/fulfillment/partners/` доступен
- ❌ `/partners/` возвращает 404
- ❌ Нельзя зайти на `/seller/partners/`
3. **И т.д. для всех ролей**
---
## 🚦 ПЛАН БЕЗОПАСНОЙ РЕАЛИЗАЦИИ
### ПОРЯДОК РЕАЛИЗАЦИИ (БЕЗ РИСКА СЛОМАТЬ ПРОДАКШН)
#### ШАГ 1: СОЗДАНИЕ КОМПОНЕНТОВ (0 риска)
- [x] Создать роль-специфичные компоненты
- [x] НЕ удалять старые компоненты
- [x] НЕ удалять глобальные маршруты
#### ШАГ 2: ОБНОВЛЕНИЕ КАБИНЕТНЫХ МАРШРУТОВ (минимальный риск)
- [x] Заменить импорты в кабинетных page.tsx
- [x] Протестировать каждый кабинет
- [x] Проверить что все работает
#### ШАГ 3: ИСПРАВЛЕНИЕ ССЫЛОК (средний риск)
- [x] Найти все ссылки на глобальные маршруты
- [x] Исправить на роль-специфичные
- [x] Протестировать навигацию
#### ШАГ 4: УДАЛЕНИЕ ГЛОБАЛЬНЫХ МАРШРУТОВ (высокий риск)
- [x] Создать бэкап
- [x] Удалить глобальные page.tsx файлы
- [x] Протестировать что возвращается 404
#### ШАГ 5: ОЧИСТКА СТАРЫХ КОМПОНЕНТОВ (минимальный риск)
- [x] Удалить неиспользуемые wrapper компоненты
- [x] Обновить экспорты
### ПЛАН ОТКАТА
**Если что-то пойдет не так:**
```bash
# Быстрый откат глобальных маршрутов
git checkout HEAD~1 -- src/app/partners/page.tsx
git checkout HEAD~1 -- src/app/economics/page.tsx
# и т.д.
# Или полный откат коммита
git revert <commit-hash>
```
---
## 📊 МЕТРИКИ УСПЕХА
### КРИТЕРИИ ГОТОВНОСТИ
- [ ] ✅ Все 10 глобальных маршрутов удалены
- [ ] ✅ Все 4 роли имеют специфичные компоненты partners
- [ ] ✅ Все ссылки ведут на кабинетные маршруты
- [ ] ✅ Автоматические тесты безопасности проходят
- [ ] ✅ Ручное тестирование для всех ролей успешно
- [ ] ✅ Нет способа обойти роль-специфичную защиту
### ОЖИДАЕМЫЙ РЕЗУЛЬТАТ
**ДО:**
```
❌ /partners/ → PartnersDashboard (доступно всем ролям)
❌ /economics/ → EconomicsPageWrapper (обход useRoleGuard)
❌ Возможность обхода защиты
```
**ПОСЛЕ:**
```
✅ /seller/partners/ → SellerPartners (только SELLER)
✅ /fulfillment/partners/ → FulfillmentPartners (только FULFILLMENT)
✅ /partners/ → 404 Not Found
✅ Невозможно обойти роль-специфичную защиту
```
---
## 🎯 НАЧАЛО РЕАЛИЗАЦИИ
**Готов приступить к реализации по этому плану!**
**Следующее действие:** Создание роль-специфичных компонентов для Partners