# Исправление Push-уведомлений ## Проблема Push-уведомления не работали по следующим причинам: ### 1. **Кнопка "Включить уведомления" не зависела от состояния разрешения** #### До: ```tsx {!pushEnabled && 'Notification' in window && ( )} ``` **Проблема:** Кнопка показывалась, даже если пользователь заблокировал уведомления (`Notification.permission === 'denied'`). Клик по ней приводил к ошибке, так как браузер не давал повторно запросить разрешение. #### После: ```tsx {!pushEnabled && 'Notification' in window && pushPermission !== 'denied' && ( )} {pushPermission === 'denied' && (
Push-уведомления заблокированы. Разрешите их в настройках браузера.
)} ``` **Решение:** - Кнопка показывается только когда `pushPermission === 'default'` (не запрашивалось) - Если `pushPermission === 'denied'`, показывается предупреждение с инструкцией ### 2. **Service Worker мог не копироваться в dist при сборке** #### До: ```typescript // vite.config.ts export default defineConfig({ plugins: [react()], }) ``` **Проблема:** Файл `public/service-worker.js` не копировался автоматически в `dist/` при сборке, что приводило к 404 ошибке при регистрации. #### После: ```typescript export default defineConfig({ plugins: [ react(), { name: 'copy-service-worker', writeBundle() { copyFileSync( resolve(__dirname, 'public/service-worker.js'), resolve(__dirname, 'dist/service-worker.js') ) console.log('✅ Service worker скопирован в dist/') } } ], }) ``` **Решение:** Добавлен плагин Vite, который автоматически копирует `service-worker.js` в корень `dist/` при каждой сборке. ### 3. **Недостаточная диагностика ошибок** #### До: ```typescript console.error('Ошибка подключения Push-уведомлений:', error); ``` #### После: ```typescript console.log('📝 Регистрируем Service Worker...'); const registration = await navigator.serviceWorker.register('/service-worker.js'); console.log('✅ Service Worker зарегистрирован:', registration); console.log('📝 Получаем VAPID ключ...'); const vapidPublicKey = await getVapidKey(); console.log('✅ VAPID ключ получен:', vapidPublicKey.substring(0, 20) + '...'); console.log('📝 Создаём Push подписку...'); const subscription = await registration.pushManager.subscribe({...}); console.log('✅ Push подписка создана:', subscription.endpoint); ``` **Решение:** Добавлены подробные логи на каждом этапе подключения Push-уведомлений для быстрой диагностики проблем. ## Архитектура Push-уведомлений ### Frontend (`notificationService.ts`) ``` 1. Notification.requestPermission() → Запрос разрешения 2. navigator.serviceWorker.register() → Регистрация SW 3. GET /api/notifications/vapid-key → Получение публичного ключа 4. registration.pushManager.subscribe() → Создание подписки 5. POST /api/notifications/subscribe-push → Отправка подписки на сервер ``` ### Backend ``` 1. GET /api/notifications/vapid-key → Возвращает VAPID_PUBLIC_KEY из .env 2. POST /api/notifications/subscribe-push → Сохраняет подписку в PushSubscription 3. Отправка уведомлений → webpush.sendNotification() для каждой подписки ``` ### Service Worker (`public/service-worker.js`) ```javascript self.addEventListener('push', (event) => { const data = event.data.json(); self.registration.showNotification(data.title, { body: data.body, icon: data.icon || '/favicon.svg', ... }); }); ``` ## Проверка работы ### 1. Проверка VAPID ключей ```bash curl https://ospab.host:5000/api/notifications/vapid-key \ -H "Authorization: Bearer YOUR_TOKEN" ``` Должен вернуть: ```json { "success": true, "publicKey": "BPtLNi3TY1ifUWTkgZrhxoEH6ihDgknFcgzc3xzFQg07PeuJ1TsJDQZqA32VqlxUo03g_mG0yKCKqADb4r5fnsM" } ``` ### 2. Проверка Service Worker Откройте `https://ospab.host` → DevTools → Application → Service Workers Должен быть зарегистрирован: `/service-worker.js` со статусом **Activated** ### 3. Проверка подписки После нажатия "Включить уведомления" в консоли должны появиться: ``` 📝 Запрашиваем разрешение на уведомления... 📝 Результат запроса разрешения: granted 📝 Регистрируем Service Worker... ✅ Service Worker зарегистрирован: ServiceWorkerRegistration {...} 📝 Ожидаем готовности Service Worker... ✅ Service Worker готов 📝 Получаем VAPID ключ... ✅ VAPID ключ получен: BPtLNi3TY1ifUWTk... 📝 Создаём Push подписку... ✅ Push подписка создана: https://fcm.googleapis.com/fcm/send/... 📝 Отправляем подписку на сервер... ✅ Push-уведомления успешно подключены ``` ### 4. Проверка в базе данных ```sql SELECT * FROM PushSubscription WHERE userId = YOUR_USER_ID; ``` Должна быть запись с endpoint, p256dh, auth. ### 5. Тестовая отправка Можно создать тестовую отправку через backend: ```typescript import { sendPushNotification } from './modules/notification/push.service'; await sendPushNotification(userId, { title: 'Тестовое уведомление', body: 'Push-уведомления работают!', icon: '/logo192.png' }); ``` ## Состояния Notification.permission | Состояние | Описание | UI | |-----------|----------|-----| | `default` | Разрешение не запрашивалось | Показывается синяя кнопка "Включить уведомления" | | `granted` | Разрешение получено | Кнопка скрыта, уведомления работают | | `denied` | Пользователь заблокировал | Показывается красное предупреждение с инструкцией | ## Разблокировка в браузерах ### Chrome/Edge 1. Нажмите на иконку 🔒 (замок) слева от адресной строки 2. Найдите "Уведомления" 3. Выберите "Разрешить" 4. Обновите страницу ### Firefox 1. Откройте Настройки → Приватность и защита 2. Прокрутите до раздела "Разрешения" 3. Нажмите "Настройки" рядом с "Уведомления" 4. Найдите `ospab.host` и измените на "Разрешить" ### Safari 1. Safari → Настройки → Веб-сайты 2. Выберите "Уведомления" 3. Найдите `ospab.host` и выберите "Разрешить" ## Файлы изменены 1. ✅ `frontend/src/pages/dashboard/notifications.tsx` - Добавлено состояние `pushPermission` - Условный рендеринг кнопки/предупреждения - Обновление состояния после запроса 2. ✅ `frontend/src/services/notificationService.ts` - Добавлены подробные логи в `requestPushPermission()` - Эмодзи-маркеры для быстрого поиска в консоли 3. ✅ `frontend/vite.config.ts` - Плагин копирования `service-worker.js` в `dist/` ## Деплой ```bash # Frontend cd frontend npm run build # Скопируйте dist/ на production сервер # Backend (если были изменения) cd backend npm run build pm2 restart ospab-backend ``` ## Возможные проблемы ### Service Worker не регистрируется - **Проверка:** DevTools → Application → Service Workers - **Причина:** Файл `service-worker.js` не доступен по адресу `https://ospab.host/service-worker.js` - **Решение:** Убедитесь, что файл скопирован в корень `dist/` и доступен через nginx ### 403 Forbidden при запросе VAPID ключа - **Проверка:** Network → `/api/notifications/vapid-key` → Response - **Причина:** Не передаётся токен авторизации - **Решение:** Проверьте, что в localStorage есть `access_token` ### Push-уведомления не приходят - **Проверка:** Console → Ошибки от `webpush.sendNotification()` - **Причина:** Неправильные VAPID ключи или подписка устарела - **Решение:** Перегенерируйте VAPID ключи (`npx web-push generate-vapid-keys`) и переподпишитесь ### Подписка создаётся, но не сохраняется в БД - **Проверка:** Console → Network → `/api/notifications/subscribe-push` → Response - **Причина:** Ошибка на backend при сохранении в Prisma - **Решение:** Проверьте логи backend (`pm2 logs ospab-backend`) --- **Статус:** ✅ Исправлено и готово к тестированию **Дата:** 2025-01-20