diff --git a/apps/backend/server.js b/apps/backend/server.js index a461e0c..74d7480 100644 --- a/apps/backend/server.js +++ b/apps/backend/server.js @@ -253,34 +253,70 @@ async function initDatabase() { `); } - await dbRun(` - CREATE TABLE IF NOT EXISTS push_subscriptions ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - medicine_nregistro TEXT NOT NULL, - medicine_name TEXT, - endpoint TEXT NOT NULL, - p256dh TEXT NOT NULL, - auth TEXT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(medicine_nregistro, endpoint) - ) - `); - await dbRun(`CREATE INDEX IF NOT EXISTS idx_push_subscriptions_med ON push_subscriptions(medicine_nregistro)`); + // Push subscription tables — PG when available, SQLite fallback + if (pgPool) { + await pgPool.query(` + CREATE TABLE IF NOT EXISTS push_subscriptions ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + medicine_nregistro TEXT NOT NULL, + medicine_name TEXT, + endpoint TEXT NOT NULL, + p256dh TEXT NOT NULL, + auth TEXT NOT NULL, + created_at TIMESTAMPTZ DEFAULT NOW(), + UNIQUE(user_id, medicine_nregistro, endpoint) + ) + `); + await pgPool.query(`CREATE INDEX IF NOT EXISTS idx_push_subscriptions_med ON push_subscriptions(medicine_nregistro)`); + await pgPool.query(`CREATE INDEX IF NOT EXISTS idx_push_subscriptions_user ON push_subscriptions(user_id)`); - await dbRun(` - CREATE TABLE IF NOT EXISTS push_subscriptions_pharmacy ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - medicine_nregistro TEXT NOT NULL, - medicine_name TEXT, - pharmacy_id INTEGER NOT NULL, - endpoint TEXT NOT NULL, - p256dh TEXT NOT NULL, - auth TEXT NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(medicine_nregistro, pharmacy_id, endpoint) - ) - `); - await dbRun(`CREATE INDEX IF NOT EXISTS idx_push_subs_pharm ON push_subscriptions_pharmacy(medicine_nregistro, pharmacy_id)`); + await pgPool.query(` + CREATE TABLE IF NOT EXISTS push_subscriptions_pharmacy ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + medicine_nregistro TEXT NOT NULL, + medicine_name TEXT, + pharmacy_id INTEGER NOT NULL, + endpoint TEXT NOT NULL, + p256dh TEXT NOT NULL, + auth TEXT NOT NULL, + created_at TIMESTAMPTZ DEFAULT NOW(), + UNIQUE(user_id, medicine_nregistro, pharmacy_id, endpoint) + ) + `); + await pgPool.query(`CREATE INDEX IF NOT EXISTS idx_push_subs_pharm ON push_subscriptions_pharmacy(medicine_nregistro, pharmacy_id)`); + await pgPool.query(`CREATE INDEX IF NOT EXISTS idx_push_subs_pharm_user ON push_subscriptions_pharmacy(user_id)`); + } else { + await dbRun(` + CREATE TABLE IF NOT EXISTS push_subscriptions ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + medicine_nregistro TEXT NOT NULL, + medicine_name TEXT, + endpoint TEXT NOT NULL, + p256dh TEXT NOT NULL, + auth TEXT NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE(medicine_nregistro, endpoint) + ) + `); + await dbRun(`CREATE INDEX IF NOT EXISTS idx_push_subscriptions_med ON push_subscriptions(medicine_nregistro)`); + + await dbRun(` + CREATE TABLE IF NOT EXISTS push_subscriptions_pharmacy ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + medicine_nregistro TEXT NOT NULL, + medicine_name TEXT, + pharmacy_id INTEGER NOT NULL, + endpoint TEXT NOT NULL, + p256dh TEXT NOT NULL, + auth TEXT NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE(medicine_nregistro, pharmacy_id, endpoint) + ) + `); + await dbRun(`CREATE INDEX IF NOT EXISTS idx_push_subs_pharm ON push_subscriptions_pharmacy(medicine_nregistro, pharmacy_id)`); + } if (!pgPool) { // SQLite-only migrations for existing deployments @@ -307,9 +343,11 @@ if (!pgPool) { try { await dbRun('ALTER TABLE users ADD COLUMN city TEXT'); } catch {} } -// Add user_id to push tables (SQLite — no cross-DB FK) - try { await dbRun('ALTER TABLE push_subscriptions ADD COLUMN user_id INTEGER'); } catch {} - try { await dbRun('ALTER TABLE push_subscriptions_pharmacy ADD COLUMN user_id INTEGER'); } catch {} +// Add user_id to push tables (SQLite only — PG tables already have it) + if (!pgPool) { + try { await dbRun('ALTER TABLE push_subscriptions ADD COLUMN user_id INTEGER'); } catch {} + try { await dbRun('ALTER TABLE push_subscriptions_pharmacy ADD COLUMN user_id INTEGER'); } catch {} + } // Create alerts table for persistent Avisos data try { @@ -1733,35 +1771,35 @@ app.post('/api/notifications/subscribe', requireAuth, async (req, res) => { } if (pharmacy_id) { - const existing = await dbGet( - 'SELECT id FROM push_subscriptions_pharmacy WHERE medicine_nregistro = ? AND pharmacy_id = ? AND endpoint = ?', - [medicine_nregistro, pharmacy_id, endpoint] + const existing = await userDbGet( + 'SELECT id FROM push_subscriptions_pharmacy WHERE user_id = ? AND medicine_nregistro = ? AND pharmacy_id = ? AND endpoint = ?', + [userId, medicine_nregistro, pharmacy_id, endpoint] ); if (existing) { - await dbRun( - 'UPDATE push_subscriptions_pharmacy SET medicine_name = ?, p256dh = ?, auth = ?, user_id = ? WHERE id = ?', - [medicine_name || null, p256dh, auth, userId, existing.id] + await userDbRun( + 'UPDATE push_subscriptions_pharmacy SET medicine_name = ?, p256dh = ?, auth = ? WHERE id = ? AND user_id = ?', + [medicine_name || null, p256dh, auth, existing.id, userId] ); } else { - await dbRun( - 'INSERT INTO push_subscriptions_pharmacy (medicine_nregistro, medicine_name, pharmacy_id, endpoint, p256dh, auth, user_id) VALUES (?, ?, ?, ?, ?, ?, ?)', - [medicine_nregistro, medicine_name || null, pharmacy_id, endpoint, p256dh, auth, userId] + await userDbRun( + 'INSERT INTO push_subscriptions_pharmacy (user_id, medicine_nregistro, medicine_name, pharmacy_id, endpoint, p256dh, auth) VALUES (?, ?, ?, ?, ?, ?, ?)', + [userId, medicine_nregistro, medicine_name || null, pharmacy_id, endpoint, p256dh, auth] ); } } else { - const existing = await dbGet( - 'SELECT id FROM push_subscriptions WHERE medicine_nregistro = ? AND endpoint = ?', - [medicine_nregistro, endpoint] + const existing = await userDbGet( + 'SELECT id FROM push_subscriptions WHERE user_id = ? AND medicine_nregistro = ? AND endpoint = ?', + [userId, medicine_nregistro, endpoint] ); if (existing) { - await dbRun( - 'UPDATE push_subscriptions SET medicine_name = ?, p256dh = ?, auth = ?, user_id = ? WHERE id = ?', - [medicine_name || null, p256dh, auth, userId, existing.id] + await userDbRun( + 'UPDATE push_subscriptions SET medicine_name = ?, p256dh = ?, auth = ? WHERE id = ? AND user_id = ?', + [medicine_name || null, p256dh, auth, existing.id, userId] ); } else { - await dbRun( - 'INSERT INTO push_subscriptions (medicine_nregistro, medicine_name, endpoint, p256dh, auth, user_id) VALUES (?, ?, ?, ?, ?, ?)', - [medicine_nregistro, medicine_name || null, endpoint, p256dh, auth, userId] + await userDbRun( + 'INSERT INTO push_subscriptions (user_id, medicine_nregistro, medicine_name, endpoint, p256dh, auth) VALUES (?, ?, ?, ?, ?, ?)', + [userId, medicine_nregistro, medicine_name || null, endpoint, p256dh, auth] ); } } @@ -1776,21 +1814,22 @@ app.post('/api/notifications/subscribe', requireAuth, async (req, res) => { app.delete('/api/notifications/unsubscribe', requireAuth, async (req, res) => { try { const { medicine_nregistro, endpoint, pharmacy_id } = req.body || {}; + const userId = req.session.userId; if (!endpoint) { return res.status(400).json({ error: 'endpoint is required' }); } if (pharmacy_id) { - await dbRun( - 'DELETE FROM push_subscriptions_pharmacy WHERE medicine_nregistro = ? AND pharmacy_id = ? AND endpoint = ?', - [medicine_nregistro, pharmacy_id, endpoint] + await userDbRun( + 'DELETE FROM push_subscriptions_pharmacy WHERE user_id = ? AND medicine_nregistro = ? AND pharmacy_id = ? AND endpoint = ?', + [userId, medicine_nregistro, pharmacy_id, endpoint] ); } else if (medicine_nregistro) { - await dbRun( - 'DELETE FROM push_subscriptions WHERE medicine_nregistro = ? AND endpoint = ?', - [medicine_nregistro, endpoint] + await userDbRun( + 'DELETE FROM push_subscriptions WHERE user_id = ? AND medicine_nregistro = ? AND endpoint = ?', + [userId, medicine_nregistro, endpoint] ); } else { - await dbRun('DELETE FROM push_subscriptions WHERE endpoint = ?', [endpoint]); + await userDbRun('DELETE FROM push_subscriptions WHERE user_id = ? AND endpoint = ?', [userId, endpoint]); } res.status(204).end(); } catch (error) { @@ -1803,14 +1842,14 @@ app.delete('/api/notifications/unsubscribe', requireAuth, async (req, res) => { app.get('/api/notifications/mine', requireAuth, async (req, res) => { try { const userId = req.session.userId; - const globalRows = await dbAll( + const globalRows = await userDbAll( `SELECT id, medicine_nregistro, medicine_name, created_at FROM push_subscriptions WHERE user_id = ? ORDER BY created_at DESC`, [userId] ); - const pharmacyRows = await dbAll( + const pharmacyRows = await userDbAll( `SELECT ps.id, ps.medicine_nregistro, ps.medicine_name, ps.pharmacy_id, ps.created_at, p.name AS pharmacy_name, p.address AS pharmacy_address FROM push_subscriptions_pharmacy ps @@ -1839,12 +1878,12 @@ app.delete('/api/notifications/mine', requireAuth, async (req, res) => { return res.status(400).json({ error: 'id must be a positive integer' }); } if (scope === 'pharmacy') { - await dbRun( + await userDbRun( 'DELETE FROM push_subscriptions_pharmacy WHERE id = ? AND user_id = ?', [rowId, userId] ); } else if (scope === 'global') { - await dbRun( + await userDbRun( 'DELETE FROM push_subscriptions WHERE id = ? AND user_id = ?', [rowId, userId] ); @@ -1861,11 +1900,11 @@ app.delete('/api/notifications/mine', requireAuth, async (req, res) => { async function sendPushForMedicine({ medicine_nregistro, medicine_name, pharmacy }) { if (!PUSH_ENABLED) return { sent: 0, failed: 0, pruned: 0 }; - const globalSubs = await dbAll( + const globalSubs = await userDbAll( 'SELECT id, endpoint, p256dh, auth FROM push_subscriptions WHERE medicine_nregistro = ?', [medicine_nregistro] ); - const pharmacySubs = pharmacy?.id ? await dbAll( + const pharmacySubs = pharmacy?.id ? await userDbAll( 'SELECT id, endpoint, p256dh, auth FROM push_subscriptions_pharmacy WHERE medicine_nregistro = ? AND pharmacy_id = ?', [medicine_nregistro, pharmacy.id] ) : []; @@ -1907,7 +1946,7 @@ async function sendPushForMedicine({ medicine_nregistro, medicine_name, pharmacy const deleteQuery = sub._pharmSub ? 'DELETE FROM push_subscriptions_pharmacy WHERE id = ?' : 'DELETE FROM push_subscriptions WHERE id = ?'; - await dbRun(deleteQuery, [sub.id]); + await userDbRun(deleteQuery, [sub.id]); pruned++; } catch {} } else { diff --git a/apps/frontend-mobile/.idea/caches/deviceStreaming.xml b/apps/frontend-mobile/.idea/caches/deviceStreaming.xml index ddfd7af..95dc662 100644 --- a/apps/frontend-mobile/.idea/caches/deviceStreaming.xml +++ b/apps/frontend-mobile/.idea/caches/deviceStreaming.xml @@ -1,8 +1,27 @@ + - - - + \ No newline at end of file diff --git a/apps/frontend-mobile/.idea/vcs.xml b/apps/frontend-mobile/.idea/vcs.xml index 6c0b863..64713b8 100644 --- a/apps/frontend-mobile/.idea/vcs.xml +++ b/apps/frontend-mobile/.idea/vcs.xml @@ -1,6 +1,7 @@ + \ No newline at end of file