BIG_UPDATE deleted vps, added s3 infrastructure.
This commit is contained in:
259
ospabhost/PUSH_NOTIFICATIONS_FIX.md
Normal file
259
ospabhost/PUSH_NOTIFICATIONS_FIX.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Исправление Push-уведомлений
|
||||
|
||||
## Проблема
|
||||
|
||||
Push-уведомления не работали по следующим причинам:
|
||||
|
||||
### 1. **Кнопка "Включить уведомления" не зависела от состояния разрешения**
|
||||
|
||||
#### До:
|
||||
```tsx
|
||||
{!pushEnabled && 'Notification' in window && (
|
||||
<button onClick={handleEnablePush}>Включить уведомления</button>
|
||||
)}
|
||||
```
|
||||
|
||||
**Проблема:** Кнопка показывалась, даже если пользователь заблокировал уведомления (`Notification.permission === 'denied'`). Клик по ней приводил к ошибке, так как браузер не давал повторно запросить разрешение.
|
||||
|
||||
#### После:
|
||||
```tsx
|
||||
{!pushEnabled && 'Notification' in window && pushPermission !== 'denied' && (
|
||||
<button onClick={handleEnablePush}>Включить уведомления</button>
|
||||
)}
|
||||
|
||||
{pushPermission === 'denied' && (
|
||||
<div className="alert alert-warning">
|
||||
Push-уведомления заблокированы. Разрешите их в настройках браузера.
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
**Решение:**
|
||||
- Кнопка показывается только когда `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
|
||||
Reference in New Issue
Block a user