let db; const DEFAULT_SETTINGS = { review_code: 'GUEST2026', review_min_length: '20', review_ip_cooldown_minutes: '5' }; function init(database) { db = database; initDefaultSettings(); } function initDefaultSettings() { Object.entries(DEFAULT_SETTINGS).forEach(([key, value]) => { db.run(`INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)`, [key, value], (err) => { if (err) console.error('Settings init error:', err); else console.log(`✅ Setting "${key}" initialized/confirmed`); }); }); } function get(key, callback) { db.get(`SELECT value FROM settings WHERE key = ?`, [key], (err, row) => { if (err) { console.error('Settings get error:', err); return callback(err, null); } callback(null, row ? row.value : null); }); } function set(key, value, callback) { db.run( `INSERT INTO settings (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP) ON CONFLICT(key) DO UPDATE SET value = ?, updated_at = CURRENT_TIMESTAMP`, [key, value, value], function(err) { if (err) { console.error('Settings set error:', err); return callback(err); } callback(null); } ); } function getAll(callback) { db.all(`SELECT * FROM settings`, [], (err, rows) => { if (err) { console.error('Settings getAll error:', err); return callback(err, null); } const settings = {}; rows.forEach(row => { settings[row.key] = row.value; }); callback(null, settings); }); } function getReviewCode(callback) { get('review_code', callback); } function setReviewCode(value, callback) { set('review_code', value, callback); } function checkIpCooldown(ip, callback) { const cooldownMinutes = 5; const cutoffTime = new Date(Date.now() - cooldownMinutes * 60 * 1000).toISOString(); db.get( `SELECT id FROM reviews WHERE ip_address = ? AND created_at > ? LIMIT 1`, [ip, cutoffTime], (err, row) => { if (err) { console.error('IP cooldown check error:', err); return callback(err, false); } callback(null, !!row); } ); } function setupRoutes(app, authenticateToken, requireAdmin) { app.get('/api/admin/settings', authenticateToken, requireAdmin, (req, res) => { getAll((err, settings) => { if (err) return res.status(500).json({ error: 'Database error' }); if (settings.review_code) { settings.review_code_masked = settings.review_code.replace(/./g, '*'); } res.json(settings); }); }); app.get('/api/admin/settings/review-code', authenticateToken, requireAdmin, (req, res) => { getReviewCode((err, code) => { if (err) return res.status(500).json({ error: 'Database error' }); res.json({ code: code }); }); }); app.put('/api/admin/settings/review-code', authenticateToken, requireAdmin, (req, res) => { const { code } = req.body; if (!code || code.length < 3) { return res.status(400).json({ error: 'Code must be at least 3 characters' }); } setReviewCode(code, (err) => { if (err) return res.status(500).json({ error: 'Database error' }); res.json({ message: 'Review code updated', code: code }); }); }); } module.exports = { init, get, set, getAll, getReviewCode, setReviewCode, checkIpCooldown, setupRoutes };