From 489894a1a8d42af37e8cba2d3b42cd0d0a1a3fdd Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Wed, 10 Jun 2026 20:58:53 +0200 Subject: [PATCH] fix(agenda): escopa GET /api/agendamentos por clinica + auth (multi-tenancy) - GET /api/agendamentos: tenantGuard + WHERE clinica_id (antes: SELECT * sem filtro/sem auth -> vazava todas as clinicas) - getAgendamentos passa clinicaId da workspace ativa + guard de array - salvarAgendamento injeta clinica_id (senao novos ficariam nulos e sumiriam apos o escopo) Co-Authored-By: Claude Opus 4.8 --- backend/server.js | 6 ++++-- frontend/services/backend.ts | 11 ++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/server.js b/backend/server.js index d3f7b25..5599983 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1777,9 +1777,11 @@ app.get('/api/reports/productivity', async (req, res) => { }); // --- AGENDAMENTOS --- -app.get('/api/agendamentos', async (req, res) => { +app.get('/api/agendamentos', tenantGuard, async (req, res) => { try { - const { rows } = await pool.query('SELECT * FROM agendamentos'); + const clinicaId = req.clinicaId; + if (!clinicaId) return res.json([]); // sem clínica escopada → nada (isolamento entre unidades) + const { rows } = await pool.query('SELECT * FROM agendamentos WHERE clinica_id = $1', [clinicaId]); res.json(rows.map(r => ({ ...r, dentistaId: r.dentistaid, diff --git a/frontend/services/backend.ts b/frontend/services/backend.ts index fe9712e..b85db57 100644 --- a/frontend/services/backend.ts +++ b/frontend/services/backend.ts @@ -704,15 +704,20 @@ export const HybridBackend = { }, getAgendamentos: async (): Promise => { - const res = await apiFetch(`${API_URL}/agendamentos`, { }); - return await res.json(); + const clinicaId = HybridBackend.getActiveWorkspace()?.id || ''; + if (!clinicaId) return []; + const res = await apiFetch(`${API_URL}/agendamentos?clinicaId=${clinicaId}`, {}); + const data = await res.json().catch(() => []); + return Array.isArray(data) ? data : []; }, salvarAgendamento: async (ag: Partial) => { + const clinicaId = HybridBackend.getActiveWorkspace()?.id || ''; + const body = { ...ag, clinica_id: (ag as any).clinica_id || clinicaId }; const res = await apiFetch(`${API_URL}/agendamentos`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(ag) + body: JSON.stringify(body) }); if (!res.ok) { const err = await res.json().catch(() => ({} as any));