114 lines
3.6 KiB
JavaScript
114 lines
3.6 KiB
JavaScript
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 }; |