fix(ui): согласовать права диагностики с API
This commit is contained in:
1 parent
cba3db1508
commit
b856215c03
6 files changed
+50
-11
No files matched your search
@@ -20,6 +20,7 @@ import { Input } from "@/components/ui/input"
|
||||
import { ServerRailLayout, ServerRailMobileButton } from "@/components/server-rail-layout"
|
||||
import { type ServerTileItem } from "@/components/server-tile-rail"
|
||||
import { servers, greTunnels, type GreTunnel, type Server } from "@/lib/data"
|
||||
import { can } from "@/lib/auth"
|
||||
import { readProbeOutput, probeServersSchema } from "@/lib/probe-response"
|
||||
import { useDataSource } from "@/lib/data-source"
|
||||
import {
|
||||
@@ -572,6 +573,9 @@ export default function ProbesPage() {
|
||||
|
||||
function ProbesContent() {
|
||||
const { mode, backendUrl } = useDataSource()
|
||||
const canRead = can("mm:servers:read")
|
||||
const canRun = can("mm:servers:write")
|
||||
const canReadGre = can("mm:filters:read")
|
||||
const isLive = mode === "live"
|
||||
const apiFetch = useMemo(() => makeApiFetch(backendUrl), [backendUrl])
|
||||
|
||||
@@ -600,7 +604,7 @@ function ProbesContent() {
|
||||
const [rosSrcV4, setRosSrcV4] = useState<string | null | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLive) return
|
||||
if (!isLive || !canRead) return
|
||||
let cancelled = false
|
||||
const ctrl = new AbortController()
|
||||
queueMicrotask(() => { if (!cancelled) { setLiveLoad("loading"); setCatalogError(null) } })
|
||||
@@ -624,7 +628,7 @@ function ProbesContent() {
|
||||
setLiveLoad("error")
|
||||
})
|
||||
return () => { cancelled = true; ctrl.abort() }
|
||||
}, [isLive, apiFetch, catalogRevision])
|
||||
}, [isLive, canRead, apiFetch, catalogRevision])
|
||||
|
||||
const allServers = useMemo(() => {
|
||||
if (!isLive) return servers
|
||||
@@ -668,7 +672,7 @@ function ProbesContent() {
|
||||
}, [isLive, srcId, apiFetch])
|
||||
|
||||
const ensureGre = useCallback(async (serverId: string) => {
|
||||
if (!isLive) return
|
||||
if (!isLive || !canReadGre) return
|
||||
try {
|
||||
const d = await apiFetch<{ tunnels: GreTunnel[] }>(
|
||||
`/api/filters/gre-tunnels?serverId=${encodeURIComponent(serverId)}`,
|
||||
@@ -677,7 +681,7 @@ function ProbesContent() {
|
||||
} catch {
|
||||
setGreByServer(prev => ({ ...prev, [serverId]: [] }))
|
||||
}
|
||||
}, [isLive, apiFetch])
|
||||
}, [isLive, canReadGre, apiFetch])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLive || !srcId) return
|
||||
@@ -748,7 +752,7 @@ function ProbesContent() {
|
||||
// ── run test ──
|
||||
const runTest = useCallback(async () => {
|
||||
const srv = allServers.find(s => s.id === srcId)
|
||||
if (!srv || !srv.enabled || runLock.current || (isLive && liveLoad !== "idle")) return
|
||||
if (!canRun || (tool === "bandwidth" && isLive && !canReadGre) || !srv || !srv.enabled || runLock.current || (isLive && liveLoad !== "idle")) return
|
||||
const id = String(nextId.current++)
|
||||
const numericServerId = Number.parseInt(srcId, 10)
|
||||
|
||||
@@ -875,6 +879,8 @@ function ProbesContent() {
|
||||
}, [
|
||||
isLive,
|
||||
liveLoad,
|
||||
canRun,
|
||||
canReadGre,
|
||||
allServers,
|
||||
srcId,
|
||||
tool,
|
||||
@@ -907,6 +913,8 @@ function ProbesContent() {
|
||||
|
||||
const running = tests.filter(t => t.status === "running")
|
||||
|
||||
if (!canRead) return <p role="status">Для просмотра устройств требуется mm:servers:read.</p>
|
||||
|
||||
if (isLive && liveLoad === "loading" && catalogReadAt === null) {
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
@@ -962,6 +970,9 @@ function ProbesContent() {
|
||||
</p>
|
||||
)}
|
||||
|
||||
{!canRun && <p role="status" className="text-sm text-muted-foreground">Для запуска диагностики требуется mm:servers:write.</p>}
|
||||
{isLive && tool === "bandwidth" && !canReadGre && <p role="status" className="text-sm text-muted-foreground">Для выбора GRE требуется mm:filters:read.</p>}
|
||||
|
||||
{/* ── tool selector + config ── */}
|
||||
<OpsPanel contentClassName="pt-4 pb-4 px-4 flex flex-col gap-4">
|
||||
|
||||
@@ -1078,7 +1089,7 @@ function ProbesContent() {
|
||||
|
||||
<Button
|
||||
onClick={() => void runTest()}
|
||||
disabled={runBusy || !srcServer?.enabled || (isLive && liveLoad !== "idle") || (tool === "bandwidth" && !bwTunnels.length)}
|
||||
disabled={!canRun || (tool === "bandwidth" && isLive && !canReadGre) || runBusy || !srcServer?.enabled || (isLive && liveLoad !== "idle") || (tool === "bandwidth" && !bwTunnels.length)}
|
||||
className="h-8 shrink-0 gap-1.5 self-end"
|
||||
>
|
||||
{runBusy ? <LoaderCircleIcon className="size-3.5 animate-spin" /> : <PlayIcon className="size-3.5" />}
|
||||
|
||||
Reference in new issue
Block a user