fix(network): защитить ключи WireGuard и режим просмотра операций
This commit is contained in:
1 parent
c8f9c83f45
commit
a404da768d
23 files changed
+1648
-36
No files matched your search
@@ -184,6 +184,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
}) {
|
||||
const { mode, backendUrl } = useDataSource()
|
||||
const isLive = mode === "live"
|
||||
const canWrite = !isLive || can("mm:network:write")
|
||||
|
||||
const [liveIfaces, setLiveIfaces] = useState<WgIfaceWithServer[]>([])
|
||||
const [liveServers, setLiveServers] = useState<Server[]>([])
|
||||
@@ -446,6 +447,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
setCreateError(null)
|
||||
setBusy(true)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
const ep = parseEndpoint(form.peerEndpoint)
|
||||
await createWireGuardInterface(backendUrl, {
|
||||
serverId: form.serverId,
|
||||
@@ -495,6 +497,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
setImportError(null)
|
||||
setBusy(true)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
const res = await importWireGuard(backendUrl, {
|
||||
serverId: args.serverId,
|
||||
content: args.content,
|
||||
@@ -538,6 +541,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
setTogglePending(context)
|
||||
setToggleError(null)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
const result = await patchWireGuardInterface(backendUrl, iface.serverId, iface.rosId, {
|
||||
disabled: iface.enabled,
|
||||
})
|
||||
@@ -564,6 +568,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
setDeleteBusy(true)
|
||||
setDeleteError(null)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
if (pendingDelete.kind === "iface") {
|
||||
if (!pendingDelete.iface.rosId) {
|
||||
if (active.current) toast.info("Доступно только в live-режиме")
|
||||
@@ -599,6 +604,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
setPeerError(null)
|
||||
setBusy(true)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
const ep = parseEndpoint(form.endpoint)
|
||||
await createWireGuardPeer(backendUrl, {
|
||||
serverId: peerIface.serverId,
|
||||
@@ -630,6 +636,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
exportPending.current = epoch
|
||||
setExportBusy(true)
|
||||
try {
|
||||
if (!can("mm:network:write")) throw new Error("Нет прав на изменение сети или экспорт ключей")
|
||||
const peer = format === "peer-conf" ? selectWgExportPeer(exportIface.peers, exportPeerId) : undefined
|
||||
if (format === "peer-conf" && !peer) throw new Error("Выбранный пир не найден. Обновите список и выберите пира заново.")
|
||||
const res = await exportWireGuard(backendUrl, {
|
||||
@@ -671,7 +678,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
}
|
||||
|
||||
const emptyCreateAction = (
|
||||
<Button size="sm" disabled={!!urlError || !catalogKnown || loadError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
|
||||
<Button size="sm" disabled={!canWrite || !!urlError || !catalogKnown || loadError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
|
||||
<PlusIcon className="size-4" />
|
||||
Новый интерфейс
|
||||
</Button>
|
||||
@@ -687,6 +694,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
showAll
|
||||
allCount={completeScope ? displayIfaces.length : undefined}
|
||||
loading={isLive && loading && displayServers.length === 0}
|
||||
banner={!canWrite ? <p role="status" className="border-b px-4 py-2 text-sm text-muted-foreground">Режим просмотра. Изменение конфигурации и экспорт ключей недоступны.</p> : undefined}
|
||||
header={
|
||||
<PageHeader
|
||||
crumbs={[{ label: "Управление" }, { label: "WireGuard" }]}
|
||||
@@ -719,11 +727,11 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Button size="sm" variant="outline" disabled={!!urlError || !catalogKnown || loadError} onClick={() => { setImportError(null); setImportOpen(true) }}>
|
||||
<Button size="sm" variant="outline" disabled={!canWrite || !!urlError || !catalogKnown || loadError} onClick={() => { setImportError(null); setImportOpen(true) }}>
|
||||
<UploadIcon className="size-4" />
|
||||
Импорт
|
||||
</Button>
|
||||
<Button size="sm" disabled={!!urlError || !catalogKnown || loadError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
|
||||
<Button size="sm" disabled={!canWrite || !!urlError || !catalogKnown || loadError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
|
||||
<PlusIcon className="size-4" />
|
||||
Новый интерфейс
|
||||
</Button>
|
||||
@@ -843,15 +851,16 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
/>
|
||||
{catalogKnown && !urlError && (completeScope || filteredIfaces.length > 0) ? <WireguardDataGrid
|
||||
interfaces={filteredIfaces}
|
||||
canWrite={canWrite}
|
||||
compactServer={compactServer}
|
||||
emptyAction={emptyCreateAction}
|
||||
onExport={(iface) => openExport(iface, "rsc")}
|
||||
onAddPeer={selectedSourceError ? undefined : iface => { setPeerError(null); setPeerIface(iface) }}
|
||||
onToggle={selectedSourceError ? undefined : handleToggle}
|
||||
onAddPeer={!canWrite || selectedSourceError ? undefined : iface => { setPeerError(null); setPeerIface(iface) }}
|
||||
onToggle={!canWrite || selectedSourceError ? undefined : handleToggle}
|
||||
toggleBusy={togglePending !== null}
|
||||
onDelete={selectedSourceError ? undefined : (iface) => setPendingDelete({ kind: "iface", iface })}
|
||||
onDeletePeer={selectedSourceError ? undefined : (iface, peerId) => setPendingDelete({ kind: "peer", iface, peerId })}
|
||||
onExportPeer={(iface, peerId) => openExport(iface, "peer", peerId)}
|
||||
onDelete={!canWrite || selectedSourceError ? undefined : (iface) => setPendingDelete({ kind: "iface", iface })}
|
||||
onDeletePeer={!canWrite || selectedSourceError ? undefined : (iface, peerId) => setPendingDelete({ kind: "peer", iface, peerId })}
|
||||
onExportPeer={canWrite ? (iface, peerId) => openExport(iface, "peer", peerId) : undefined}
|
||||
/> : <p role="status" className="px-5 py-8 text-sm text-muted-foreground">Каталог интерфейсов пока неизвестен</p>}
|
||||
</DataPageCard>
|
||||
</TabsContent>
|
||||
@@ -869,22 +878,22 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
|
||||
compactServer={compactServer}
|
||||
emptyAction={
|
||||
scopedIfaces.length === 1 ? (
|
||||
<Button size="sm" disabled={selectedSourceError} onClick={() => { setPeerError(null); setPeerIface(scopedIfaces[0]) }}>
|
||||
<Button size="sm" disabled={!canWrite || selectedSourceError} onClick={() => { setPeerError(null); setPeerIface(scopedIfaces[0]) }}>
|
||||
<PlusIcon className="size-4" />
|
||||
Добавить пира
|
||||
</Button>
|
||||
) : emptyCreateAction
|
||||
}
|
||||
onDeletePeer={selectedSourceError ? undefined : (row) => {
|
||||
onDeletePeer={!canWrite || selectedSourceError ? undefined : (row) => {
|
||||
const iface = scopedIfaces.find((i) => i.id === row.ifaceId && i.serverId === row.serverId)
|
||||
if (!iface) return
|
||||
setPendingDelete({ kind: "peer", iface, peerId: row.id })
|
||||
}}
|
||||
onExportPeer={(row) => {
|
||||
onExportPeer={canWrite ? (row) => {
|
||||
const iface = scopedIfaces.find((i) => i.id === row.ifaceId && i.serverId === row.serverId)
|
||||
if (!iface) return
|
||||
openExport(iface, "peer", row.id)
|
||||
}}
|
||||
} : undefined}
|
||||
/> : <p role="status" className="px-5 py-8 text-sm text-muted-foreground">Каталог пиров пока неизвестен</p>}
|
||||
</DataPageCard>
|
||||
</TabsContent>
|
||||
|
||||
Reference in new issue
Block a user