const express = require('express'); const router = express.Router(); const { authenticate } = require('../middleware/auth'); const { modifyLimiter, readLimiter } = require('../middleware/rateLimiter'); const { db } = require('../database/db'); const { validateSettings } = require('../middleware/inputValidation'); const logger = require('../utils/logger'); const SecurityAuditLogger = require('../utils/securityAudit'); // Get user settings router.get('/', authenticate, readLimiter, async (req, res) => { const ip = req.ip || req.headers['x-forwarded-for'] || req.connection.remoteAddress; const userAgent = req.headers['user-agent']; db.all( 'SELECT key, value FROM settings WHERE user_id = ?', [req.user.userId], async (err, settings) => { if (err) { return res.status(500).json({ error: 'Failed to fetch settings' }); } // CWE-778: Log sensitive data access await SecurityAuditLogger.logSensitiveDataAccess(req.user.userId, 'settings', { ip, userAgent, recordCount: settings.length, scope: 'own', accessMethod: 'view' }); // Convert array to object const settingsObj = {}; settings.forEach(s => { try { settingsObj[s.key] = JSON.parse(s.value); } catch { settingsObj[s.key] = s.value; } }); res.json(settingsObj); } ); }); // Update setting router.put('/:key', authenticate, modifyLimiter, validateSettings, (req, res) => { const { key } = req.params; const { value } = req.body; const jsonValue = typeof value === 'string' ? value : JSON.stringify(value); db.run( `INSERT INTO settings (user_id, key, value, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(user_id, key) DO UPDATE SET value = ?, updated_at = CURRENT_TIMESTAMP`, [req.user.userId, key, jsonValue, jsonValue], function(err) { if (err) { return res.status(500).json({ error: 'Failed to update setting' }); } res.json({ key, value }); } ); }); // Get specific setting router.get('/:key', authenticate, readLimiter, (req, res) => { const { key } = req.params; // Validate key format if (!key || !/^[a-zA-Z0-9_.-]+$/.test(key)) { return res.status(400).json({ error: 'Invalid setting key' }); } // Handle stream_settings specially - return defaults if not found if (key === 'stream_settings') { db.get( 'SELECT value FROM settings WHERE user_id = ? AND key = ?', [req.user.userId, key], (err, setting) => { if (err) { return res.status(500).json({ error: 'Failed to fetch setting' }); } // Return defaults if not found if (!setting) { return res.json({ value: { hwaccel: 'auto', hwaccel_device: '/dev/dri/renderD128', codec: 'h264', preset: 'veryfast', buffer_size: '2M', max_bitrate: '8M' } }); } try { res.json({ value: JSON.parse(setting.value) }); } catch { res.json({ value: setting.value }); } } ); return; } db.get( 'SELECT value FROM settings WHERE user_id = ? AND key = ?', [req.user.userId, key], (err, setting) => { if (err) { return res.status(500).json({ error: 'Failed to fetch setting' }); } if (!setting) { return res.status(404).json({ error: 'Setting not found' }); } try { res.json({ value: JSON.parse(setting.value) }); } catch { res.json({ value: setting.value }); } } ); }); module.exports = router;