fix(ui): сохранять контекст и блокировку рекурсивных маршрутов
This commit is contained in:
1 parent
52493debc2
commit
50fad3ac80
10 files changed
+223
-28
No files matched your search
@@ -241,6 +241,7 @@ export function permissionForPath(pathname: string): string | null {
|
||||
if (pathname.startsWith("/certificates")) return "mm:certificates:read"
|
||||
if (
|
||||
pathname.startsWith("/network") ||
|
||||
pathname.startsWith("/recursive-routes") ||
|
||||
pathname.startsWith("/ospf") ||
|
||||
pathname.startsWith("/route-optimizer")
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import {test} from "node:test"
|
||||
import assert from "node:assert/strict"
|
||||
import {readRecursiveUrl,patchRecursiveUrl} from "./recursive-route-url-state"
|
||||
import {permissionForPath} from "./auth"
|
||||
test("recursive context roundtrip owns only its URL fields",()=>{
|
||||
const params=new URLSearchParams("keep=x&server=2&q=ether&route=10.0.0.0%2F24&table=main")
|
||||
assert.deepEqual(readRecursiveUrl(params),{serverId:"2",q:"ether",route:"10.0.0.0/24",table:"main",error:null})
|
||||
const next=patchRecursiveUrl(params,{serverId:"1",q:null,route:null,table:null})
|
||||
assert.equal(next.get("keep"),"x");assert.equal(next.get("server"),"1");assert.equal(next.has("q"),false)
|
||||
assert.equal(permissionForPath("/recursive-routes"),"mm:network:read")
|
||||
})
|
||||
test("recursive invalid or ambiguous URL never guesses a device/group",()=>{
|
||||
for(const q of ["server=0","server=srv1","server=1&server=2","route=10.0.0.0/24","table=main","q=a&q=b","q="+"x".repeat(257)]) assert.ok(readRecursiveUrl(new URLSearchParams(q)).error,q)
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
export type RecursiveUrlState = { serverId: string | null; q: string; route: string | null; table: string | null; error: string | null }
|
||||
export type RecursiveUrlPatch = Partial<{ serverId: string | null; q: string | null; route: string | null; table: string | null }>
|
||||
export function readRecursiveUrl(params: URLSearchParams): RecursiveUrlState {
|
||||
const result: RecursiveUrlState = { serverId: null, q: "", route: null, table: null, error: null }
|
||||
for (const [key, limit] of [["server", 64], ["q", 256], ["route", 128], ["table", 256]] as const) {
|
||||
const values = params.getAll(key)
|
||||
if (values.length > 1 || values.some(value => value.length > limit)) return { ...result, error: "Некорректный контекст маршрутов в ссылке" }
|
||||
}
|
||||
const server = params.get("server"), q = params.get("q")?.trim() ?? ""
|
||||
if (server !== null && !/^[1-9]\d*$/.test(server)) return { ...result, error: "Некорректное устройство в ссылке" }
|
||||
const route = params.get("route")?.trim() ?? null, table = params.get("table")?.trim() ?? null
|
||||
if ((route !== null || table !== null) && (!route || !table)) return { ...result, error: "В ссылке маршрута нужны адрес и таблица" }
|
||||
return { serverId: server, q, route, table, error: null }
|
||||
}
|
||||
export function patchRecursiveUrl(params: URLSearchParams, patch: RecursiveUrlPatch): URLSearchParams {
|
||||
const next = new URLSearchParams(params)
|
||||
for (const [field, value] of Object.entries(patch)) {
|
||||
const key = field === "serverId" ? "server" : field
|
||||
if (value === null || value.trim() === "") next.delete(key); else next.set(key, value.trim())
|
||||
}
|
||||
return next
|
||||
}
|
||||
Reference in new issue
Block a user