Initial commit: Club DynaSQY
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
const { Router } = require('express');
|
||||
const pool = require('../config/db');
|
||||
const { authenticate } = require('../middleware/auth');
|
||||
const webPush = require('web-push');
|
||||
|
||||
const router = Router();
|
||||
|
||||
const publicVapidKey = process.env.VAPID_PUBLIC_KEY;
|
||||
const privateVapidKey = process.env.VAPID_PRIVATE_KEY;
|
||||
|
||||
if (publicVapidKey && privateVapidKey) {
|
||||
webPush.setVapidDetails('mailto:pierre@secourit.fr', publicVapidKey, privateVapidKey);
|
||||
}
|
||||
|
||||
router.post('/subscribe', authenticate, async (req, res) => {
|
||||
try {
|
||||
const { endpoint, keys, reminderDays } = req.body;
|
||||
if (!endpoint || !keys?.p256dh || !keys?.auth) {
|
||||
return res.status(400).json({ error: 'endpoint, p256dh, and auth required' });
|
||||
}
|
||||
await pool.query(
|
||||
`INSERT INTO push_subscriptions (user_id, endpoint, p256dh, auth, reminder_days)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE p256dh = VALUES(p256dh), auth = VALUES(auth), reminder_days = VALUES(reminder_days)`,
|
||||
[req.user.id, endpoint, keys.p256dh, keys.auth, reminderDays || 3]
|
||||
);
|
||||
res.json({ message: 'Abonnement aux notifications enregistré' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/unsubscribe', authenticate, async (req, res) => {
|
||||
try {
|
||||
const { endpoint } = req.body;
|
||||
if (!endpoint) return res.status(400).json({ error: 'endpoint required' });
|
||||
await pool.query('DELETE FROM push_subscriptions WHERE user_id = ? AND endpoint = ?', [req.user.id, endpoint]);
|
||||
res.json({ message: 'Désabonné' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/subscriptions', authenticate, async (req, res) => {
|
||||
try {
|
||||
const [rows] = await pool.query(
|
||||
'SELECT id, endpoint, reminder_days, last_sent_at, created_at FROM push_subscriptions WHERE user_id = ?',
|
||||
[req.user.id]
|
||||
);
|
||||
res.json(rows);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/vapid-public-key', (req, res) => {
|
||||
res.json({ publicKey: publicVapidKey });
|
||||
});
|
||||
|
||||
router.get('/members-with-push', authenticate, async (req, res) => {
|
||||
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin seulement' });
|
||||
try {
|
||||
const [rows] = await pool.query(
|
||||
`SELECT u.id, u.prenom, u.nom, u.societe,
|
||||
(SELECT COUNT(*) FROM push_subscriptions ps WHERE ps.user_id = u.id) AS has_push
|
||||
FROM users u WHERE u.actif = 1 ORDER BY u.prenom`
|
||||
);
|
||||
res.json(rows);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/broadcast', authenticate, async (req, res) => {
|
||||
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin seulement' });
|
||||
try {
|
||||
const { title, body, url, userIds } = req.body;
|
||||
if (!title || !body) return res.status(400).json({ error: 'Titre et message requis' });
|
||||
|
||||
let subs;
|
||||
if (userIds && Array.isArray(userIds) && userIds.length > 0) {
|
||||
const placeholders = userIds.map(() => '?').join(',');
|
||||
[subs] = await pool.query(
|
||||
`SELECT endpoint, p256dh, auth, user_id FROM push_subscriptions WHERE user_id IN (${placeholders})`,
|
||||
userIds
|
||||
);
|
||||
} else {
|
||||
[subs] = await pool.query('SELECT endpoint, p256dh, auth, user_id FROM push_subscriptions');
|
||||
}
|
||||
|
||||
if (subs.length === 0) return res.status(400).json({ error: 'Aucun abonné' });
|
||||
|
||||
const [notifResult] = await pool.query(
|
||||
'INSERT INTO notifications (sender_id, title, body) VALUES (?, ?, ?)',
|
||||
[req.user.id, title.slice(0, 100), body.slice(0, 255)]
|
||||
);
|
||||
const notifId = notifResult.insertId;
|
||||
|
||||
const recipientIds = [...new Set(subs.map((s) => s.user_id))];
|
||||
for (const uid of recipientIds) {
|
||||
await pool.query(
|
||||
'INSERT IGNORE INTO notification_recipients (notification_id, user_id) VALUES (?, ?)',
|
||||
[notifId, uid]
|
||||
);
|
||||
}
|
||||
|
||||
const payload = JSON.stringify({
|
||||
title: title.slice(0, 100),
|
||||
body: body.slice(0, 255),
|
||||
icon: '/logo.svg',
|
||||
badge: '/favicon.svg',
|
||||
data: { url: '/notifications' },
|
||||
});
|
||||
|
||||
let sent = 0;
|
||||
for (const sub of subs) {
|
||||
try {
|
||||
await webPush.sendNotification(
|
||||
{ endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
|
||||
payload
|
||||
);
|
||||
sent++;
|
||||
} catch (err) {
|
||||
if (err.statusCode === 410 || err.statusCode === 404) {
|
||||
await pool.query('DELETE FROM push_subscriptions WHERE endpoint = ?', [sub.endpoint]);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.json({ message: `Notification envoyée à ${sent} abonné(s) sur ${recipientIds.length} destinataire(s)` });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/test', authenticate, async (req, res) => {
|
||||
try {
|
||||
const [subs] = await pool.query(
|
||||
'SELECT endpoint, p256dh, auth FROM push_subscriptions WHERE user_id = ?',
|
||||
[req.user.id]
|
||||
);
|
||||
if (subs.length === 0) return res.status(400).json({ error: 'Aucun abonnement trouvé' });
|
||||
|
||||
const payload = JSON.stringify({
|
||||
title: 'Dyna Biz Coignières',
|
||||
body: 'Notification de test ✓',
|
||||
icon: '/logo.svg',
|
||||
badge: '/favicon.svg',
|
||||
data: { url: '/' },
|
||||
});
|
||||
|
||||
for (const sub of subs) {
|
||||
try {
|
||||
await webPush.sendNotification(
|
||||
{ endpoint: sub.endpoint, keys: { p256dh: sub.p256dh, auth: sub.auth } },
|
||||
payload
|
||||
);
|
||||
} catch (err) {
|
||||
if (err.statusCode === 410 || err.statusCode === 404) {
|
||||
await pool.query('DELETE FROM push_subscriptions WHERE endpoint = ?', [sub.endpoint]);
|
||||
}
|
||||
}
|
||||
}
|
||||
res.json({ message: 'Notification de test envoyée' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Erreur serveur' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user