feat: Add credentials viewer with copy buttons
- Add 'Credenciais Carregadas' section in web interface - Show services (Coolify, Gitea, Supabase, Logto) status - Display path and number of keys found - Add refresh button to reload credentials - Add copy to clipboard functionality for credentials
This commit is contained in:
@@ -864,6 +864,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CREDENCIAIS CARREGADAS -->
|
||||
<div class="section-title">Credenciais Carregadas</div>
|
||||
<div class="card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<span style="font-size: 0.85rem; color: var(--text-muted);">
|
||||
Credenciais sincronizadas dos serviços (Coolify, Gitea, Supabase, etc)
|
||||
</span>
|
||||
<button type="button" class="btn" onclick="loadCredentials()" style="padding: 0.4rem 0.75rem; font-size: 0.75rem;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14">
|
||||
<path d="M23 4v6h-6M1 20v-6h6"/>
|
||||
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
||||
</svg>
|
||||
Atualizar
|
||||
</button>
|
||||
</div>
|
||||
<div id="credentials-container" style="display: none;">
|
||||
<div id="credentials-list" style="max-height: 300px; overflow-y: auto;"></div>
|
||||
</div>
|
||||
<div id="credentials-loading" style="text-align: center; padding: 1rem; color: var(--text-muted);">
|
||||
Clique em "Atualizar" para carregar as credenciais
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">Terminal & Insights da IA</div>
|
||||
<div class="chat-layout">
|
||||
<!-- Coluna 1: Chat Técnico -->
|
||||
@@ -1333,6 +1356,76 @@
|
||||
showToast('Erro ao sincronizar.', true);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadCredentials() {
|
||||
const loadingEl = document.getElementById('credentials-loading');
|
||||
const containerEl = document.getElementById('credentials-container');
|
||||
const listEl = document.getElementById('credentials-list');
|
||||
|
||||
if (loadingEl) loadingEl.innerHTML = 'Carregando...';
|
||||
|
||||
try {
|
||||
// Sync first
|
||||
await apiFetch('/api/sync-credentials', { method: 'POST' });
|
||||
|
||||
// Get orchestrator status which has services info
|
||||
const res = await apiFetch('/api/orchestrator-status');
|
||||
const data = await res.json();
|
||||
|
||||
const services = data.credentials || {};
|
||||
const serviceNames = {
|
||||
coolify: 'Coolify (Orquestrador)',
|
||||
supabase: 'Supabase (BaaS)',
|
||||
gitea: 'Gitea (Git Server)',
|
||||
logto: 'Logto (Autenticação)'
|
||||
};
|
||||
|
||||
let html = '<div style="display: grid; gap: 1rem;">';
|
||||
|
||||
for (const [key, info] of Object.entries(services)) {
|
||||
const name = serviceNames[key] || key;
|
||||
const status = info.exists ? '<span style="color: var(--success);">Disponivel</span>' : '<span style="color: var(--danger);">Nao disponivel</span>';
|
||||
const keysCount = info.keys_count || 0;
|
||||
|
||||
html += `
|
||||
<div style="padding: 1rem; background: var(--bg-input); border-radius: 8px; border: 1px solid var(--border);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
|
||||
<strong style="color: var(--accent);">${name}</strong>
|
||||
${status}
|
||||
</div>
|
||||
<div style="font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.5rem;">
|
||||
Caminho: <code style="background: var(--bg-base); padding: 0.1rem 0.3rem; border-radius: 4px;">${info.path || 'N/A'}</code>
|
||||
</div>
|
||||
<div style="font-size: 0.75rem; color: var(--text-muted);">
|
||||
${keysCount} chave(s) encontrada(s)
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
if (loadingEl) loadingEl.style.display = 'none';
|
||||
if (containerEl) containerEl.style.display = 'block';
|
||||
if (listEl) listEl.innerHTML = html;
|
||||
|
||||
} catch (e) {
|
||||
if (loadingEl) {
|
||||
loadingEl.innerHTML = 'Erro ao carregar credenciais';
|
||||
loadingEl.style.color = 'var(--danger)';
|
||||
}
|
||||
console.error('Erro ao carregar credenciais:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function copyToClipboard(text, label) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
showToast(label + ' copiado!');
|
||||
} catch (e) {
|
||||
showToast('Erro ao copiar.', true);
|
||||
}
|
||||
}
|
||||
|
||||
async function testLLMSpeed() {
|
||||
const btn = document.getElementById('btn-test-llm');
|
||||
|
||||
Reference in New Issue
Block a user