const express = require('express'); const fs = require('fs'); const path = require('path'); const app = express(); const PORT = process.env.PORT || 80; // Caminhos dos arquivos const SECRETS_PATH = process.env.SECRETS_PATH || '/root/Apps/segredos.md'; const KEYS_JSON_PATH = path.join(__dirname, 'keys.json'); const KEYS_HTML_PATH = path.join(__dirname, 'index.html'); app.use(express.json()); // Autenticação básica simples const auth = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader) { res.setHeader('WWW-Authenticate', 'Basic realm="VaultUI"'); return res.status(401).send('Autenticação necessária'); } const [user, pass] = Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':'); if (user === 'tracksteel' && pass === '@@Gi05Br;;') { next(); } else { res.setHeader('WWW-Authenticate', 'Basic realm="VaultUI"'); return res.status(401).send('Credenciais inválidas'); } }; app.use(auth); // Rota para servir o app app.get('/', (req, res) => { res.sendFile(KEYS_HTML_PATH); }); // Servir o JSON de forma dinâmica (sempre sincronizado) app.get('/keys.json', (req, res) => { try { const data = syncAndGetJson(); res.json(data); } catch (err) { console.error('Erro ao sincronizar:', err); // Fallback para o arquivo local se a sincronização falhar if (fs.existsSync(KEYS_JSON_PATH)) { res.sendFile(KEYS_JSON_PATH); } else { res.status(500).send('Erro ao carregar dados'); } } }); // Endpoint explícito de sync app.get('/api/sync', (req, res) => { try { const data = syncAndGetJson(); res.json({ success: true, lastUpdated: data.lastUpdated }); } catch (err) { res.status(500).json({ success: false, error: err.message }); } }); // Servir outros arquivos estáticos app.use(express.static(__dirname)); function syncAndGetJson() { let currentData = { version: "1.0", lastUpdated: new Date().toISOString(), credentials: [], metadata: { categories: { destino: [], "tipo-dado": [] } } }; // Tenta carregar dados existentes para manter IDs e infos que não estão no segredos.md if (fs.existsSync(KEYS_JSON_PATH)) { currentData = JSON.parse(fs.readFileSync(KEYS_JSON_PATH, 'utf8')); } if (!fs.existsSync(SECRETS_PATH)) return currentData; const markdown = fs.readFileSync(SECRETS_PATH, 'utf8'); // 1. Extrair Seções e Linhas de Credenciais // Padrão: - **Nome:** `Valor` const credentialRegex = /- \*\*([^*]+):\*\* `([^`]+)`/g; let match; const foundValues = new Map(); while ((match = credentialRegex.exec(markdown)) !== null) { foundValues.set(match[1].trim(), match[2].trim()); } // 2. Extrair Tabelas (Resumo e APIs) const tableRegex = /\|([^|]+)\|([^|]+)\|([^|]+)\|/g; while ((match = tableRegex.exec(markdown)) !== null) { const col1 = match[1].trim(); const col2 = match[2].trim(); const col3 = match[3].trim(); if (col1 && col1 !== 'Recurso' && col1 !== 'Serviço / Site' && col1 !== 'Provedor' && !col1.includes('---')) { foundValues.set(col1, { user: col2, pass: col3 }); } } // 3. Atualizar ou Criar Credenciais no JSON foundValues.forEach((val, name) => { let cred = currentData.credentials.find(c => c.name.includes(name) || name.includes(c.name)); const isTableEntry = typeof val === 'object'; const displayValue = isTableEntry ? val.pass : val; const loginUser = isTableEntry ? val.user : null; if (cred) { cred.value = displayValue; if (loginUser && loginUser !== '-') cred.loginUsername = loginUser; cred.updatedAt = new Date().toISOString().split('T')[0]; } else { // Criar nova se não existir (ID simplificado) currentData.credentials.push({ id: `sync-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`, name: name, category: "infraestrutura", dataType: name.toLowerCase().includes('token') ? 'token' : 'password', value: displayValue, loginUsername: (loginUser && loginUser !== '-') ? loginUser : null, createdAt: new Date().toISOString().split('T')[0], updatedAt: new Date().toISOString().split('T')[0], tags: ["auto-sync"] }); } }); currentData.lastUpdated = new Date().toISOString(); // Salva o JSON atualizado fs.writeFileSync(KEYS_JSON_PATH, JSON.stringify(currentData, null, 2)); return currentData; } app.listen(PORT, () => { console.log(`VaultUI Server rodando na porta ${PORT}`); });