ligbox-ops-platform/deploy/vm112-wizard/frontend-provision037b.patch.py
Ligbox Spec Hub 038fb8f7ce feat(dns): Spec 037 DNS Viewer — Desk, Console e patches Wizard V4
Entrega read-only de apontamentos DNS (Cloudflare, OpenPanel BIND, público)
no Desk e Console /admin/dominio, com spec, scripts de rollback e patches
VM112 para painel lateral no passo DNS do onboarding (deploy wizard pendente).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 16:36:25 +00:00

165 lines
6.3 KiB
Python

#!/usr/bin/env python3
"""Frontend Spec 037b — provision-zone cria zona cliente na CF Ligbox."""
from pathlib import Path
APP = Path("/opt/ligbox-wizard/frontend/src/App.jsx")
text = APP.read_text(encoding="utf-8")
OLD = """ async function choosePortalDns() {
setDnsChoice('portal')
setError(null)
startBusy('dns_zone')
try {
const resolved = dnsResolve || (await api(`/onboarding/dns/resolve/${domain}`))
setDnsResolve(resolved)
if (!resolved.matched) {
throw new Error(
resolved.message ||
'Domínio não está nas contas Ligbox (ligit, itecnologys, ibytera).',
)
}
const cf = await refreshCfStatus()
setCfStatus(cf)
markActionDone('choosePortalDns')
markActionDone('verifyZone')
const data = await api('/onboarding/dns/cloudflare/apply', {
method: 'POST',
body: JSON.stringify({
domain,
zone_id: resolved.zone_id,
mail_aliases: sanitizeMailAliases(mailAliasInputs, domain),
}),
})
setPortalGuide({
message: resolved.message,
nameservers: cf?.nameservers || [],
status: cf,
ligbox_account_id: resolved.account_id,
})
setVerification(data.verification)
setResult({ type: 'dns', data })
markActionDone('applyPortalDns')
} catch (e) {
setError(e.message)
setDnsChoice(null)
setActionsDone((prev) => ({ ...prev, choosePortalDns: false }))
} finally {
stopBusy()
}
}"""
NEW = """ async function choosePortalDns() {
setDnsChoice('portal')
setError(null)
startBusy('dns_zone')
try {
const resolved = dnsResolve || (await api(`/onboarding/dns/resolve/${domain}`))
setDnsResolve(resolved)
const guide = await api('/onboarding/dns/cloudflare/provision-zone', {
method: 'POST',
body: JSON.stringify({ domain }),
})
setPortalGuide(guide)
const cf = guide.status || (await refreshCfStatus())
setCfStatus(cf)
markActionDone('choosePortalDns')
if (guide.verification) {
setVerification(guide.verification)
setResult({ type: 'dns', data: { verification: guide.verification } })
markActionDone('verifyZone')
markActionDone('applyPortalDns')
} else if (cf?.zone_in_account && cf?.can_apply_mail_records) {
markActionDone('verifyZone')
const data = await api('/onboarding/dns/cloudflare/apply', {
method: 'POST',
body: JSON.stringify({
domain,
zone_id: guide.zone_id || resolved.zone_id,
mail_aliases: sanitizeMailAliases(mailAliasInputs, domain),
}),
})
setVerification(data.verification)
setResult({ type: 'dns', data })
markActionDone('applyPortalDns')
}
} catch (e) {
setError(e.message)
setDnsChoice(null)
setActionsDone((prev) => ({ ...prev, choosePortalDns: false }))
} finally {
stopBusy()
}
}"""
if "provision-zone" in text and "if (!resolved.matched)" in text:
text = text.replace(OLD, NEW)
print("choosePortalDns restored with provision-zone")
# Auto mode: allow for new domains too
text = text.replace(
" const resolve = instructions?.resolve || dnsResolve\n if (resolve && !resolve.matched) return\n autoDnsAttempted.current = true",
" autoDnsAttempted.current = true",
)
# Ligbox button always enabled when can provision
text = text.replace(
""" label={
dnsResolve?.matched
? `Cloudflare Ligbox (${dnsResolve.account_id})`
: 'Cloudflare Ligbox (indisponível)'
}
hint={
dnsResolve?.matched
? dnsResolve.message
: 'Domínio não está nas contas ligit / itecnologys / ibytera.'
}
disabled={
loading ||
actionsDone.chooseExternalDns ||
actionsDone.chooseByoDns ||
!dnsResolve?.matched
}""",
""" label={
dnsResolve?.matched
? `Cloudflare Ligbox (${dnsResolve.account_id})`
: `Cloudflare Ligbox (${dnsResolve?.provision_account_id || 'nova zona'})`
}
hint={
dnsResolve?.matched
? dnsResolve.message
: 'Criar zona do seu domínio na Cloudflare gerenciada pela Ligbox.'
}
disabled={
loading ||
actionsDone.chooseExternalDns ||
actionsDone.chooseByoDns ||
dnsResolve?.can_provision_ligbox === false
}""",
)
# Simple mode warning
text = text.replace(
""" {!dnsResolve?.matched && !portalDnsApplied && (
<WizardStatusPanel variant="warn" icon={ShieldCheck} title="Escolha como apontar o DNS">
<p>
Este domínio não está nas contas Cloudflare Ligbox. Use{' '}
<strong>Minha conta Cloudflare</strong> ou{' '}
<strong>Registrador / DNS externo</strong> (botão técnico abaixo).
</p>
</WizardStatusPanel>
)}""",
""" {!dnsResolve?.matched && !portalDnsApplied && (
<WizardStatusPanel variant="info" icon={ShieldCheck} title="Domínio novo na Cloudflare Ligbox">
<p>
Vamos criar a zona do seu domínio na Cloudflare gerenciada pela Ligbox
{dnsResolve?.provision_account_id
? ` (conta ${dnsResolve.provision_account_id})`
: ''}
. Depois altere os nameservers no registrador.
</p>
</WizardStatusPanel>
)}""",
)
APP.write_text(text, encoding="utf-8")
print("App.jsx 037b patched OK")