Files
MikrotikManager/backend/src/services/recursive-route-validation.ts
T

28 lines
1.6 KiB
TypeScript

import { z } from "zod"
import { isIP } from "node:net"
const destination = z.string().trim().refine(value => {
const [address, prefix, extra] = value.split("/")
return extra === undefined && isIP(address ?? "") === 4 && (prefix === undefined || /^\d+$/.test(prefix) && Number(prefix) <= 32)
}, "Нужен IPv4 адрес или префикс")
const gateway = z.string().trim().refine(value => {
const [address, iface, extra] = value.split("%")
return extra === undefined && isIP(address ?? "") === 4 && (iface === undefined || Boolean(iface) && !/\s/.test(iface))
}, "Нужен IPv4 шлюз с необязательным интерфейсом")
const serverId = z.union([z.number().int().positive(), z.string().trim().regex(/^\d+$/)])
.transform(Number).refine(value => Number.isSafeInteger(value) && value > 0)
export const recursiveTargetSchema = z.object({ serverId })
export const recursiveInputRowSchema = z.object({
id: z.string().optional().default(""),
dstAddress: destination, gateway,
distance: z.number().int().min(0).max(255),
scope: z.number().int().min(0).max(255).nullable(),
targetScope: z.number().int().min(0).max(255).nullable(),
routingTable: z.string().trim().min(1), checkGateway: z.enum(["none", "arp", "ping", "bfd"]),
country: z.string(), comment: z.string(), disabled: z.boolean(),
})
export const recursiveInputRowsSchema = z.array(recursiveInputRowSchema)
.refine(rows => { const ids = rows.map(row => row.id).filter(Boolean); return new Set(ids).size === ids.length })
export const recursiveApplyBodySchema = recursiveTargetSchema.extend({
routes: recursiveInputRowsSchema, source: z.enum(["apply", "copy"]).optional(),
})