/** * Domínios VM112 — Account Home card + modal (Spec 017) */ const DeskVm112Domains = (() => { const API_BASE = '/api'; let _domains = []; let _query = ''; function canManage() { return typeof canRunAudit === 'function' && canRunAudit(); } function isEnabled() { return window.DeskModules?.isEnabled('vm112-domains') !== false; } function esc(s) { return String(s ?? '') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } function filtered() { const q = _query.trim().toLowerCase(); if (!q) return _domains; return _domains.filter((d) => { const blob = [ d.domain, d.portal_admin_email, (d.accounts_preview || []).join(' '), (d.portal_users || []).map((u) => u.login_id).join(' '), ].join(' ').toLowerCase(); return blob.includes(q); }); } function statusBadges(d) { const parts = []; parts.push(d.carbonio_exists ? 'Carbonio' : 'sem CD'); parts.push(d.site_folder_exists ? 'site' : 'sem pasta'); parts.push(`${d.account_count != null ? d.account_count : (d.carbonio_exists ? 'CD' : '0')} contas`); return parts.join(' '); } function cardHtml() { if (!canManage() || !isEnabled()) return ''; const rows = filtered() .map((d) => ` `) .join(''); return `
Nenhum domínio encontrado na VM112.
'}Nenhum resultado.
'; if (foot) foot.textContent = `${filtered().length} / ${_domains.length} domínio(s) · Admin only`; list.querySelectorAll('[data-vm112-domain]').forEach((btn) => { btn.addEventListener('click', () => openModal(btn.dataset.vm112Domain)); }); } }); root.querySelector('#vm112-domains-refresh')?.addEventListener('click', async () => { const list = root.querySelector('#vm112-domains-list'); if (list) list.innerHTML = 'A carregar VM112…
'; try { await loadDomains(); await injectCard(root.closest('.cf-home') || root); } catch (e) { if (list) list.innerHTML = `Erro: ${esc(e.message)}
`; } }); root.querySelectorAll('[data-vm112-domain]').forEach((btn) => { btn.addEventListener('click', () => openModal(btn.dataset.vm112Domain)); }); } async function injectCard(cfHome) { if (!cfHome || !canManage() || !isEnabled()) return; const existing = cfHome.querySelector('#vm112-domains-panel'); if (existing) existing.remove(); const grid = cfHome.querySelector('.cf-grid-2'); const loading = document.createElement('div'); loading.id = 'vm112-domains-panel'; loading.className = 'cf-panel vm112-domains-panel'; loading.innerHTML = 'A carregar lista VM112 (pode demorar ~1 min)…
Erro: ${esc(e.message)}
A carregar…
'; loadModal(domain); modal.querySelector('[data-close-vm112-modal]')?.addEventListener('click', closeModal, { once: true }); modal.querySelector('.modal-backdrop')?.addEventListener('click', closeModal, { once: true }); } async function loadModal(domain) { const body = document.getElementById('vm112-domain-modal-body'); const sub = document.getElementById('vm112-domain-modal-sub'); try { const d = await fetchWithTimeout(`${API_BASE}/v1/vm112/domains/${encodeURIComponent(domain)}`, { headers: authHeaders({ 'Content-Type': 'application/json' }), }, 120000).then(async (res) => { if (!res.ok) { const data = await res.json().catch(() => ({})); throw new Error(data.detail || `${res.status}`); } return res.json(); }); sub.textContent = `${d.account_count || 0} conta(s) · ${d.mail_host || ''}`; const steps = (d.infra_status?.steps || []) .map((s) => `Admin portal: ${esc(d.portal_admin_email || '—')}
Carbonio: ${d.carbonio_exists ? 'ativo' : 'ausente'} · Pasta site: ${d.site_folder_exists ? 'sim' : 'não'}
Cloudflare: ${esc(cfTxt)}
Remove domínio Carbonio, contas, pasta ligbox-sites, zona Cloudflare, Traefik/SNI e registos Desk. Irreversível. Uso principal: limpar testes.
Erro: ${esc(e.message)}
`; } } async function runPurge(domain) { const msg = document.getElementById('vm112-purge-msg'); const confirmDomain = document.getElementById('vm112-purge-confirm')?.value?.trim() || ''; const rootPassword = document.getElementById('vm112-purge-root-pwd')?.value || ''; if (!confirmDomain || !rootPassword) { if (msg) msg.textContent = 'Preencha confirmação do domínio e senha Root.'; return; } if (!window.confirm(`PURGE definitivo de ${domain}? Esta ação não pode ser desfeita.`)) return; const btn = document.getElementById('vm112-purge-btn'); if (btn) { btn.disabled = true; btn.textContent = 'A apagar…'; } if (msg) msg.textContent = 'A executar purge VM112 + Desk…'; try { const res = await api(`/v1/vm112/domains/${encodeURIComponent(domain)}/purge`, { method: 'POST', body: JSON.stringify({ confirm_domain: confirmDomain, root_password: rootPassword }), }); if (msg) msg.textContent = `Concluído. Desk: ${JSON.stringify(res.desk || {})}`; _domains = _domains.filter((d) => d.domain !== domain); setTimeout(() => { closeModal(); const panel = document.getElementById('vm112-domains-panel'); if (panel) document.getElementById('vm112-domains-refresh')?.click(); }, 1500); } catch (e) { if (msg) msg.textContent = e.message || 'Purge falhou'; if (btn) { btn.disabled = false; btn.textContent = 'Apagar domínio e todos os dados'; } } } return { injectCard, loadDomains, openModal, canManage, isEnabled }; })(); window.DeskVm112Domains = DeskVm112Domains;