
КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ: - Исправлено отображение входящих заявок (неправильное извлечение данных) - Устранен 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>
15 KiB
🚨 ПЛАН УСТРАНЕНИЯ ГЛОБАЛЬНЫХ МАРШРУТОВ И СОЗДАНИЯ РОЛЬ-СПЕЦИФИЧНЫХ КОМПОНЕНТОВ
Дата: 2025-09-19
Приоритет: 🔴 КРИТИЧЕСКИЙ
Статус: В реализации
Цель: Устранить критические уязвимости безопасности через удаление глобальных маршрутов
🔍 РЕЗУЛЬТАТЫ МАКСИМАЛЬНОЙ ДИАГНОСТИКИ
ОБНАРУЖЕННЫЕ ГЛОБАЛЬНЫЕ МАРШРУТЫ
10 критических глобальных page.tsx файлов:
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:
// src/components/messenger/messenger-empty-state.tsx:12
router.push('/market') // ❌ Ведет на глобальный маршрут!
АНАЛИЗ УЯЗВИМОСТИ
Сценарий атаки:
1. Пользователь LOGIST авторизован ✅
2. Заходит на /partners/ ❌ (обходит useRoleGuard)
3. Видит PartnersDashboard со всеми табами ❌
4. Получает доступ к интерфейсу других ролей ❌
Критичность: 🔴 Высокая - возможность обхода роль-специфичной защиты
🎯 ДЕТАЛЬНЫЙ ПЛАН УСТРАНЕНИЯ
ЭТАП 1: БЕЗОПАСНОЕ УДАЛЕНИЕ ГЛОБАЛЬНЫХ МАРШРУТОВ
1.1 ПОДГОТОВКА К УДАЛЕНИЮ
Создать бэкап:
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 БЕЗОПАСНОЕ УДАЛЕНИЕ
Последовательность удаления (от менее к более критичным):
-
Второстепенные разделы:
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
-
Основные разделы:
rm src/app/supplies/page.tsx rm src/app/economics/page.tsx
-
Критичные разделы (после создания замены):
rm src/app/partners/page.tsx rm src/app/market/page.tsx rm src/app/messenger/page.tsx
ЭТАП 2: СОЗДАНИЕ РОЛЬ-СПЕЦИФИЧНЫХ КОМПОНЕНТОВ
2.1 PARTNERS - ПЕРВЫЙ ПРИОРИТЕТ
Анализ текущего PartnersDashboard:
// Текущие табы (одинаковые для всех ролей):
- Мои контрагенты
- Фулфилмент
- Селлеры
- Логистика
- Поставщик
- Рефералы
Создание роль-специфичных компонентов:
A. SellerPartners:
// 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:
// 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:
// 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:
// 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 для каждой роли
- Логика мессенджера одинакова, но контрагенты разные
Создание роль-специфичных мессенджеров:
// src/components/messenger/seller-messenger.tsx
export function SellerMessenger() {
const { user } = useAuthContext()
if (user?.organization?.type !== 'SELLER') {
redirect('/login')
}
// Специфичная логика для селлера
return <MessengerDashboard />
}
2.3 MARKET - ТРЕТИЙ ПРИОРИТЕТ
Создание роль-специфичных компонентов маркета:
// 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 в кабинетах:
// 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: ИСПРАВЛЕНИЕ ССЫЛОК
Найти и исправить все ссылки на глобальные маршруты:
// 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 АВТОМАТИЧЕСКИЕ ТЕСТЫ
Создать тесты для проверки роль-специфичного доступа:
// 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 РУЧНОЕ ТЕСТИРОВАНИЕ
Проверить каждую роль:
-
SELLER:
- ✅
/seller/partners/
доступен - ❌
/partners/
возвращает 404 - ❌ Нельзя зайти на
/fulfillment/partners/
- ✅
-
FULFILLMENT:
- ✅
/fulfillment/partners/
доступен - ❌
/partners/
возвращает 404 - ❌ Нельзя зайти на
/seller/partners/
- ✅
-
И т.д. для всех ролей
🚦 ПЛАН БЕЗОПАСНОЙ РЕАЛИЗАЦИИ
ПОРЯДОК РЕАЛИЗАЦИИ (БЕЗ РИСКА СЛОМАТЬ ПРОДАКШН)
ШАГ 1: СОЗДАНИЕ КОМПОНЕНТОВ (0 риска)
- Создать роль-специфичные компоненты
- НЕ удалять старые компоненты
- НЕ удалять глобальные маршруты
ШАГ 2: ОБНОВЛЕНИЕ КАБИНЕТНЫХ МАРШРУТОВ (минимальный риск)
- Заменить импорты в кабинетных page.tsx
- Протестировать каждый кабинет
- Проверить что все работает
ШАГ 3: ИСПРАВЛЕНИЕ ССЫЛОК (средний риск)
- Найти все ссылки на глобальные маршруты
- Исправить на роль-специфичные
- Протестировать навигацию
ШАГ 4: УДАЛЕНИЕ ГЛОБАЛЬНЫХ МАРШРУТОВ (высокий риск)
- Создать бэкап
- Удалить глобальные page.tsx файлы
- Протестировать что возвращается 404
ШАГ 5: ОЧИСТКА СТАРЫХ КОМПОНЕНТОВ (минимальный риск)
- Удалить неиспользуемые wrapper компоненты
- Обновить экспорты
ПЛАН ОТКАТА
Если что-то пойдет не так:
# Быстрый откат глобальных маршрутов
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