abbd9374b4
Backend:
- config.js: config lida da tabela settings (id=newwhats_config) com fallback ENV;
loadConfigFromDb/saveConfigToDb + cache.
- index.js: endpoints superadmin GET/PUT /api/nw/config (secrets nunca em claro;
branco mantém valor), GET /api/nw/clinicas (dropdown), GET /api/nw/status (testar
conexão). server.js passa { superadminGuard }.
Frontend:
- PluginsView: NewwhatsConfigModal dedicado (carrega/salva no backend, dropdown de
clínicas em vez de ID cru, botão Testar conexão). Substitui o form genérico p/ newwhats.
Resolve UX ruim: nada de digitar ID de clínica; config passa a funcionar de fato.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.2 KiB
JavaScript
65 lines
2.2 KiB
JavaScript
// Config da integração com o motor NewWhats.
|
|
// Fonte: tabela `settings` (id='newwhats_config') — editável pelo super-admin na UI.
|
|
// Fallback: variáveis de ambiente (NEWWHATS_*), úteis para bootstrap/deploy.
|
|
//
|
|
// NEWWHATS_URL / motorUrl URL do motor
|
|
// NEWWHATS_INTEGRATION_KEY / integrationKey x-nw-key
|
|
// NEWWHATS_WEBHOOK_SECRET / webhookSecret HMAC do webhook
|
|
// NEWWHATS_CLINICA_ID / clinicaId clínica que este satélite atende
|
|
|
|
let cache = null; // { motorUrl, integrationKey, webhookSecret, clinicaId } | null
|
|
|
|
function fromEnv() {
|
|
return {
|
|
motorUrl: (process.env.NEWWHATS_URL || '').replace(/\/$/, ''),
|
|
integrationKey: process.env.NEWWHATS_INTEGRATION_KEY || '',
|
|
webhookSecret: process.env.NEWWHATS_WEBHOOK_SECRET || '',
|
|
clinicaId: process.env.NEWWHATS_CLINICA_ID || '',
|
|
};
|
|
}
|
|
|
|
// DB (se houver valor) tem prioridade; ENV preenche o que faltar.
|
|
export function getConfig() {
|
|
const env = fromEnv();
|
|
if (!cache) return env;
|
|
return {
|
|
motorUrl: (cache.motorUrl || env.motorUrl || '').replace(/\/$/, ''),
|
|
integrationKey: cache.integrationKey || env.integrationKey || '',
|
|
webhookSecret: cache.webhookSecret || env.webhookSecret || '',
|
|
clinicaId: cache.clinicaId || env.clinicaId || '',
|
|
};
|
|
}
|
|
|
|
export function isConfigured() {
|
|
const c = getConfig();
|
|
return Boolean(c.motorUrl && c.integrationKey);
|
|
}
|
|
|
|
// Carrega a config do banco para o cache (chamado no boot e após salvar).
|
|
export async function loadConfigFromDb(pool) {
|
|
try {
|
|
const { rows } = await pool.query("SELECT data FROM settings WHERE id = 'newwhats_config'");
|
|
cache = rows[0]?.data || {};
|
|
} catch {
|
|
if (!cache) cache = {};
|
|
}
|
|
return getConfig();
|
|
}
|
|
|
|
// Persiste no banco e atualiza o cache.
|
|
export async function saveConfigToDb(pool, cfg) {
|
|
const data = {
|
|
motorUrl: (cfg.motorUrl || '').replace(/\/$/, ''),
|
|
integrationKey: cfg.integrationKey || '',
|
|
webhookSecret: cfg.webhookSecret || '',
|
|
clinicaId: cfg.clinicaId || '',
|
|
};
|
|
await pool.query(
|
|
`INSERT INTO settings (id, category, data) VALUES ('newwhats_config', 'integration', $1)
|
|
ON CONFLICT (id) DO UPDATE SET data = EXCLUDED.data`,
|
|
[JSON.stringify(data)]
|
|
);
|
|
cache = data;
|
|
return getConfig();
|
|
}
|