183 lines
6.5 KiB
TypeScript
183 lines
6.5 KiB
TypeScript
import { z } from "zod"
|
|
|
|
/** The client's remote endpoint belongs to the exporting interface, not its peer. */
|
|
export function resolveWgClientEndpoint(clientEndpoint: string | undefined, serverHost: string | undefined, listenPort: number): string | undefined {
|
|
const value = clientEndpoint?.trim() || serverHost?.trim()
|
|
if (!value || /[\s/]/.test(value) || !Number.isInteger(listenPort) || listenPort < 1 || listenPort > 65535) return undefined
|
|
const explicit = value.match(/^(\[[^\]]+\]|[^:]+):(\d+)$/)
|
|
if (explicit) return Number(explicit[2]) >= 1 && Number(explicit[2]) <= 65535 ? value : undefined
|
|
if (value.startsWith("[")) return value.endsWith("]") ? `${value}:${listenPort}` : undefined
|
|
if (value.includes(":")) return value.split(":").length > 2 && /^[\da-f:]+$/i.test(value) ? `[${value}]:${listenPort}` : undefined
|
|
return `${value}:${listenPort}`
|
|
}
|
|
|
|
export const wgStatusSchema = z.enum(["up", "down"])
|
|
|
|
export const wgPeerDtoSchema = z.object({
|
|
id: z.string().min(1),
|
|
rosId: z.string().min(1),
|
|
publicKey: z.string(),
|
|
allowedIps: z.array(z.string()),
|
|
endpoint: z.string().optional(),
|
|
latestHandshake: z.string().optional(),
|
|
transferRx: z.number().nonnegative().optional(),
|
|
transferTx: z.number().nonnegative().optional(),
|
|
persistentKeepalive: z.number().int().nonnegative().optional(),
|
|
persistent: z.boolean().optional(),
|
|
comment: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
name: z.string().optional(),
|
|
clientAddress: z.string().optional(),
|
|
clientDns: z.string().optional(),
|
|
clientEndpoint: z.string().optional(),
|
|
})
|
|
|
|
export const wgIfaceDtoSchema = z.object({
|
|
id: z.string().min(1),
|
|
rosId: z.string().min(1),
|
|
name: z.string().min(1),
|
|
serverId: z.string().min(1),
|
|
serverName: z.string(),
|
|
serverCountry: z.string().optional(),
|
|
listenPort: z.number().int().positive(),
|
|
mtu: z.number().int().positive(),
|
|
publicKey: z.string().optional(),
|
|
privateKey: z.string().optional(),
|
|
address: z.string().optional(),
|
|
peers: z.array(wgPeerDtoSchema),
|
|
comment: z.string(),
|
|
enabled: z.boolean(),
|
|
status: wgStatusSchema,
|
|
})
|
|
|
|
export const wgListResponseSchema = z.object({
|
|
interfaces: z.array(wgIfaceDtoSchema),
|
|
failures: z
|
|
.array(
|
|
z.object({
|
|
serverId: z.string(),
|
|
serverName: z.string().optional(),
|
|
error: z.string(),
|
|
}),
|
|
)
|
|
.optional(),
|
|
})
|
|
|
|
export const wgCreatePeerSchema = z.object({
|
|
publicKey: z.string().min(1),
|
|
allowedAddresses: z.array(z.string().min(1)).min(1),
|
|
endpointAddress: z.string().optional(),
|
|
endpointPort: z.number().int().positive().optional(),
|
|
persistentKeepalive: z.number().int().nonnegative().optional(),
|
|
comment: z.string().optional(),
|
|
name: z.string().optional(),
|
|
privateKey: z.enum(["auto", "none"]).or(z.string().min(1)).optional(),
|
|
clientAddress: z.string().optional(),
|
|
clientDns: z.string().optional(),
|
|
clientEndpoint: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
})
|
|
|
|
export const wgCreateInterfaceSchema = z.object({
|
|
serverId: z.union([z.string(), z.number()]),
|
|
name: z.string().min(1).max(64),
|
|
listenPort: z.number().int().positive().default(13231),
|
|
mtu: z.number().int().positive().default(1420),
|
|
comment: z.string().optional(),
|
|
privateKey: z.string().min(1).optional(),
|
|
address: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
peer: wgCreatePeerSchema.optional(),
|
|
})
|
|
|
|
export const wgPatchInterfaceSchema = z.object({
|
|
name: z.string().min(1).max(64).optional(),
|
|
listenPort: z.number().int().positive().optional(),
|
|
mtu: z.number().int().positive().optional(),
|
|
comment: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
privateKey: z.string().min(1).optional(),
|
|
})
|
|
|
|
export const wgCreatePeerRequestSchema = wgCreatePeerSchema.extend({
|
|
serverId: z.union([z.string(), z.number()]),
|
|
interfaceName: z.string().min(1),
|
|
})
|
|
|
|
export const wgPatchPeerSchema = z.object({
|
|
publicKey: z.string().min(1).optional(),
|
|
allowedAddresses: z.array(z.string().min(1)).min(1).optional(),
|
|
endpointAddress: z.string().optional(),
|
|
endpointPort: z.number().int().positive().optional(),
|
|
persistentKeepalive: z.number().int().nonnegative().optional(),
|
|
comment: z.string().optional(),
|
|
name: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
clientAddress: z.string().optional(),
|
|
clientDns: z.string().optional(),
|
|
clientEndpoint: z.string().optional(),
|
|
})
|
|
|
|
export const wgImportFormatSchema = z.enum(["auto", "rsc", "conf"])
|
|
|
|
export const wgImportRequestSchema = z.object({
|
|
serverId: z.union([z.string(), z.number()]),
|
|
content: z.string().min(1),
|
|
format: wgImportFormatSchema.optional().default("auto"),
|
|
dryRun: z.boolean().optional().default(false),
|
|
})
|
|
|
|
export const wgExportFormatSchema = z.enum(["rsc", "conf", "peer-conf"])
|
|
|
|
export const wgExportRequestSchema = z.object({
|
|
serverId: z.union([z.string(), z.number()]),
|
|
interfaceName: z.string().min(1),
|
|
format: wgExportFormatSchema,
|
|
peerId: z.string().optional(),
|
|
includePrivateKey: z.boolean().optional().default(false),
|
|
})
|
|
|
|
export const wgImportPreviewSchema = z.object({
|
|
format: z.enum(["rsc", "conf"]),
|
|
interface: z.object({
|
|
name: z.string(),
|
|
listenPort: z.number().int().positive().optional(),
|
|
mtu: z.number().int().positive().optional(),
|
|
privateKey: z.string().optional(),
|
|
comment: z.string().optional(),
|
|
address: z.string().optional(),
|
|
disabled: z.boolean().optional(),
|
|
}),
|
|
peers: z.array(wgCreatePeerSchema),
|
|
})
|
|
|
|
export const wgImportResponseSchema = z.object({
|
|
dryRun: z.boolean(),
|
|
preview: wgImportPreviewSchema,
|
|
applied: z
|
|
.object({
|
|
interfaceName: z.string(),
|
|
peersCreated: z.number().int().nonnegative(),
|
|
})
|
|
.optional(),
|
|
})
|
|
|
|
export const wgExportResponseSchema = z.object({
|
|
format: wgExportFormatSchema,
|
|
filename: z.string(),
|
|
content: z.string(),
|
|
})
|
|
|
|
export type WgPeerDto = z.infer<typeof wgPeerDtoSchema>
|
|
export type WgIfaceDto = z.infer<typeof wgIfaceDtoSchema>
|
|
export type WgListResponse = z.infer<typeof wgListResponseSchema>
|
|
export type WgCreateInterface = z.infer<typeof wgCreateInterfaceSchema>
|
|
export type WgPatchInterface = z.infer<typeof wgPatchInterfaceSchema>
|
|
export type WgCreatePeerRequest = z.infer<typeof wgCreatePeerRequestSchema>
|
|
export type WgPatchPeer = z.infer<typeof wgPatchPeerSchema>
|
|
export type WgImportRequest = z.infer<typeof wgImportRequestSchema>
|
|
export type WgExportRequest = z.infer<typeof wgExportRequestSchema>
|
|
export type WgImportPreview = z.infer<typeof wgImportPreviewSchema>
|
|
export type WgImportResponse = z.infer<typeof wgImportResponseSchema>
|
|
export type WgExportResponse = z.infer<typeof wgExportResponseSchema>
|