mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-12 14:21:01 +00:00
a329882e0e
Land the WireGuard client-config UX work on main (the upstream PR #5642 branch could not be pushed to). - Reusable collapsible ConfigBlock (copy/download/QR, actions aligned right) for the client .conf, used by client info and the public sub page. - Correct .conf: canonical PresharedKey casing and DNS sourced from the inbound (configurable per-inbound, default 1.1.1.1, 1.0.0.1). - Configurable per-inbound DNS for WireGuard (schema + form + backend hint via InboundOption.WgDns); inert at the Xray layer. - Public sub page now shows the WireGuard config, rebuilt from the share link; the Go wireguard:// link carries dns/presharedkey/keepalive for completeness. - QR enabled for the wireguard:// link; link rows are compact like other protocols. - Client information order is subscription, copy URL, WireGuard config; the redundant config tab is removed from the add/edit client modal. - Drop the Inbound Information and QR Code row actions for WireGuard inbounds.
71 lines
3.1 KiB
TypeScript
71 lines
3.1 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
export const WireguardDomainStrategySchema = z.enum([
|
|
'ForceIP',
|
|
'ForceIPv4',
|
|
'ForceIPv4v6',
|
|
'ForceIPv6',
|
|
'ForceIPv6v4',
|
|
]);
|
|
export type WireguardDomainStrategy = z.infer<typeof WireguardDomainStrategySchema>;
|
|
|
|
// AntD InputNumber emits null (not undefined) when the user clears it, and
|
|
// the form store hands that null straight to safeParse on submit — a bare
|
|
// .optional() would reject it and block the save.
|
|
const optionalClearedInt = (schema: z.ZodNumber) =>
|
|
z.preprocess((v) => (v == null ? undefined : v), schema.optional());
|
|
|
|
// Wireguard inbound is peer-based (no clients). Each peer is a client device
|
|
// the server accepts; secretKey is the server-side private key and pubKey is
|
|
// derived from it at runtime (not persisted on the wire). Inbound peers
|
|
// optionally store the client's privateKey so the panel can render configs
|
|
// for the user — outbound peers never have a privateKey.
|
|
export const WireguardInboundPeerSchema = z.object({
|
|
privateKey: z.string().optional(),
|
|
publicKey: z.string().min(1),
|
|
preSharedKey: z.string().optional(),
|
|
allowedIPs: z.array(z.string()).default([]),
|
|
keepAlive: optionalClearedInt(z.number().int().min(0)),
|
|
// Panel-only annotation (#5168): which client/device this peer belongs to.
|
|
// Rides along in the settings JSON like privateKey does; xray-core ignores
|
|
// unknown peer fields.
|
|
comment: z.string().optional(),
|
|
});
|
|
export type WireguardInboundPeer = z.infer<typeof WireguardInboundPeerSchema>;
|
|
|
|
// A WireGuard inbound client (multi-client model). Each client is one peer the
|
|
// server accepts: the panel stores its keypair so it can render a full .conf/QR,
|
|
// and allowedIPs is the client's unique tunnel address (allocated server-side
|
|
// when left blank). Keys are optional on the wire — the backend generates them
|
|
// when absent.
|
|
export const WireguardClientSchema = z.object({
|
|
privateKey: z.string().optional(),
|
|
publicKey: z.string().optional(),
|
|
preSharedKey: z.string().optional(),
|
|
allowedIPs: z.array(z.string()).default([]),
|
|
keepAlive: optionalClearedInt(z.number().int().min(0)),
|
|
email: z.string().min(1),
|
|
limitIp: z.number().int().min(0).default(0),
|
|
totalGB: z.number().int().min(0).default(0),
|
|
expiryTime: z.number().int().default(0),
|
|
enable: z.boolean().default(true),
|
|
tgId: z.union([z.number(), z.string()]).transform((v) => Number(v) || 0).default(0),
|
|
subId: z.string().default(''),
|
|
comment: z.string().default(''),
|
|
reset: z.number().int().min(0).default(0),
|
|
created_at: z.number().int().optional(),
|
|
updated_at: z.number().int().optional(),
|
|
});
|
|
export type WireguardClient = z.infer<typeof WireguardClientSchema>;
|
|
|
|
export const WireguardInboundSettingsSchema = z.object({
|
|
mtu: optionalClearedInt(z.number().int().min(1)),
|
|
secretKey: z.string().min(1),
|
|
dns: z.string().optional(),
|
|
peers: z.array(WireguardInboundPeerSchema).default([]),
|
|
clients: z.array(WireguardClientSchema).default([]),
|
|
noKernelTun: z.boolean().default(false),
|
|
domainStrategy: WireguardDomainStrategySchema.optional(),
|
|
});
|
|
export type WireguardInboundSettings = z.infer<typeof WireguardInboundSettingsSchema>;
|