Add public IP field and Network interface to host form
This commit is contained in:
@@ -222,6 +222,10 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
|
|||||||
fieldName: "public_ip_address",
|
fieldName: "public_ip_address",
|
||||||
dataType: "TEXT",
|
dataType: "TEXT",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: "interface",
|
||||||
|
dataType: "TEXT",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: "wg_ip_address",
|
fieldName: "wg_ip_address",
|
||||||
dataType: "TEXT",
|
dataType: "TEXT",
|
||||||
|
|||||||
+2
-1
@@ -132,6 +132,7 @@ export type BUN_SQLITE_WGUI_HOSTS = {
|
|||||||
updated_at?: number | "";
|
updated_at?: number | "";
|
||||||
user_id?: number | "";
|
user_id?: number | "";
|
||||||
public_ip_address?: string;
|
public_ip_address?: string;
|
||||||
|
interface?: string;
|
||||||
wg_ip_address?: string;
|
wg_ip_address?: string;
|
||||||
public_key?: string;
|
public_key?: string;
|
||||||
}
|
}
|
||||||
@@ -171,7 +172,7 @@ export type BUN_SQLITE_WGUI_VARIABLES = {
|
|||||||
* The time when the record was updated. (Unix Timestamp)
|
* The time when the record was updated. (Unix Timestamp)
|
||||||
*/
|
*/
|
||||||
updated_at?: number | "";
|
updated_at?: number | "";
|
||||||
key?: "main_host_wg_ip_address" | "main_host_public_ip_address" | "main_host_wg_public_key" | "main_host_wg_private_key" | "";
|
key?: "main_host_wg_ip_address" | "main_host_public_ip_address" | "main_host_wg_public_key" | "main_host_wg_private_key" | "main_host_public_interface" | "";
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ export default function HostWgIpField({
|
|||||||
WireGuard IP Address
|
WireGuard IP Address
|
||||||
</Span>
|
</Span>
|
||||||
}
|
}
|
||||||
|
title="Wireguard IP Address"
|
||||||
|
showLabel
|
||||||
componentRef={inputRef}
|
componentRef={inputRef}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,4 +19,9 @@ export const Variables = [
|
|||||||
value: "main_host_wg_private_key",
|
value: "main_host_wg_private_key",
|
||||||
description: `Private Key for the main host`,
|
description: `Private Key for the main host`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: `Main Host Public Interface`,
|
||||||
|
value: "main_host_public_interface",
|
||||||
|
description: `Network interface for the main host (e.g. eth0, wlan0)`,
|
||||||
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
import type { BUN_SQLITE_WGUI_HOSTS, BUN_SQLITE_WGUI_VARIABLES } from "@/db/types/db";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
import type { TableType, User } from "@/src/types";
|
import type { TableType, User } from "@/src/types";
|
||||||
@@ -7,6 +7,8 @@ import grabHostPublicIPAddress from "./grab-host-public-ip-address";
|
|||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
wg_ip_address?: string | null;
|
wg_ip_address?: string | null;
|
||||||
|
public_ip_address?: string | null;
|
||||||
|
interface?: string | null;
|
||||||
user: User;
|
user: User;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -20,6 +22,8 @@ type Params = {
|
|||||||
*/
|
*/
|
||||||
export default async function createWireguardHost({
|
export default async function createWireguardHost({
|
||||||
wg_ip_address,
|
wg_ip_address,
|
||||||
|
public_ip_address,
|
||||||
|
interface: iface,
|
||||||
user,
|
user,
|
||||||
}: Params): Promise<APIResponseObject> {
|
}: Params): Promise<APIResponseObject> {
|
||||||
const wg_ip = (wg_ip_address || "").trim();
|
const wg_ip = (wg_ip_address || "").trim();
|
||||||
@@ -31,7 +35,9 @@ export default async function createWireguardHost({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const public_ip_address = await grabHostPublicIPAddress();
|
const detected_public_ip = await grabHostPublicIPAddress();
|
||||||
|
const final_public_ip = public_ip_address?.trim() || detected_public_ip;
|
||||||
|
const final_interface = iface?.trim() || undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const insert_host = await BunSQLite.insert<
|
const insert_host = await BunSQLite.insert<
|
||||||
@@ -43,7 +49,8 @@ export default async function createWireguardHost({
|
|||||||
{
|
{
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
wg_ip_address: wg_ip,
|
wg_ip_address: wg_ip,
|
||||||
public_ip_address: public_ip_address || undefined,
|
public_ip_address: final_public_ip || undefined,
|
||||||
|
interface: final_interface,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -61,9 +68,26 @@ export default async function createWireguardHost({
|
|||||||
id: host_id,
|
id: host_id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
wg_ip_address: wg_ip,
|
wg_ip_address: wg_ip,
|
||||||
public_ip_address: public_ip_address || undefined,
|
public_ip_address: final_public_ip || undefined,
|
||||||
|
interface: final_interface,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (host_id === 0 && final_interface) {
|
||||||
|
await BunSQLite.insert<
|
||||||
|
BUN_SQLITE_WGUI_VARIABLES,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "variables",
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
key: "main_host_public_interface",
|
||||||
|
value: final_interface,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
update_on_duplicate: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const setup_res = await setupWireguardHost({
|
const setup_res = await setupWireguardHost({
|
||||||
host,
|
host,
|
||||||
wg_subnet_ip: wg_ip,
|
wg_subnet_ip: wg_ip,
|
||||||
@@ -93,4 +117,4 @@ export default async function createWireguardHost({
|
|||||||
msg: error.message,
|
msg: error.message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import { execSync } from "node:child_process";
|
||||||
|
import os from "node:os";
|
||||||
|
|
||||||
|
const VIRTUAL_INTERFACE_PATTERNS = [
|
||||||
|
/^wg\d+$/,
|
||||||
|
/^docker\d*$/,
|
||||||
|
/^br\d*$/,
|
||||||
|
/^veth.*/,
|
||||||
|
/^tun.*/,
|
||||||
|
/^tap.*/,
|
||||||
|
/^vlan.*/,
|
||||||
|
/^bond\d*$/,
|
||||||
|
/^macvlan.*/,
|
||||||
|
/^ipvlan.*/,
|
||||||
|
/^wgui\d+$/,
|
||||||
|
/^virbr\d*$/,
|
||||||
|
/^vboxnet\d*$/,
|
||||||
|
/^vmnet\d*$/,
|
||||||
|
];
|
||||||
|
|
||||||
|
function isVirtualInterface(name: string): boolean {
|
||||||
|
return VIRTUAL_INTERFACE_PATTERNS.some((pattern) =>
|
||||||
|
pattern.test(name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPhysicalInterface(name: string): boolean {
|
||||||
|
try {
|
||||||
|
const devicePath = `/sys/class/net/${name}/device`;
|
||||||
|
const result = execSync(`test -e ${devicePath} && echo yes || echo no`, {
|
||||||
|
encoding: "utf-8",
|
||||||
|
}).trim();
|
||||||
|
return result === "yes";
|
||||||
|
} catch {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to grab all available physical network interfaces on the machine
|
||||||
|
* @returns Array of interface names (e.g. ["enp2s0", "wlan0"])
|
||||||
|
*/
|
||||||
|
export default async function grabHostNetworkInterfaces(): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const interfaces = os.networkInterfaces();
|
||||||
|
const names: string[] = [];
|
||||||
|
|
||||||
|
for (const [name, addrs] of Object.entries(interfaces)) {
|
||||||
|
if (!addrs) continue;
|
||||||
|
if (name === "lo") continue;
|
||||||
|
if (isVirtualInterface(name)) continue;
|
||||||
|
for (const addr of addrs) {
|
||||||
|
if (addr.family === "IPv4" && !addr.internal) {
|
||||||
|
if (isPhysicalInterface(name)) {
|
||||||
|
names.push(name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (names.length > 0) {
|
||||||
|
return names.sort();
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const route = execSync(`ip -4 addr show`, { encoding: "utf-8" })
|
||||||
|
.trim()
|
||||||
|
.split(/\n/);
|
||||||
|
const names: string[] = [];
|
||||||
|
for (const line of route) {
|
||||||
|
const match = line.match(/^\d+:\s+(\S+):/);
|
||||||
|
if (match && match[1] && match[1] !== "lo") {
|
||||||
|
const iface = match[1];
|
||||||
|
if (!isVirtualInterface(iface) && isPhysicalInterface(iface)) {
|
||||||
|
names.push(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (names.length > 0) return names.sort();
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
return [`eth0`];
|
||||||
|
}
|
||||||
@@ -100,7 +100,7 @@ export default async function setupWireguardHost({
|
|||||||
rules_by_client_id.set(rule.client_id, existing_rules);
|
rules_by_client_id.set(rule.client_id, existing_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TARGET_INTERFACE = await grabHostNetworkInterface();
|
const TARGET_INTERFACE = host?.interface || await grabHostNetworkInterface();
|
||||||
const HOST_WG_IP =
|
const HOST_WG_IP =
|
||||||
host?.wg_ip_address ||
|
host?.wg_ip_address ||
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value ||
|
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value ||
|
||||||
@@ -158,21 +158,29 @@ export default async function setupWireguardHost({
|
|||||||
}).trim();
|
}).trim();
|
||||||
|
|
||||||
if (HOST_ID == 0 && !is_update_after_client_setup) {
|
if (HOST_ID == 0 && !is_update_after_client_setup) {
|
||||||
|
const variables_data: Array<{ key: string; value: string }> = [
|
||||||
|
{
|
||||||
|
key: "main_host_wg_ip_address",
|
||||||
|
value: HOST_WG_IP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "main_host_wg_public_key",
|
||||||
|
value: HOST_PUBLIC_KEY,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (host?.interface) {
|
||||||
|
variables_data.push({
|
||||||
|
key: "main_host_public_interface",
|
||||||
|
value: host.interface,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const update_variables = await BunSQLite.insert<
|
const update_variables = await BunSQLite.insert<
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
BUN_SQLITE_WGUI_VARIABLES,
|
||||||
TableType
|
TableType
|
||||||
>({
|
>({
|
||||||
table: "variables",
|
table: "variables",
|
||||||
data: [
|
data: variables_data as BUN_SQLITE_WGUI_VARIABLES[],
|
||||||
{
|
|
||||||
key: "main_host_wg_ip_address",
|
|
||||||
value: HOST_WG_IP,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "main_host_wg_public_key",
|
|
||||||
value: HOST_PUBLIC_KEY,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
update_on_duplicate: true,
|
update_on_duplicate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ export default async function syncWireguardHosts() {
|
|||||||
(v) => v.key == "main_host_public_ip_address",
|
(v) => v.key == "main_host_public_ip_address",
|
||||||
)?.value;
|
)?.value;
|
||||||
|
|
||||||
|
const main_host_interface = variables.payload?.find(
|
||||||
|
(v) => v.key == "main_host_public_interface",
|
||||||
|
)?.value;
|
||||||
|
|
||||||
if (!main_host_ip) {
|
if (!main_host_ip) {
|
||||||
throw new Error(`Main Host not set yet`);
|
throw new Error(`Main Host not set yet`);
|
||||||
}
|
}
|
||||||
@@ -52,6 +56,7 @@ export default async function syncWireguardHosts() {
|
|||||||
id: 0,
|
id: 0,
|
||||||
public_ip_address: main_host_public_ip,
|
public_ip_address: main_host_public_ip,
|
||||||
wg_ip_address: main_host_ip,
|
wg_ip_address: main_host_ip,
|
||||||
|
interface: main_host_interface,
|
||||||
},
|
},
|
||||||
...(hosts.payload || []),
|
...(hosts.payload || []),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
import type { BUN_SQLITE_WGUI_ALL_TYPEDEFS } from "@/db/types/db";
|
import type { BUN_SQLITE_WGUI_ALL_TYPEDEFS } from "@/db/types/db";
|
||||||
import useStatus from "@/src/components/twui/hooks/useStatus";
|
import useStatus from "@/src/components/twui/hooks/useStatus";
|
||||||
import { useCallback, useContext, useEffect, useState } from "react";
|
import {
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
type Dispatch,
|
||||||
|
type SetStateAction,
|
||||||
|
} from "react";
|
||||||
import { AppContext } from "../pages/__root";
|
import { AppContext } from "../pages/__root";
|
||||||
import type { ImageInputToBase64FunctionReturn } from "../components/twui/utils/form/imageInputToBase64";
|
import type { ImageInputToBase64FunctionReturn } from "../components/twui/utils/form/imageInputToBase64";
|
||||||
import EJSON from "../utils/ejson";
|
import EJSON from "../utils/ejson";
|
||||||
@@ -32,6 +39,14 @@ type Params<T extends {} = BUN_SQLITE_WGUI_ALL_TYPEDEFS> = {
|
|||||||
* Is this the first user?
|
* Is this the first user?
|
||||||
*/
|
*/
|
||||||
is_first_user?: boolean;
|
is_first_user?: boolean;
|
||||||
|
/**
|
||||||
|
* Function to run before the `setReady`
|
||||||
|
* dispatch is fired
|
||||||
|
*/
|
||||||
|
before_ready_function?: (params: {
|
||||||
|
form: T;
|
||||||
|
setForm: Dispatch<SetStateAction<T>>;
|
||||||
|
}) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function useFormInit<
|
export default function useFormInit<
|
||||||
@@ -94,7 +109,22 @@ export default function useFormInit<
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
} finally {
|
} finally {
|
||||||
setReady(true);
|
if (params?.before_ready_function) {
|
||||||
|
params
|
||||||
|
.before_ready_function({ form, setForm })
|
||||||
|
.then(() => {})
|
||||||
|
.catch((e2) => {
|
||||||
|
console.log(
|
||||||
|
`Before ready function error:`,
|
||||||
|
e2.message,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setReady(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setReady(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export default async function submitAddHostForm({
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
body: {
|
body: {
|
||||||
wg_ip_address: form.wg_ip_address || "",
|
wg_ip_address: form.wg_ip_address || "",
|
||||||
|
public_ip_address: form.public_ip_address || "",
|
||||||
|
interface: form.interface || "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import Select from "@/src/components/twui/form/Select";
|
||||||
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
|
import useFormInit from "@/src/hooks/use-form-init";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
|
||||||
|
|
||||||
|
export default function AddHostFormInterface({ form, setForm }: Props) {
|
||||||
|
const [interfaces, setInterfaces] = useState<string[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchApi<ApiReqParams, APIResponseObject>(
|
||||||
|
"/api/admin/network-interfaces",
|
||||||
|
{ method: "GET" },
|
||||||
|
).then((res) => {
|
||||||
|
if (res.success && res.stringRes) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(res.stringRes) as string[];
|
||||||
|
setInterfaces(parsed);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack className="w-full gap-2 items-stretch">
|
||||||
|
<Select
|
||||||
|
name="interface"
|
||||||
|
label="Network Interface"
|
||||||
|
showLabel
|
||||||
|
options={interfaces.map((iface) => ({
|
||||||
|
value: iface,
|
||||||
|
title: iface,
|
||||||
|
default: iface === form.interface,
|
||||||
|
}))}
|
||||||
|
changeHandler={(v) => {
|
||||||
|
setForm((prev) => ({
|
||||||
|
...prev,
|
||||||
|
interface: v,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import Input from "@/src/components/twui/form/Input";
|
||||||
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
|
import useFormInit from "@/src/hooks/use-form-init";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
|
||||||
|
|
||||||
|
export default function AddHostFormPublicIP({ form, setForm }: Props) {
|
||||||
|
useEffect(() => {
|
||||||
|
fetchApi<ApiReqParams, APIResponseObject>(
|
||||||
|
"/api/admin/public-ip",
|
||||||
|
{ method: "GET" },
|
||||||
|
).then((res) => {
|
||||||
|
if (res.success && res.stringRes) {
|
||||||
|
setForm((prev) => ({
|
||||||
|
...prev,
|
||||||
|
public_ip_address: res.stringRes!,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack className="w-full gap-2">
|
||||||
|
<Input
|
||||||
|
name="public_ip_address"
|
||||||
|
label="Public IP Address"
|
||||||
|
showLabel
|
||||||
|
placeholder="e.g. 203.0.113.10"
|
||||||
|
value={form.public_ip_address || ""}
|
||||||
|
changeHandler={(v) => {
|
||||||
|
setForm((prev) => ({
|
||||||
|
...prev,
|
||||||
|
public_ip_address: v,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ import submitAddHostForm from "../../(functions)/submit-add-host-form";
|
|||||||
import AddHostFormAction from "./add-host-form-action";
|
import AddHostFormAction from "./add-host-form-action";
|
||||||
import AddHostFormSubnet from "./add-host-form-subnet";
|
import AddHostFormSubnet from "./add-host-form-subnet";
|
||||||
import AddHostFormWgIpAddress from "./add-host-form-wg-ip-address";
|
import AddHostFormWgIpAddress from "./add-host-form-wg-ip-address";
|
||||||
|
import AddHostFormPublicIP from "./add-host-form-public-ip";
|
||||||
|
import AddHostFormInterface from "./add-host-form-interface";
|
||||||
import LoadingRectangleBlock from "@/src/components/twui/layout/LoadingRectangleBlock";
|
import LoadingRectangleBlock from "@/src/components/twui/layout/LoadingRectangleBlock";
|
||||||
import type { HostWgIpFieldStatus } from "@/src/components/general/host-wg-ip-field";
|
import type { HostWgIpFieldStatus } from "@/src/components/general/host-wg-ip-field";
|
||||||
|
|
||||||
@@ -35,8 +37,10 @@ export default function AddHostForm() {
|
|||||||
{status?.error && <Tag color="error">{status.msg}</Tag>}
|
{status?.error && <Tag color="error">{status.msg}</Tag>}
|
||||||
{loading && <LoadingOverlay />}
|
{loading && <LoadingOverlay />}
|
||||||
{init.ready ? (
|
{init.ready ? (
|
||||||
<Stack className="w-full gap-2">
|
<Stack className="w-full gap-6 items-stretch">
|
||||||
<AddHostFormSubnet />
|
{/* <AddHostFormSubnet /> */}
|
||||||
|
<AddHostFormPublicIP {...init} />
|
||||||
|
<AddHostFormInterface {...init} />
|
||||||
<AddHostFormWgIpAddress
|
<AddHostFormWgIpAddress
|
||||||
{...init}
|
{...init}
|
||||||
setIpStatus={setIpStatus}
|
setIpStatus={setIpStatus}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
|||||||
|
|
||||||
return await createWireguardHost({
|
return await createWireguardHost({
|
||||||
wg_ip_address: body?.wg_ip_address,
|
wg_ip_address: body?.wg_ip_address,
|
||||||
|
public_ip_address: body?.public_ip_address,
|
||||||
|
interface: body?.interface,
|
||||||
user,
|
user,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import grabHostNetworkInterfaces from "@/src/functions/backend/setup/grab-host-network-interfaces";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type {
|
||||||
|
APIResponseObject,
|
||||||
|
BunextAPIRouteHandler,
|
||||||
|
} from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
||||||
|
params,
|
||||||
|
) => {
|
||||||
|
if (params.req.method !== "GET") {
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const interfaces = await grabHostNetworkInterfaces();
|
||||||
|
return { success: true, stringRes: JSON.stringify(interfaces) };
|
||||||
|
} catch (error: any) {
|
||||||
|
return { success: false, msg: error.message };
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import grabHostPublicIPAddress from "@/src/functions/backend/setup/grab-host-public-ip-address";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type {
|
||||||
|
APIResponseObject,
|
||||||
|
BunextAPIRouteHandler,
|
||||||
|
} from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
||||||
|
params,
|
||||||
|
) => {
|
||||||
|
if (params.req.method !== "GET") {
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const public_ip = await grabHostPublicIPAddress();
|
||||||
|
return { success: true, stringRes: public_ip };
|
||||||
|
} catch (error: any) {
|
||||||
|
return { success: false, msg: error.message };
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -222,6 +222,7 @@ export type ApiReqParams<
|
|||||||
host_id?: string | number | null;
|
host_id?: string | number | null;
|
||||||
client_id?: string | number | null;
|
client_id?: string | number | null;
|
||||||
public_ip_address?: string | null;
|
public_ip_address?: string | null;
|
||||||
|
interface?: string | null;
|
||||||
// client_rules?: BUN_SQLITE_WGUI_CLIENT_RULES[];
|
// client_rules?: BUN_SQLITE_WGUI_CLIENT_RULES[];
|
||||||
|
|
||||||
media_base_64?: string;
|
media_base_64?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user