import { requireAuth, requireCap } from '../auth.js' import { pool } from '../db.js' import { isConnected as mqttConnected } from '../lib/mqtt.js' // Standard app_settings pattern (see conventions doc's "Cross-app integration // credentials" section) — plant only has one setting today (who gets alert // emails), but the shape is kept generic so a future integration is a one-row // addition to ALLOWED_KEYS + the seed default in db.js, not a new pattern. const ALLOWED_KEYS = new Set(['alert_notify_email']) export async function settingsRoutes(app) { app.addHook('preHandler', requireAuth) app.get('/api/settings', { preHandler: requireCap('settings') }, async () => { const { rows } = await pool.query('SELECT key, value, updated_at FROM app_settings ORDER BY key') return { settings: rows } }) app.put('/api/settings', { preHandler: requireCap('settings') }, async (req, reply) => { const { settings } = req.body || {} if (!Array.isArray(settings)) return reply.status(400).send({ error: 'settings must be an array' }) for (const { key, value } of settings) { if (!ALLOWED_KEYS.has(key)) continue await pool.query( `INSERT INTO app_settings (key, value, updated_at) VALUES ($1, $2, NOW()) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()`, [key, value ?? ''] ) } return { ok: true } }) app.get('/api/settings/mqtt-status', { preHandler: requireCap('settings') }, async () => { return { connected: mqttConnected(), note: mqttConnected() ? 'Connected to the shared MQTT broker.' : 'Not connected — the shared MQTT broker (LXC 104) may be unreachable, or plant-backend has no credentials in settings.', } }) }