
• Полная миграция 64 компонентов с useAuth на AuthContext • Исправлена race condition в SMS регистрации • Улучшена SSR совместимость с таймаутами • Удалена дублирующая система регистрации • Обновлена документация архитектуры аутентификации Технические изменения: - AuthContext.tsx: централизованная система состояния - auth-flow.tsx: убрана агрессивная логика logout - confirmation-step.tsx: исправлена передача телефона - page.tsx: добавлена синхронизация состояния - 64 файла: миграция useAuth → useAuthContext 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
9.5 KiB
9.5 KiB
🔍 ПЛАН ИСПРАВЛЕНИЯ SMS РЕГИСТРАЦИИ - ДЕТАЛЬНЫЙ АНАЛИЗ ПРОБЛЕМЫ
Дата: 2025-09-18
Проблема: После SMS верификации пользователь перебрасывается на/
вместо продолжения регистрации
🚨 ОПИСАНИЕ ПРОБЛЕМЫ
📱 Что должно происходить (правильная логика SFERA):
ЕДИНЫЙ FLOW авторизации/регистрации:
- Пользователь вводит номер телефона → SMS отправляется
- Пользователь вводит SMS код → код верифицируется
- Определяется сценарий:
- СЦЕНАРИЙ A: Пользователь существует + есть организация → Dashboard
- СЦЕНАРИЙ B: Пользователь существует + НЕТ организации → Cabinet-select (выбор типа кабинета)
- СЦЕНАРИЙ C: Новый пользователь → Cabinet-select (выбор типа кабинета)
❌ Что происходит сейчас (баг):
1. Пользователь вводит телефон → ✅ SMS отправляется
2. Пользователь вводит SMS код → ✅ код верифицируется успешно
3. ❌ Пользователь перебрасывается на главную страницу `/`
4. ❌ AuthFlow сбрасывается на step: "phone"
5. ❌ Пользователь вынужден начинать регистрацию заново
🔍 Логи ошибки:
// SMS verification прошла успешно:
🌐 GraphQL REQUEST: { operationName: 'VerifySmsCode', variables: { phone: '76657584949', code: '1234' } }
POST /api/graphql 200 in 1295ms
// Но после этого:
AppShell state: { pathname: '/', isAuthenticated: false, hasUser: false }
🎢 AuthFlow - useEffect triggered with: { isAuthenticated: false, hasUser: false, currentStep: "phone" }
🎢 AuthFlow - User not authenticated, setting step to phone
КЛЮЧЕВАЯ ПРОБЛЕМА: isAuthenticated: false
после успешной SMS верификации!
🔍 КОРНЕВАЯ ПРИЧИНА
🎯 Диагноз:
AuthContext не обновляется после SMS верификации, поэтому:
- SMS верификация успешна → токен сохраняется в localStorage
- НО AuthContext остается
isAuthenticated: false, user: null
- app/page.tsx видит неавторизованного пользователя → redirect на
/login
- AuthFlow инициализируется заново → step: "phone"
🔧 Предполагаемые причины:
1. Timing issue в AuthContext:
- SMS-step сохраняет токен через
verifySmsCode()
- AuthContext не успевает обновить состояние
- useEffect в AuthFlow срабатывает с устаревшими данными
2. Конфликт между экземплярами AuthFlow:
- AuthGuard на
/dashboard
может создавать второй AuthFlow - Два AuthFlow конфликтуют между собой
3. Проблема в app/page.tsx:
- Слишком быстро перенаправляет до обновления AuthContext
- Не учитывает
isLoading
состояние
📋 ПЛАН ИСПРАВЛЕНИЯ
PHASE 1: ДИАГНОСТИКА И ЛОГИРОВАНИЕ
1.1 Добавить детальное логирование в AuthContext
// В verifySmsCode после успешной верификации:
console.warn('🔑 AuthContext - BEFORE setState:', {
isAuthenticated: this.isAuthenticated,
hasUser: !!this.user
})
setUser(result.user)
setIsAuthenticated(true)
console.warn('🔑 AuthContext - AFTER setState:', {
isAuthenticated: true,
hasUser: !!result.user,
userOrganization: result.user.organization
})
1.2 Добавить логирование в AuthFlow useEffect
useEffect(() => {
console.warn('🎢 AuthFlow - useEffect DETAILED:', {
isAuthenticated,
hasUser: !!user,
hasOrganization: !!user?.organization,
userFromContext: user,
currentStep: step,
timestamp: new Date().toISOString()
})
// Существующая логика...
}, [isAuthenticated, user])
1.3 Добавить логирование в app/page.tsx
useEffect(() => {
console.warn('📍 app/page.tsx - routing decision:', {
isLoading,
hasUser: !!user,
hasOrganization: !!user?.organization,
currentPath: window.location.pathname
})
// Существующая логика...
}, [router, user, isLoading])
PHASE 2: ИСПРАВЛЕНИЕ TIMING ISSUES
2.1 Исправить AuthContext - добавить промисы
const verifySmsCode = async (phone: string, code: string) => {
// ... существующий код ...
if (result.success && result.token && result.user) {
setAuthToken(result.token)
setUserData(result.user)
// Синхронно обновляем состояние
setUser(result.user)
setIsAuthenticated(true)
// ЖДЕМ обновления Apollo Client
await refreshApolloClient()
// Возвращаем промис когда все готово
return new Promise(resolve => {
setTimeout(() => {
resolve({ success: true, message: result.message, user: result.user })
}, 100) // Небольшая задержка для обновления состояния
})
}
}
2.2 Добавить isLoading в app/page.tsx
const { user, isLoading, isAuthenticated } = useAuthContext()
useEffect(() => {
// КРИТИЧНО: ждем завершения всех проверок
if (isLoading) {
console.warn('📍 app/page.tsx - still loading, waiting...')
return
}
// Только после isLoading: false делаем redirect
if (user?.organization) {
router.replace('/dashboard')
} else if (isAuthenticated) {
router.replace('/login') // Продолжить на странице регистрации
} else {
router.replace('/login')
}
}, [router, user, isLoading, isAuthenticated])
PHASE 3: УСТРАНЕНИЕ КОНФЛИКТОВ
3.1 Исправить AuthGuard
// НЕ создавать новый AuthFlow на dashboard
if (!isAuthenticated || (isAuthenticated && user && !user.organization)) {
// Перенаправить вместо показа AuthFlow
const router = useRouter()
useEffect(() => {
router.replace('/login')
}, [])
return <div>Перенаправление...</div>
}
3.2 Убрать window.location.href из AuthFlow
// ЗАМЕНИТЬ:
window.location.href = '/dashboard'
// НА:
router.push('/dashboard')
PHASE 4: ТЕСТИРОВАНИЕ
4.1 Тест-сценарии:
- Новый пользователь: phone → sms → cabinet-select → inn/api → complete → dashboard
- Существующий без организации: phone → sms → cabinet-select → inn/api → complete → dashboard
- Существующий с организацией: phone → sms → dashboard
- Партнерские коды: все сценарии с параметрами
4.2 Проверки:
- ✅ Нет перебросов на
/
- ✅ AuthFlow не сбрасывается на phone
- ✅ Состояние AuthContext корректное
- ✅ Нет создания второго AuthFlow
🎯 ОЖИДАЕМЫЙ РЕЗУЛЬТАТ
✅ После исправления:
1. Пользователь вводит телефон → SMS отправляется
2. Пользователь вводит SMS код → код верифицируется
3. AuthContext обновляется → isAuthenticated: true, user: {...}
4. AuthFlow определяет сценарий:
- СЦЕНАРИЙ A: user.organization есть → step: 'complete' → dashboard
- СЦЕНАРИЙ B/C: user.organization нет → step: 'cabinet-select'
5. Пользователь продолжает регистрацию БЕЗ сброса
📊 Логи после исправления:
🔑 AuthContext - SMS verification successful
🔑 AuthContext - State updated: isAuthenticated=true, user=...
🎢 AuthFlow - useEffect: { isAuthenticated: true, hasUser: true, hasOrganization: false }
🎢 AuthFlow - Setting step to cabinet-select
✅ Пользователь видит страницу выбора типа кабинета
🚀 ГОТОВНОСТЬ К РЕАЛИЗАЦИИ
✅ Проблема диагностирована: Timing issue в AuthContext + конфликт AuthFlow экземпляров
✅ План пошаговый: 4 фазы с детальным логированием и тестированием
✅ Минимальные изменения: Фокус на исправлении, а не переписывании архитектуры
🎯 Следующий шаг: Начать PHASE 1 - добавить детальное логирование для подтверждения диагноза