Privacy settings #60
@@ -955,6 +955,93 @@ const requireAdmin = (req, res, next) => {
|
|||||||
return res.status(401).json({ error: 'Authentication required' });
|
return res.status(401).json({ error: 'Authentication required' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Middleware to check if user has granted a specific consent category
|
||||||
|
const requireConsent = (category) => {
|
||||||
|
return async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const userId = req.session?.userId;
|
||||||
|
const sessionId = req.sessionID;
|
||||||
|
let consent;
|
||||||
|
if (userId) {
|
||||||
|
consent = await userDbGet('SELECT granted FROM user_consents WHERE user_id = ? AND category = ?', [userId, category]);
|
||||||
|
} else if (sessionId) {
|
||||||
|
consent = await userDbGet('SELECT granted FROM user_consents WHERE session_id = ? AND category = ?', [sessionId, category]);
|
||||||
|
}
|
||||||
|
if (consent && consent.granted) return next();
|
||||||
|
return res.status(403).json({ error: `Consent required: ${category}` });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Consent check error:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== CONSENT MANAGEMENT ==========
|
||||||
|
app.get('/api/consents', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.session?.userId;
|
||||||
|
const sessionId = req.sessionID;
|
||||||
|
const categories = ['essential', 'analytics', 'preferences', 'health_data'];
|
||||||
|
const result = {};
|
||||||
|
categories.forEach(c => { result[c] = c === 'essential'; });
|
||||||
|
if (userId) {
|
||||||
|
const rows = await userDbAll('SELECT category, granted FROM user_consents WHERE user_id = ?', [userId]);
|
||||||
|
rows.forEach(r => { result[r.category] = r.granted; });
|
||||||
|
} else if (sessionId) {
|
||||||
|
const rows = await userDbAll('SELECT category, granted FROM user_consents WHERE session_id = ?', [sessionId]);
|
||||||
|
rows.forEach(r => { result[r.category] = r.granted; });
|
||||||
|
}
|
||||||
|
result.essential = true;
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching consents:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.put('/api/consents', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.session?.userId;
|
||||||
|
const sessionId = req.sessionID;
|
||||||
|
const { categories } = req.body;
|
||||||
|
if (!categories || typeof categories !== 'object') {
|
||||||
|
return res.status(400).json({ error: 'categories object required' });
|
||||||
|
}
|
||||||
|
const allowedCategories = ['analytics', 'preferences', 'health_data'];
|
||||||
|
for (const cat of allowedCategories) {
|
||||||
|
if (cat in categories) {
|
||||||
|
const granted = Boolean(categories[cat]);
|
||||||
|
if (userId) {
|
||||||
|
await userDbRun(
|
||||||
|
`INSERT INTO user_consents (user_id, category, granted, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT (user_id, category) DO UPDATE SET granted = ?, updated_at = CURRENT_TIMESTAMP`,
|
||||||
|
[userId, cat, granted, granted]
|
||||||
|
);
|
||||||
|
} else if (sessionId) {
|
||||||
|
await userDbRun(
|
||||||
|
`INSERT INTO user_consents (session_id, category, granted, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT (session_id, category) DO UPDATE SET granted = ?, updated_at = CURRENT_TIMESTAMP`,
|
||||||
|
[sessionId, cat, granted, granted]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return updated consents
|
||||||
|
const result = { essential: true };
|
||||||
|
const cats = ['analytics', 'preferences', 'health_data'];
|
||||||
|
if (userId) {
|
||||||
|
const rows = await userDbAll('SELECT category, granted FROM user_consents WHERE user_id = ?', [userId]);
|
||||||
|
rows.forEach(r => { result[r.category] = r.granted; });
|
||||||
|
} else if (sessionId) {
|
||||||
|
const rows = await userDbAll('SELECT category, granted FROM user_consents WHERE session_id = ?', [sessionId]);
|
||||||
|
rows.forEach(r => { result[r.category] = r.granted; });
|
||||||
|
}
|
||||||
|
cats.forEach(c => { if (!(c in result)) result[c] = false; });
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving consents:', error);
|
||||||
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ========== RECENT SEARCHES (database-based) ==========
|
// ========== RECENT SEARCHES (database-based) ==========
|
||||||
|
|
||||||
const MAX_RECENT = 5;
|
const MAX_RECENT = 5;
|
||||||
|
|||||||
Reference in New Issue
Block a user