fix(ui): сохранять контекст экспорта сертификатов IPsec
This commit is contained in:
1 parent
86ecf764ff
commit
74e7cd257d
7 files changed
+151
-67
No files matched your search
+41
-41
@@ -173,6 +173,10 @@ export default function IpsecPage() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [busy, setBusy] = useState(false)
|
||||
const [certBusy, setCertBusy] = useState(false)
|
||||
const [certError, setCertError] = useState<string | null>(null)
|
||||
const certEpoch = useRef(0)
|
||||
const certPending = useRef(false)
|
||||
useEffect(() => () => { certEpoch.current += 1 }, [])
|
||||
|
||||
const [selectedServerId, setSelectedServerId] = useState(ALL_SERVERS_ID)
|
||||
const [workspaceTab, setWorkspaceTab] = useState<IpsecWorkspaceTab>("clients")
|
||||
@@ -393,6 +397,10 @@ export default function IpsecPage() {
|
||||
setEditing(null)
|
||||
await loadLive()
|
||||
if (res.bundle) {
|
||||
certEpoch.current += 1
|
||||
certPending.current = false
|
||||
setCertBusy(false)
|
||||
setCertError(null)
|
||||
setCertBundle(res.bundle)
|
||||
setCertClient(res.client ?? null)
|
||||
setCertByName(null)
|
||||
@@ -421,63 +429,51 @@ export default function IpsecPage() {
|
||||
}
|
||||
}
|
||||
|
||||
const loadCert = async (request: () => Promise<IpsecCertBundle>) => {
|
||||
if (certPending.current) return
|
||||
certPending.current = true
|
||||
const epoch = ++certEpoch.current
|
||||
setCertBusy(true)
|
||||
setCertError(null)
|
||||
try {
|
||||
const bundle = await request()
|
||||
if (epoch === certEpoch.current) setCertBundle(bundle)
|
||||
} catch (error) {
|
||||
if (epoch === certEpoch.current) setCertError(error instanceof Error ? error.message : "Ошибка экспорта сертификата")
|
||||
} finally {
|
||||
if (epoch === certEpoch.current) { certPending.current = false; setCertBusy(false) }
|
||||
}
|
||||
}
|
||||
|
||||
const openCert = async (client: IpsecClientDto) => {
|
||||
const byName = client.kind === "cert" && Boolean(client.certName)
|
||||
certEpoch.current += 1
|
||||
certPending.current = false
|
||||
setCertClient(byName ? null : client)
|
||||
setCertByName(byName ? { serverId: client.serverId, name: client.certName! } : null)
|
||||
setCertBundle(null)
|
||||
setCertOpen(true)
|
||||
setCertBusy(true)
|
||||
try {
|
||||
const passphrase = `mm-${Math.random().toString(36).slice(2, 10)}`
|
||||
const bundle = byName
|
||||
? await exportIpsecCertByName(backendUrl, client.serverId, client.certName!, passphrase)
|
||||
: await exportIpsecUserCert(backendUrl, client.serverId, client.rosId, passphrase)
|
||||
setCertBundle(bundle)
|
||||
} catch (e) {
|
||||
toast.error("Ошибка экспорта сертификата", {
|
||||
description: e instanceof Error ? e.message : String(e),
|
||||
})
|
||||
setCertOpen(false)
|
||||
} finally {
|
||||
setCertBusy(false)
|
||||
}
|
||||
const passphrase = crypto.randomUUID()
|
||||
await loadCert(() => byName
|
||||
? exportIpsecCertByName(backendUrl, client.serverId, client.certName!, passphrase)
|
||||
: exportIpsecUserCert(backendUrl, client.serverId, client.rosId, passphrase))
|
||||
}
|
||||
|
||||
/** Экспорт .p12 существующего клиентского серта по имени (client1/anakondra и т.п.). */
|
||||
const openCertByName = async (serverId: string, cert: IpsecCertInfoDto) => {
|
||||
certEpoch.current += 1
|
||||
certPending.current = false
|
||||
setCertByName({ serverId, name: cert.name })
|
||||
setCertClient(null)
|
||||
setCertBundle(null)
|
||||
setCertOpen(true)
|
||||
setCertBusy(true)
|
||||
try {
|
||||
const passphrase = `mm-${Math.random().toString(36).slice(2, 10)}`
|
||||
const bundle = await exportIpsecCertByName(backendUrl, serverId, cert.name, passphrase)
|
||||
setCertBundle(bundle)
|
||||
} catch (e) {
|
||||
toast.error("Ошибка экспорта сертификата", {
|
||||
description: e instanceof Error ? e.message : String(e),
|
||||
})
|
||||
setCertOpen(false)
|
||||
} finally {
|
||||
setCertBusy(false)
|
||||
}
|
||||
await loadCert(() => exportIpsecCertByName(backendUrl, serverId, cert.name, crypto.randomUUID()))
|
||||
}
|
||||
|
||||
const reexportCert = async (passphrase: string) => {
|
||||
if (!certClient && !certByName) return
|
||||
setCertBusy(true)
|
||||
try {
|
||||
const bundle = certByName
|
||||
? await exportIpsecCertByName(backendUrl, certByName.serverId, certByName.name, passphrase)
|
||||
: await exportIpsecUserCert(backendUrl, certClient!.serverId, certClient!.rosId, passphrase)
|
||||
setCertBundle(bundle)
|
||||
} catch (e) {
|
||||
toast.error("Ошибка экспорта", { description: e instanceof Error ? e.message : String(e) })
|
||||
} finally {
|
||||
setCertBusy(false)
|
||||
}
|
||||
await loadCert(() => certByName
|
||||
? exportIpsecCertByName(backendUrl, certByName.serverId, certByName.name, passphrase)
|
||||
: exportIpsecUserCert(backendUrl, certClient!.serverId, certClient!.rosId, passphrase))
|
||||
}
|
||||
|
||||
const confirmDelete = async () => {
|
||||
@@ -850,7 +846,11 @@ export default function IpsecPage() {
|
||||
|
||||
<IpsecCertSheet
|
||||
open={certOpen}
|
||||
onOpenChange={(v) => { setCertOpen(v); if (!v) setCertByName(null) }}
|
||||
onOpenChange={(v) => {
|
||||
if (!v) { certEpoch.current += 1; certPending.current = false; setCertBusy(false); setCertBundle(null); setCertClient(null); setCertByName(null) }
|
||||
setCertOpen(v)
|
||||
}}
|
||||
error={certError}
|
||||
bundle={certBundle}
|
||||
busy={certBusy}
|
||||
onReexport={reexportCert}
|
||||
|
||||
Reference in new issue
Block a user