# 📋 ПЛАН УЛУЧШЕНИЯ АРХИТЕКТУРЫ АВТОРИЗАЦИИ И БЕЗОПАСНОСТИ SFERA **Дата создания:** 2025-09-18 **Автор:** Claude AI + Вероника Смирнова **Статус:** В разработке ## 📊 Анализ текущего состояния ### ✅ Что уже реализовано и работает: 1. **Безопасные ID (CUID)** - Все модели используют `@default(cuid())` - Невозможно угадать ID других организаций - Пример: `cmfpe46iv0001y51d87f4vy2n` 2. **Защита типов кабинетов** - `useRoleGuard` на 49 страницах - Автоматический редирект при попытке доступа к чужому типу кабинета - Селлер не может зайти в кабинет Поставщика 3. **Изоляция данных на уровне API** - Все резолверы фильтруют по `organizationId` - Каждая организация видит только свои данные - Проверки в каждом GraphQL резолвере 4. **Структура роутинга** - Четкое разделение: `/seller/*`, `/fulfillment/*`, `/logistics/*`, `/wholesale/*` - DashboardHome автоматически направляет в нужный кабинет ### 🚨 Выявленные проблемы: 1. **Отсутствие глобального состояния (AuthContext)** - Каждый компонент создает свой экземпляр useAuth - Состояние не синхронизируется между компонентами - Sidebar не видит данные пользователя после авторизации 2. **Дублирование кода безопасности** - Одинаковые проверки в 50+ резолверах - Риск забыть добавить проверку в новый резолвер - Сложность поддержки 3. **Отсутствие персистентности** - При обновлении страницы состояние теряется - Повторные запросы GET_ME - Плохой UX при F5 4. **Нет серверной проверки роутов** - Проверки только на уровне компонентов - Страница начинает загружаться до проверки прав ## 🎯 План улучшений ### ФАЗА 1: Критические исправления #### 1. Реализация AuthContext [🔴 КРИТИЧНО] **Срок:** 2-3 часа **Приоритет:** Максимальный **Влияние:** Решает проблему с sidebar и синхронизацией состояния **План реализации:** 1. Создать `/src/contexts/AuthContext.tsx`: ```typescript import { createContext, useContext, useState, useEffect } from 'react' import { useApolloClient } from '@apollo/client' interface AuthContextType { user: User | null isAuthenticated: boolean isLoading: boolean checkAuth: () => Promise login: (phone: string, code: string) => Promise logout: () => void } const AuthContext = createContext(null) export function AuthProvider({ children }) { // Перенести всю логику из текущего useAuth const [user, setUser] = useState(null) const [isLoading, setIsLoading] = useState(true) // ... вся логика авторизации return ( {children} ) } export function useAuth() { const context = useContext(AuthContext) if (!context) { throw new Error('useAuth must be used within AuthProvider') } return context } ``` 2. Обновить `/src/app/providers.tsx`: ```typescript export function Providers({ children }) { return ( {children} ) } ``` 3. Убрать временные решения: - Удалить `useQuery(GET_ME)` из AppShell - Убрать передачу user через props - Вернуть оригинальную логику компонентов #### 2. GraphQL Middleware для безопасности [🟡 ВАЖНО] **Срок:** 1 день **Приоритет:** Высокий **Влияние:** Централизованная безопасность, чистый код **План реализации:** 1. Создать `/src/graphql/middleware/organizationAccess.ts`: ```typescript export const organizationAccessMiddleware = async ( resolve, parent, args, context, info ) => { // Пропускаем публичные операции const PUBLIC_OPERATIONS = ['login', 'sendSmsCode', 'verifySmsCode'] if (PUBLIC_OPERATIONS.includes(info.fieldName)) { return resolve(parent, args, context, info) } // Проверяем авторизацию if (!context.user?.organizationId) { throw new GraphQLError('Unauthorized', { extensions: { code: 'UNAUTHENTICATED' } }) } // Автоматически добавляем organizationId к запросам if (args.where && typeof args.where === 'object') { args.where.organizationId = context.user.organizationId } // Логирование для безопасности console.log(`[${context.user.organizationId}] ${info.fieldName}`, { userId: context.user.id, operation: info.fieldName, timestamp: new Date().toISOString() }) return resolve(parent, args, context, info) } ``` 2. Применить middleware ко всем резолверам 3. Удалить дублированные проверки из резолверов ### ФАЗА 2: Важные улучшения #### 3. Персистентность состояния [🟡 ВАЖНО] **Срок:** 0.5 дня **Приоритет:** Средний **Влияние:** Улучшение UX при обновлении страницы **План реализации:** 1. Добавить в AuthContext сохранение состояния: ```typescript // При успешной авторизации const encryptedUser = encrypt(JSON.stringify(user)) localStorage.setItem('auth:user', encryptedUser) // При инициализации const savedUser = localStorage.getItem('auth:user') if (savedUser) { const user = JSON.parse(decrypt(savedUser)) // Проверить валидность токена } ``` 2. Реализовать refresh token механизм 3. Очистка при logout #### 4. Next.js Middleware [🟢 ЖЕЛАТЕЛЬНО] **Срок:** 1 день **Приоритет:** Средний **Влияние:** Производительность, серверная защита **План реализации:** 1. Создать `/src/middleware.ts`: ```typescript import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' import { jwtVerify } from 'jose' export async function middleware(request: NextRequest) { const token = request.cookies.get('auth-token')?.value const pathname = request.nextUrl.pathname // Публичные маршруты const publicPaths = ['/', '/login', '/register'] if (publicPaths.includes(pathname)) return // Проверка токена if (!token) { return NextResponse.redirect(new URL('/login', request.url)) } try { const { payload } = await jwtVerify(token, new TextEncoder().encode(process.env.JWT_SECRET!)) const orgType = payload.organization?.type // Проверка доступа к кабинету if (pathname.startsWith('/seller') && orgType !== 'SELLER') { return NextResponse.redirect(new URL('/dashboard', request.url)) } // ... остальные проверки } catch (error) { return NextResponse.redirect(new URL('/login', request.url)) } } export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'] } ``` ### ФАЗА 3: Оптимизации #### 5. Улучшение загрузки [🔵 ОПЦИОНАЛЬНО] **Срок:** 1 неделя **Приоритет:** Низкий **Влияние:** Улучшение UX - Skeleton screens для всех страниц - Prefetch критических данных - Оптимистичные обновления UI - PWA функциональность #### 6. Расширенная система прав [🔵 ОПЦИОНАЛЬНО] **Срок:** 2 недели **Приоритет:** Низкий **Влияние:** Enterprise функциональность - Роли: Admin, Manager, Viewer - Permissions: canEdit, canDelete, canApprove - Аудит всех действий - Делегирование доступа ## 📈 Ожидаемые результаты ### После ФАЗЫ 1: - ✅ Sidebar работает стабильно - ✅ Состояние синхронизировано между компонентами - ✅ Единая точка контроля безопасности - ✅ Чистый, поддерживаемый код ### После ФАЗЫ 2: - ✅ Мгновенная загрузка после F5 - ✅ Защита на уровне сервера - ✅ Автоматическое управление сессией ### После ФАЗЫ 3: - ✅ Премиум UX - ✅ Enterprise-ready система - ✅ Готовность к масштабированию ## 🚀 Рекомендуемый порядок выполнения 1. **Неделя 1:** AuthContext (решает критическую проблему) 2. **Неделя 2:** GraphQL Middleware + Персистентность 3. **Месяц 2:** Next.js Middleware + Оптимизации по необходимости ## 📝 Критерии успеха - [ ] Sidebar отображается сразу после авторизации - [ ] Нет дублирования состояния между компонентами - [ ] Единая проверка безопасности для всех API запросов - [ ] Состояние сохраняется при обновлении страницы - [ ] Производительность не ухудшилась - [ ] Код стал чище и проще в поддержке --- *Документ будет обновляться по мере реализации плана*