From 62e3ded5a7145c7fb825df1dc31c973cf0ed1b18 Mon Sep 17 00:00:00 2001 From: VPS 4 Deploy Agent Date: Sun, 31 May 2026 15:36:56 +0200 Subject: [PATCH] =?UTF-8?q?feat(auth):=20token-first=20=E2=80=94=20device-?= =?UTF-8?q?info=20endpoint=20+=20pc=5Fname=20autoritativo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /api/auth/device-info?token=xxx: valida machine_token e retorna clinic_name e pc_name sem exigir email/senha. Usado pelo client para preview antes de salvar e para validação no save. - client-identify: quando autenticado via machine_token, usa socket.user.pcName como nome autoritativo (ignora o que o client enviou). - server-identified: clientInfo agora inclui 'pcName' para o client manter o nome em sincronia com o cadastro do servidor. Co-Authored-By: Claude Sonnet 4.6 --- dental-server/server.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/dental-server/server.js b/dental-server/server.js index e70ccba..b39e134 100644 --- a/dental-server/server.js +++ b/dental-server/server.js @@ -458,6 +458,24 @@ TRUST_PROXY=true app.use('/api/auth', authRoutes); app.use('/api/client', clientAuthRoutes); +// GET /api/auth/device-info?token=xxx — valida machine_token e retorna info do dispositivo. +// Usado pelo client para verificar o token antes de salvar (sem precisar de email/senha). +app.get('/api/auth/device-info', async (req, res) => { + try { + const token = (req.query.token || '').trim(); + if (!token) return res.status(400).json({ success: false, error: 'Token obrigatório.' }); + const device = await db.get( + 'SELECT clinic_name, pc_name, email, is_active FROM clinics_devices WHERE machine_token = $1', + [token] + ); + if (!device) return res.status(404).json({ success: false, error: 'Token não encontrado.' }); + if (!device.is_active) return res.status(403).json({ success: false, error: 'Dispositivo desativado.' }); + res.json({ success: true, clinicName: device.clinic_name, pcName: device.pc_name }); + } catch (e) { + res.status(500).json({ success: false, error: e.message }); + } +}); + // ================================================================ // MIDDLEWARE DE VERIFICAÇÃO DE INSTALAÇÃO (APENAS PARA APIs) @@ -839,13 +857,14 @@ io.on('connection', (socket) => { console.log('👤 Cliente identificado:', data?.type || 'SEM TYPE', data?.name || 'SEM NAME'); console.log('👤 Dados completos:', JSON.stringify(data, null, 2)); - if (!data || !data.type || !data.name) { + if (!data || !data.type) { console.error('❌ [client-identify] Dados inválidos:', data); socket.emit('error', { message: 'Dados de identificação inválidos' }); return; } - - const clientName = data.name.trim(); + + // Se autenticado via machine_token, o pc_name do cadastro é autoritativo + const clientName = (socket.user?.pcName || data.name || 'PC não identificado').trim(); const clientId = data.clientId || ''; // 1. Validar unicidade em relação aos clientes já conectados @@ -887,6 +906,7 @@ io.on('connection', (socket) => { type: data.type || 'unknown', name: clientName, clinicName: socket.user?.clinicName || (data.clinicName || '').trim() || 'Clínica não identificada', + pcName: socket.user?.pcName || clientName, version: data.version || '1.0.0', system: data.system || 'unknown', clientId: clientId,