Refactor main host setup
This commit is contained in:
+1
-1
@@ -175,7 +175,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" | "main_host_public_interface" | "";
|
key?: "test_var" | "";
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,4 +29,4 @@ docker run --name bunext-mariadb -d \
|
|||||||
-v server-data:/data \
|
-v server-data:/data \
|
||||||
--restart unless-stopped \
|
--restart unless-stopped \
|
||||||
bunext-mariadb:latest
|
bunext-mariadb:latest
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Trash2 } from "lucide-react";
|
||||||
|
import Button from "@/src/components/twui/layout/Button";
|
||||||
|
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
export default function DeleteHostButton({ host_id }: { host_id: number }) {
|
||||||
|
const [deleting, setDeleting] = useState(false);
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
if (
|
||||||
|
!window.confirm(
|
||||||
|
`Delete host #${host_id}? All clients and their configurations will be removed.`,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDeleting(true);
|
||||||
|
|
||||||
|
const res = await fetchApi<ApiReqParams, APIResponseObject>(
|
||||||
|
`/api/admin/delete-host`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
body: { host_id },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.success) {
|
||||||
|
setDeleting(false);
|
||||||
|
window.alert(res.msg || "Could not delete the host");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.pathname = "/admin/hosts";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
title="Delete Host"
|
||||||
|
size="small"
|
||||||
|
variant="ghost"
|
||||||
|
color="error"
|
||||||
|
beforeIcon={<Trash2 size={14} />}
|
||||||
|
disabled={deleting}
|
||||||
|
onClick={handleDelete}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ export const AppData = {
|
|||||||
ImageThumbnailQuality: 70,
|
ImageThumbnailQuality: 70,
|
||||||
PaystackEndpoint: "https://api.paystack.co",
|
PaystackEndpoint: "https://api.paystack.co",
|
||||||
|
|
||||||
WireguardHostID: 0,
|
WireguardMainHostID: 0,
|
||||||
DefaultPrivateIP: `10.1.0.1`,
|
DefaultPrivateIP: `10.1.0.1`,
|
||||||
DefaultWGListenPort: 51820,
|
DefaultWGListenPort: 51820,
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
+28
-23
@@ -1,27 +1,32 @@
|
|||||||
export const Variables = [
|
export const Variables = [
|
||||||
{
|
{
|
||||||
title: `Main Host Wireguard IP Address`,
|
title: `Test Variable`,
|
||||||
value: "main_host_wg_ip_address",
|
value: "test_var",
|
||||||
description: `Private IP address to use for the main Wireguard host. Eg. 10.1.0.1`,
|
description: `Just a test variable to define the schema`,
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `Main Host Public IP Address`,
|
|
||||||
value: "main_host_public_ip_address",
|
|
||||||
description: `Private IP address to use for the main Public host. Eg. 10.1.0.1`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `Main Host Wireguard Public Key`,
|
|
||||||
value: "main_host_wg_public_key",
|
|
||||||
description: `Public Key for the main host`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `Main Host Wireguard Private Key`,
|
|
||||||
value: "main_host_wg_private_key",
|
|
||||||
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)`,
|
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// title: `Main Host Wireguard IP Address`,
|
||||||
|
// value: "main_host_wg_ip_address",
|
||||||
|
// description: `Private IP address to use for the main Wireguard host. Eg. 10.1.0.1`,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: `Main Host Public IP Address`,
|
||||||
|
// value: "main_host_public_ip_address",
|
||||||
|
// description: `Private IP address to use for the main Public host. Eg. 10.1.0.1`,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: `Main Host Wireguard Public Key`,
|
||||||
|
// value: "main_host_wg_public_key",
|
||||||
|
// description: `Public Key for the main host`,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: `Main Host Wireguard Private Key`,
|
||||||
|
// value: "main_host_wg_private_key",
|
||||||
|
// 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;
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ function acceptLines({
|
|||||||
const port_chunks = ports[0] ? chunkPorts({ ports }) : [[]];
|
const port_chunks = ports[0] ? chunkPorts({ ports }) : [[]];
|
||||||
|
|
||||||
for (let p = 0; p < protocols.length; p++) {
|
for (let p = 0; p < protocols.length; p++) {
|
||||||
const proto = protocols[p];
|
const proto = protocols[p];
|
||||||
|
|
||||||
for (let c = 0; c < port_chunks.length; c++) {
|
for (let c = 0; c < port_chunks.length; c++) {
|
||||||
const chunk = port_chunks[c] || [];
|
const chunk = port_chunks[c] || [];
|
||||||
|
|
||||||
lines.push(
|
lines.push(
|
||||||
joinArgs([
|
joinArgs([
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import type {
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
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";
|
||||||
import setupWireguardHost from "./setup-wireguard-host";
|
import setupWireguardHost from "./setup-wireguard-host";
|
||||||
import grabHostPublicIPAddress from "./grab-host-public-ip-address";
|
import grabHostPublicIPAddress from "./grab-host-public-ip-address";
|
||||||
|
import { AppData } from "@/src/data/app-data";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
wg_ip_address?: string | null;
|
wg_ip_address?: string | null;
|
||||||
@@ -64,10 +62,10 @@ export default async function createWireguardHost({
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (is_main_host) {
|
if (is_main_host) {
|
||||||
insert_data.id = 0;
|
insert_data.id = AppData["WireguardMainHostID"];
|
||||||
}
|
}
|
||||||
|
|
||||||
const insert_host = await BunSQLite.insert<
|
const insert_host_res = await BunSQLite.insert<
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
TableType
|
TableType
|
||||||
>({
|
>({
|
||||||
@@ -76,15 +74,17 @@ export default async function createWireguardHost({
|
|||||||
update_on_duplicate: true,
|
update_on_duplicate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!insert_host.success || !insert_host.postInsertReturn?.insertId) {
|
const host_id = is_main_host
|
||||||
|
? AppData["WireguardMainHostID"]
|
||||||
|
: insert_host_res.postInsertReturn?.insertId;
|
||||||
|
|
||||||
|
if (typeof host_id !== "number") {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
msg: `Could not create the host record: ${insert_host.msg}`,
|
msg: `Could not create the host record: ${insert_host_res.msg}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const host_id = Number(insert_host.postInsertReturn?.insertId);
|
|
||||||
|
|
||||||
const host: BUN_SQLITE_WGUI_HOSTS = {
|
const host: BUN_SQLITE_WGUI_HOSTS = {
|
||||||
id: host_id,
|
id: host_id,
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
@@ -96,19 +96,6 @@ export default async function createWireguardHost({
|
|||||||
listen_port: listen_port != null ? listen_port : undefined,
|
listen_port: listen_port != null ? listen_port : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
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,
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import type {
|
||||||
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
|
BUN_SQLITE_WGUI_CLIENT_RULES,
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
} from "@/db/types/db";
|
||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
|
import type { TableType, User } from "@/src/types";
|
||||||
|
import manageWireguardHost from "./manage-wireguard-host";
|
||||||
|
import grabHostDirnames from "./grab-host-dir-names";
|
||||||
|
import grabClientDirnames from "./grab-client-dir-names";
|
||||||
|
import { execSync } from "node:child_process";
|
||||||
|
|
||||||
|
type Params = {
|
||||||
|
host_id: number;
|
||||||
|
user: User;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function deleteWireguardHost({
|
||||||
|
host_id,
|
||||||
|
user,
|
||||||
|
}: Params): Promise<APIResponseObject> {
|
||||||
|
try {
|
||||||
|
const host_clients_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "clients",
|
||||||
|
query: {
|
||||||
|
query: {
|
||||||
|
host_id: { value: String(host_id) },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const clients = host_clients_res.payload || [];
|
||||||
|
|
||||||
|
for (let i = 0; i < clients.length; i++) {
|
||||||
|
const client = clients[i];
|
||||||
|
if (!client?.id) continue;
|
||||||
|
|
||||||
|
await BunSQLite.delete<BUN_SQLITE_WGUI_CLIENT_RULES, TableType>({
|
||||||
|
table: "client_rules",
|
||||||
|
query: {
|
||||||
|
query: {
|
||||||
|
client_id: { value: String(client.id) },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { CLIENT_DIR } = grabClientDirnames({
|
||||||
|
client,
|
||||||
|
host_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
execSync(`rm -rf ${CLIENT_DIR}`, { encoding: "utf-8" });
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
await BunSQLite.delete<BUN_SQLITE_WGUI_CLIENTS, TableType>({
|
||||||
|
table: "clients",
|
||||||
|
targetId: client.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { HOST_CONFIG_DIR, INTERFACE_NAME } = grabHostDirnames({
|
||||||
|
host: { id: host_id },
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
manageWireguardHost({
|
||||||
|
action: "down",
|
||||||
|
host_id,
|
||||||
|
});
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
execSync(`rm -rf ${HOST_CONFIG_DIR}`, { encoding: "utf-8" });
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const del_host = await BunSQLite.sql({
|
||||||
|
sql: `DELETE FROM HOSTS WHERE id=?`,
|
||||||
|
values: [host_id],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
msg: `Host ${host_id} deleted`,
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
msg: error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ const {
|
|||||||
} = grabDirNames();
|
} = grabDirNames();
|
||||||
|
|
||||||
export default function grabHostDirnames({ host }: Params) {
|
export default function grabHostDirnames({ host }: Params) {
|
||||||
const HOST_ID = host?.id || AppData["WireguardHostID"];
|
const HOST_ID = host?.id || AppData["WireguardMainHostID"];
|
||||||
|
|
||||||
const INTERFACE_NAME = deriveWireguardInterfaceName({ host_id: HOST_ID });
|
const INTERFACE_NAME = deriveWireguardInterfaceName({ host_id: HOST_ID });
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type {
|
import type {
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
} from "@/db/types/db";
|
||||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
@@ -21,18 +20,7 @@ type Params = {
|
|||||||
export default async function grabNextAvailableClientIPAddress({
|
export default async function grabNextAvailableClientIPAddress({
|
||||||
host,
|
host,
|
||||||
}: Params): Promise<APIResponseObject> {
|
}: Params): Promise<APIResponseObject> {
|
||||||
const variables_res = await BunSQLite.select<
|
const HOST_WG_IP = host?.wg_ip_address;
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
const variables = variables_res.payload;
|
|
||||||
|
|
||||||
const HOST_WG_IP =
|
|
||||||
host?.wg_ip_address ||
|
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value;
|
|
||||||
|
|
||||||
if (!HOST_WG_IP) {
|
if (!HOST_WG_IP) {
|
||||||
return {
|
return {
|
||||||
@@ -97,6 +85,6 @@ export default async function grabNextAvailableClientIPAddress({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
msg: `${subnet}${next_last_octet}`,
|
stringRes: `${subnet}${next_last_octet}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type Params = {
|
|||||||
|
|
||||||
export default function manageWireguardHost({
|
export default function manageWireguardHost({
|
||||||
action,
|
action,
|
||||||
host_id = AppData["WireguardHostID"],
|
host_id = AppData["WireguardMainHostID"],
|
||||||
}: Params): APIResponseObject {
|
}: Params): APIResponseObject {
|
||||||
const { HOST_CONFIG_FILE, INTERFACE_NAME } = grabHostDirnames({
|
const { HOST_CONFIG_FILE, INTERFACE_NAME } = grabHostDirnames({
|
||||||
host: { id: host_id },
|
host: { id: host_id },
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type {
|
import type {
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
} from "@/db/types/db";
|
||||||
import { AppData } from "@/src/data/app-data";
|
import { AppData } from "@/src/data/app-data";
|
||||||
import grabDirNames from "@/src/utils/grab-dir-names";
|
import grabDirNames from "@/src/utils/grab-dir-names";
|
||||||
@@ -42,16 +41,20 @@ export default async function setupWireguardClient({
|
|||||||
user,
|
user,
|
||||||
skip_host_setup,
|
skip_host_setup,
|
||||||
}: Params): Promise<APIResponseObject> {
|
}: Params): Promise<APIResponseObject> {
|
||||||
const host_id = host?.id || AppData["WireguardHostID"];
|
const host_id = host?.id || AppData["WireguardMainHostID"];
|
||||||
|
|
||||||
const variables_res = await BunSQLite.select<
|
let resolved_host = host;
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
const variables = variables_res.payload;
|
if (!resolved_host) {
|
||||||
|
const host_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "hosts",
|
||||||
|
targetId: host_id,
|
||||||
|
});
|
||||||
|
resolved_host = host_res.singleRes || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
CLIENT_WG_IP,
|
CLIENT_WG_IP,
|
||||||
@@ -69,9 +72,7 @@ export default async function setupWireguardClient({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const HOST_WG_IP = host?.id
|
const HOST_WG_IP = resolved_host?.wg_ip_address;
|
||||||
? host?.wg_ip_address
|
|
||||||
: variables?.find((v) => v.key == "main_host_wg_ip_address")?.value;
|
|
||||||
|
|
||||||
if (!HOST_WG_IP) {
|
if (!HOST_WG_IP) {
|
||||||
return {
|
return {
|
||||||
@@ -98,9 +99,7 @@ export default async function setupWireguardClient({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const PUBLIC_IP_ADDRESS =
|
const PUBLIC_IP_ADDRESS =
|
||||||
host?.public_ip_address ||
|
resolved_host?.public_ip_address ||
|
||||||
variables?.find((v) => v.key == "main_host_public_ip_address")
|
|
||||||
?.value ||
|
|
||||||
(await grabHostPublicIPAddress()) ||
|
(await grabHostPublicIPAddress()) ||
|
||||||
client?.public_ip_address ||
|
client?.public_ip_address ||
|
||||||
HOST_WG_IP;
|
HOST_WG_IP;
|
||||||
@@ -130,7 +129,7 @@ export default async function setupWireguardClient({
|
|||||||
sh += `\n`;
|
sh += `\n`;
|
||||||
sh += `[Peer]\n`;
|
sh += `[Peer]\n`;
|
||||||
sh += `PublicKey = ${HOST_PUBLIC_KEY}\n`;
|
sh += `PublicKey = ${HOST_PUBLIC_KEY}\n`;
|
||||||
sh += `Endpoint = ${PUBLIC_IP_ADDRESS}:${host?.listen_port || AppData["DefaultWGListenPort"]}\n`;
|
sh += `Endpoint = ${PUBLIC_IP_ADDRESS}:${resolved_host?.listen_port || AppData["DefaultWGListenPort"]}\n`;
|
||||||
|
|
||||||
if (client?.allow_all_ips == 1) {
|
if (client?.allow_all_ips == 1) {
|
||||||
sh += `AllowedIPs = 0.0.0.0/0, ::/0\n`;
|
sh += `AllowedIPs = 0.0.0.0/0, ::/0\n`;
|
||||||
@@ -154,7 +153,7 @@ export default async function setupWireguardClient({
|
|||||||
const host_setup_res = skip_host_setup
|
const host_setup_res = skip_host_setup
|
||||||
? { success: true }
|
? { success: true }
|
||||||
: await setupWireguardHost({
|
: await setupWireguardHost({
|
||||||
host,
|
host: resolved_host,
|
||||||
user,
|
user,
|
||||||
is_update_after_client_setup: true,
|
is_update_after_client_setup: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import type {
|
|||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
BUN_SQLITE_WGUI_CLIENT_RULES,
|
BUN_SQLITE_WGUI_CLIENT_RULES,
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
} from "@/db/types/db";
|
||||||
import grabDirNames from "@/src/utils/grab-dir-names";
|
import grabDirNames from "@/src/utils/grab-dir-names";
|
||||||
import { execSync } from "node:child_process";
|
import { execSync } from "node:child_process";
|
||||||
@@ -46,15 +45,6 @@ export default async function setupWireguardHost({
|
|||||||
POST_UP_PATH,
|
POST_UP_PATH,
|
||||||
} = grabHostDirnames({ host });
|
} = grabHostDirnames({ host });
|
||||||
|
|
||||||
const variables_res = await BunSQLite.select<
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
const variables = variables_res.payload;
|
|
||||||
|
|
||||||
const host_clients_res = await BunSQLite.select<
|
const host_clients_res = await BunSQLite.select<
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
TableType
|
TableType
|
||||||
@@ -103,10 +93,7 @@ export default async function setupWireguardHost({
|
|||||||
|
|
||||||
const TARGET_INTERFACE =
|
const TARGET_INTERFACE =
|
||||||
host?.interface || (await grabHostNetworkInterface());
|
host?.interface || (await grabHostNetworkInterface());
|
||||||
const HOST_WG_IP =
|
const HOST_WG_IP = host?.wg_ip_address || wg_subnet_ip;
|
||||||
host?.wg_ip_address ||
|
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value ||
|
|
||||||
wg_subnet_ip;
|
|
||||||
|
|
||||||
if (!HOST_WG_IP) {
|
if (!HOST_WG_IP) {
|
||||||
return {
|
return {
|
||||||
@@ -159,37 +146,7 @@ export default async function setupWireguardHost({
|
|||||||
encoding: "utf-8",
|
encoding: "utf-8",
|
||||||
}).trim();
|
}).trim();
|
||||||
|
|
||||||
if (HOST_ID == 0 && !is_update_after_client_setup) {
|
if (!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<
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
data: variables_data as BUN_SQLITE_WGUI_VARIABLES[],
|
|
||||||
update_on_duplicate: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!update_variables.success) {
|
|
||||||
throw new Error(`Couldn't update host variables`);
|
|
||||||
}
|
|
||||||
} else if (HOST_ID && !is_update_after_client_setup) {
|
|
||||||
const update_host = await BunSQLite.insert<
|
const update_host = await BunSQLite.insert<
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
TableType
|
TableType
|
||||||
|
|||||||
@@ -2,12 +2,8 @@ import grabDirNames from "@/src/utils/grab-dir-names";
|
|||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import manageWireguardHost from "./manage-wireguard-host";
|
import manageWireguardHost from "./manage-wireguard-host";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type {
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import type { TableType } from "@/src/types";
|
import type { TableType } from "@/src/types";
|
||||||
import { AppData } from "@/src/data/app-data";
|
|
||||||
import bunext from "@moduletrace/bunext";
|
import bunext from "@moduletrace/bunext";
|
||||||
|
|
||||||
const HOST_CONFIG_FILE_NAME_PATTERN = /^wgui(\d+)\.conf$/;
|
const HOST_CONFIG_FILE_NAME_PATTERN = /^wgui(\d+)\.conf$/;
|
||||||
@@ -24,44 +20,22 @@ export default async function syncWireguardHosts() {
|
|||||||
HOST_CONFIG_FILE_NAME_PATTERN.test(file_name),
|
HOST_CONFIG_FILE_NAME_PATTERN.test(file_name),
|
||||||
);
|
);
|
||||||
|
|
||||||
const variables = await BunSQLite.select<
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
const hosts = await BunSQLite.select<BUN_SQLITE_WGUI_HOSTS, TableType>({
|
const hosts = await BunSQLite.select<BUN_SQLITE_WGUI_HOSTS, TableType>({
|
||||||
table: "hosts",
|
table: "hosts",
|
||||||
});
|
});
|
||||||
|
|
||||||
const main_host_ip = variables.payload?.find(
|
const main_host = hosts.payload?.find((h) => h.id === 0);
|
||||||
(v) => v.key == "main_host_wg_ip_address",
|
|
||||||
)?.value;
|
|
||||||
|
|
||||||
const main_host_public_ip = variables.payload?.find(
|
if (!main_host?.wg_ip_address) {
|
||||||
(v) => v.key == "main_host_public_ip_address",
|
|
||||||
)?.value;
|
|
||||||
|
|
||||||
const main_host_interface = variables.payload?.find(
|
|
||||||
(v) => v.key == "main_host_public_interface",
|
|
||||||
)?.value;
|
|
||||||
|
|
||||||
if (!main_host_ip) {
|
|
||||||
throw new Error(`Main Host not set yet`);
|
throw new Error(`Main Host not set yet`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const all_hosts: BUN_SQLITE_WGUI_HOSTS[] = [
|
const sorted_hosts = [
|
||||||
{
|
main_host,
|
||||||
id: 0,
|
...(hosts.payload || []).filter((h) => h.id !== 0),
|
||||||
public_ip_address: main_host_public_ip,
|
|
||||||
wg_ip_address: main_host_ip,
|
|
||||||
interface: main_host_interface,
|
|
||||||
},
|
|
||||||
...(hosts.payload || []),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const host of all_hosts) {
|
for (const host of sorted_hosts) {
|
||||||
if (typeof host.id == "number") {
|
if (typeof host.id == "number") {
|
||||||
const res = manageWireguardHost({
|
const res = manageWireguardHost({
|
||||||
action: "up",
|
action: "up",
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS, BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import { AppData } from "@/src/data/app-data";
|
|
||||||
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";
|
||||||
@@ -29,7 +24,7 @@ export default async function updateWireguardHostPublicIP({
|
|||||||
public_ip_address,
|
public_ip_address,
|
||||||
user,
|
user,
|
||||||
}: Params): Promise<APIResponseObject> {
|
}: Params): Promise<APIResponseObject> {
|
||||||
const final_host_id = Number(host_id || AppData["WireguardHostID"]);
|
const final_host_id = Number(host_id || 0);
|
||||||
const ip = (public_ip_address || "").trim();
|
const ip = (public_ip_address || "").trim();
|
||||||
|
|
||||||
if (!ip || !IP_V4_REGEX.test(ip)) {
|
if (!ip || !IP_V4_REGEX.test(ip)) {
|
||||||
@@ -42,65 +37,43 @@ export default async function updateWireguardHostPublicIP({
|
|||||||
let host: BUN_SQLITE_WGUI_HOSTS | undefined;
|
let host: BUN_SQLITE_WGUI_HOSTS | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (final_host_id == AppData["WireguardHostID"]) {
|
const host_res = await BunSQLite.select<
|
||||||
const update_variables = await BunSQLite.insert<
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
TableType
|
||||||
TableType
|
>({
|
||||||
>({
|
table: "hosts",
|
||||||
table: "variables",
|
targetId: final_host_id,
|
||||||
data: [
|
});
|
||||||
{
|
|
||||||
key: "main_host_public_ip_address",
|
|
||||||
value: ip,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
update_on_duplicate: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// console.log("update_variables", update_variables);
|
host = host_res.singleRes || undefined;
|
||||||
|
|
||||||
// if (!update_variables.success) {
|
if (!host) {
|
||||||
// throw new Error(`Couldn't update host public IP variable`);
|
return {
|
||||||
// }
|
success: false,
|
||||||
} else {
|
msg: `Host record not found`,
|
||||||
const host_res = await BunSQLite.select<
|
};
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "hosts",
|
|
||||||
targetId: final_host_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
host = host_res.singleRes || undefined;
|
|
||||||
|
|
||||||
if (!host) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
msg: `Host record not found`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const update_host = await BunSQLite.insert<
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "hosts",
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
id: host.id,
|
|
||||||
user_id: user.id,
|
|
||||||
public_ip_address: ip,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
update_on_duplicate: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!update_host.success) {
|
|
||||||
throw new Error(`Couldn't update host record`);
|
|
||||||
}
|
|
||||||
|
|
||||||
host.public_ip_address = ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const update_host = await BunSQLite.insert<
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "hosts",
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: host.id,
|
||||||
|
user_id: user.id,
|
||||||
|
public_ip_address: ip,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
update_on_duplicate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!update_host.success) {
|
||||||
|
throw new Error(`Couldn't update host record`);
|
||||||
|
}
|
||||||
|
|
||||||
|
host.public_ip_address = ip;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import type {
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import { AppData } from "@/src/data/app-data";
|
import { AppData } from "@/src/data/app-data";
|
||||||
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";
|
||||||
@@ -20,9 +17,6 @@ type Params = {
|
|||||||
/**
|
/**
|
||||||
* Update the private WireGuard subnet IP of a host
|
* Update the private WireGuard subnet IP of a host
|
||||||
* and regenerate the host config + restart the tunnel.
|
* and regenerate the host config + restart the tunnel.
|
||||||
*
|
|
||||||
* For the main host (id 0) the value is stored in the
|
|
||||||
* variables table, otherwise the hosts record is updated.
|
|
||||||
* @param param0
|
* @param param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +25,7 @@ export default async function updateWireguardHost({
|
|||||||
wg_ip_address,
|
wg_ip_address,
|
||||||
user,
|
user,
|
||||||
}: Params): Promise<APIResponseObject> {
|
}: Params): Promise<APIResponseObject> {
|
||||||
const final_host_id = Number(host_id || AppData["WireguardHostID"]);
|
const final_host_id = Number(host_id || AppData["WireguardMainHostID"]);
|
||||||
const ip = (wg_ip_address || "").trim();
|
const ip = (wg_ip_address || "").trim();
|
||||||
|
|
||||||
if (!ip || !IP_V4_REGEX.test(ip)) {
|
if (!ip || !IP_V4_REGEX.test(ip)) {
|
||||||
@@ -45,37 +39,24 @@ export default async function updateWireguardHost({
|
|||||||
let current_wg_ip: string | undefined;
|
let current_wg_ip: string | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (final_host_id == AppData["WireguardHostID"]) {
|
const host_res = await BunSQLite.select<
|
||||||
const variables_res = await BunSQLite.select<
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
TableType
|
||||||
TableType
|
>({
|
||||||
>({
|
table: "hosts",
|
||||||
table: "variables",
|
targetId: final_host_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
current_wg_ip = variables_res.payload?.find(
|
host = host_res.singleRes || undefined;
|
||||||
(v) => v.key == "main_host_wg_ip_address",
|
|
||||||
)?.value;
|
|
||||||
} else {
|
|
||||||
const host_res = await BunSQLite.select<
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "hosts",
|
|
||||||
targetId: final_host_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
host = host_res.singleRes || undefined;
|
if (!host) {
|
||||||
|
return {
|
||||||
if (!host) {
|
success: false,
|
||||||
return {
|
msg: `Host record not found`,
|
||||||
success: false,
|
};
|
||||||
msg: `Host record not found`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
current_wg_ip = host.wg_ip_address || undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_wg_ip = host.wg_ip_address || undefined;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@@ -97,53 +78,27 @@ export default async function updateWireguardHost({
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (final_host_id == AppData["WireguardHostID"]) {
|
const update_host = await BunSQLite.insert<
|
||||||
const update_variables = await BunSQLite.insert<
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
TableType
|
||||||
TableType
|
>({
|
||||||
>({
|
table: "hosts",
|
||||||
table: "variables",
|
data: [
|
||||||
data: [
|
{
|
||||||
{
|
id: host?.id,
|
||||||
key: "main_host_wg_ip_address",
|
user_id: user.id,
|
||||||
value: ip,
|
wg_ip_address: ip,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
update_on_duplicate: true,
|
update_on_duplicate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!update_variables.success) {
|
if (!update_host.success) {
|
||||||
throw new Error(`Couldn't update host variables`);
|
throw new Error(`Couldn't update host record`);
|
||||||
}
|
}
|
||||||
|
|
||||||
host = {
|
if (host) {
|
||||||
id: AppData["WireguardHostID"],
|
host.wg_ip_address = ip;
|
||||||
user_id: user.id,
|
|
||||||
wg_ip_address: ip,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const update_host = await BunSQLite.insert<
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "hosts",
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
id: host?.id,
|
|
||||||
user_id: user.id,
|
|
||||||
wg_ip_address: ip,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
update_on_duplicate: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!update_host.success) {
|
|
||||||
throw new Error(`Couldn't update host record`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host) {
|
|
||||||
host.wg_ip_address = ip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
@@ -178,4 +133,4 @@ export default async function updateWireguardHost({
|
|||||||
success: true,
|
success: true,
|
||||||
msg: `Host IP updated to ${ip}`,
|
msg: `Host IP updated to ${ip}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
import type { BUN_SQLITE_WGUI_VARIABLES } from "@/db/types/db";
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
variables?: BUN_SQLITE_WGUI_VARIABLES[];
|
host?: BUN_SQLITE_WGUI_HOSTS;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function checkIfMainHostIsSet({ variables }: Params) {
|
export default function checkIfMainHostIsSet({ host }: Params) {
|
||||||
const is_main_host_set =
|
return Boolean(host?.wg_ip_address);
|
||||||
Boolean(
|
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value,
|
|
||||||
) &&
|
|
||||||
Boolean(
|
|
||||||
variables?.find((v) => v.key == "main_host_wg_public_key")?.value,
|
|
||||||
);
|
|
||||||
|
|
||||||
return is_main_host_set;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
import type { PagePropsType } from "../types";
|
import type { PagePropsType, TableType } from "../types";
|
||||||
import userAuth from "../functions/backend/auth/user-auth";
|
import userAuth from "../functions/backend/auth/user-auth";
|
||||||
import grabHostDirnames from "../functions/backend/setup/grab-host-dir-names";
|
import grabHostDirnames from "../functions/backend/setup/grab-host-dir-names";
|
||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import { AppData } from "../data/app-data";
|
||||||
|
|
||||||
const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
||||||
const { user, user_types } = await userAuth({ req });
|
const { user, user_types } = await userAuth({ req });
|
||||||
@@ -30,6 +33,16 @@ const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
|||||||
|
|
||||||
const main_host_dir_names = grabHostDirnames({});
|
const main_host_dir_names = grabHostDirnames({});
|
||||||
|
|
||||||
|
const main_host_record_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "hosts",
|
||||||
|
targetId: AppData["WireguardMainHostID"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const main_host_record = main_host_record_res.singleRes || null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
environment: process.env.NODE_ENV,
|
environment: process.env.NODE_ENV,
|
||||||
@@ -40,6 +53,7 @@ const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
|||||||
user,
|
user,
|
||||||
user_types,
|
user_types,
|
||||||
main_host_dir_names,
|
main_host_dir_names,
|
||||||
|
main_host: main_host_record,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
import { useAdminCrudGet } from "@/src/hooks/use-admin-crud-get";
|
import { useAdminCrudGet } from "@/src/hooks/use-admin-crud-get";
|
||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS, BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
|
|
||||||
export default function useDashboardData() {
|
export default function useDashboardData() {
|
||||||
const clients_res = useAdminCrudGet<BUN_SQLITE_WGUI_CLIENTS>({
|
const clients_res = useAdminCrudGet<BUN_SQLITE_WGUI_CLIENTS>({
|
||||||
@@ -19,13 +15,8 @@ export default function useDashboardData() {
|
|||||||
limit: 100,
|
limit: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
const variables_res = useAdminCrudGet<BUN_SQLITE_WGUI_VARIABLES>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
clients: clients_res.res,
|
clients: clients_res.res,
|
||||||
hosts: hosts_res.res,
|
hosts: hosts_res.res,
|
||||||
variables: variables_res.res,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2,20 +2,15 @@ import StatCard from "../(partials)/stat-card";
|
|||||||
import type {
|
import type {
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
} from "@/db/types/db";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
||||||
hosts?: BUN_SQLITE_WGUI_HOSTS[];
|
hosts?: BUN_SQLITE_WGUI_HOSTS[];
|
||||||
variables?: BUN_SQLITE_WGUI_VARIABLES[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function KpiSecondarySection({
|
export default function KpiSecondarySection({ clients, hosts }: Props) {
|
||||||
clients,
|
const main_host = hosts?.find((h) => h.id === 0);
|
||||||
hosts,
|
|
||||||
variables,
|
|
||||||
}: Props) {
|
|
||||||
const kpis = [
|
const kpis = [
|
||||||
{
|
{
|
||||||
key: "k-clients",
|
key: "k-clients",
|
||||||
@@ -25,14 +20,12 @@ export default function KpiSecondarySection({
|
|||||||
{
|
{
|
||||||
key: "k-hosts",
|
key: "k-hosts",
|
||||||
label: "Total hosts",
|
label: "Total hosts",
|
||||||
value: String(hosts?.length || 1),
|
value: String(hosts?.length),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "k-host-address",
|
key: "k-host-address",
|
||||||
label: "Main host address",
|
label: "Main host address",
|
||||||
value:
|
value: main_host?.wg_ip_address || "—",
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")
|
|
||||||
?.value || "—",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import { AppData } from "@/src/data/app-data";
|
||||||
|
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
||||||
|
const main_host_record_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "hosts",
|
||||||
|
targetId: AppData["WireguardMainHostID"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const main_host_record = main_host_record_res.singleRes || null;
|
||||||
|
|
||||||
|
if (!main_host_record?.name) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: `/admin/hosts/add`,
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default server;
|
||||||
@@ -1,27 +1,18 @@
|
|||||||
import { AppData } from "@/src/data/app-data";
|
import { AppData } from "@/src/data/app-data";
|
||||||
import deriveWireguardInterfaceName from "@/src/utils/derive-wireguard-interface-name";
|
import deriveWireguardInterfaceName from "@/src/utils/derive-wireguard-interface-name";
|
||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
||||||
variables?: BUN_SQLITE_WGUI_VARIABLES[];
|
|
||||||
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function deriveHostConfig({ host, variables, clients }: Params) {
|
export default function deriveHostConfig({ host, clients }: Params) {
|
||||||
const host_id = host?.id || AppData["WireguardHostID"];
|
const host_id = host?.id || AppData["WireguardMainHostID"];
|
||||||
|
|
||||||
const wg_ip_address =
|
const wg_ip_address = host?.wg_ip_address;
|
||||||
host?.wg_ip_address ||
|
const public_key = host?.public_key;
|
||||||
variables?.find((v) => v.key == "main_host_wg_ip_address")?.value;
|
|
||||||
|
|
||||||
const public_key =
|
|
||||||
host?.public_key ||
|
|
||||||
variables?.find((v) => v.key == "main_host_wg_public_key")?.value;
|
|
||||||
|
|
||||||
const interface_name = deriveWireguardInterfaceName({ host_id });
|
const interface_name = deriveWireguardInterfaceName({ host_id });
|
||||||
|
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ import { useAdminCrudGet } from "@/src/hooks/use-admin-crud-get";
|
|||||||
import type {
|
import type {
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
} from "@/db/types/db";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "@/src/pages/__root";
|
||||||
|
|
||||||
export default function useHostData() {
|
export default function useHostData() {
|
||||||
|
const { pageProps } = useContext(AppContext);
|
||||||
|
|
||||||
const hosts_res = useAdminCrudGet<BUN_SQLITE_WGUI_HOSTS>({
|
const hosts_res = useAdminCrudGet<BUN_SQLITE_WGUI_HOSTS>({
|
||||||
table: "hosts",
|
table: "hosts",
|
||||||
limit: 100,
|
limit: 100,
|
||||||
});
|
initial_res: pageProps?.hosts || undefined,
|
||||||
|
|
||||||
const variables_res = useAdminCrudGet<BUN_SQLITE_WGUI_VARIABLES>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const clients_res = useAdminCrudGet<BUN_SQLITE_WGUI_CLIENTS>({
|
const clients_res = useAdminCrudGet<BUN_SQLITE_WGUI_CLIENTS>({
|
||||||
table: "clients",
|
table: "clients",
|
||||||
limit: 100,
|
limit: 100,
|
||||||
|
initial_res: pageProps?.clients || undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hosts: hosts_res.res,
|
hosts: hosts_res.res,
|
||||||
variables: variables_res.res,
|
|
||||||
clients: clients_res.res,
|
clients: clients_res.res,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-18
@@ -1,28 +1,32 @@
|
|||||||
import { Server } from "lucide-react";
|
import { GlobeCheck, Server } from "lucide-react";
|
||||||
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
|
||||||
import AdminCard from "@/src/components/general/admin-card";
|
import AdminCard from "@/src/components/general/admin-card";
|
||||||
|
import DeleteHostButton from "@/src/components/general/delete-host-button";
|
||||||
import Button from "@/src/components/twui/layout/Button";
|
import Button from "@/src/components/twui/layout/Button";
|
||||||
import Row from "@/src/components/twui/layout/Row";
|
import Row from "@/src/components/twui/layout/Row";
|
||||||
import Span from "@/src/components/twui/layout/Span";
|
import Span from "@/src/components/twui/layout/Span";
|
||||||
import Stack from "@/src/components/twui/layout/Stack";
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
import Tag from "@/src/components/twui/elements/Tag";
|
import Tag from "@/src/components/twui/elements/Tag";
|
||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import { AppData } from "@/src/data/app-data";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
host: BUN_SQLITE_WGUI_HOSTS;
|
host: BUN_SQLITE_WGUI_HOSTS;
|
||||||
client_count?: number;
|
client_count?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function OtherHostCard({ host, client_count }: Props) {
|
export default function HostCard({ host, client_count }: Props) {
|
||||||
const host_id = host.id || 0;
|
const host_id = host.id || 0;
|
||||||
|
|
||||||
|
const title = host_id == 0 ? "Main Host" : ` Host #${host_id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminCard className="w-full p-5 flex flex-col gap-4">
|
<AdminCard className="w-full p-5 flex flex-col gap-4">
|
||||||
<Row className="justify-between items-center gap-3 flex-wrap">
|
<Row className="justify-between items-center gap-3 flex-wrap">
|
||||||
<Stack className="gap-0.5">
|
<Stack className="gap-2">
|
||||||
<Row className="gap-2 items-center">
|
<Row className="gap-2 items-center">
|
||||||
<Server size={15} className="opacity-50" />
|
<GlobeCheck size={15} className="opacity-50" />
|
||||||
<Span className="text-[14px] font-semibold leading-none">
|
<Span className="text-[14px] font-semibold leading-none">
|
||||||
Host #{host_id}
|
{title}
|
||||||
</Span>
|
</Span>
|
||||||
</Row>
|
</Row>
|
||||||
<Span className="font-mono text-[12.5px] text-foreground-light/45 dark:text-foreground-dark/45">
|
<Span className="font-mono text-[12.5px] text-foreground-light/45 dark:text-foreground-dark/45">
|
||||||
@@ -46,23 +50,31 @@ export default function OtherHostCard({ host, client_count }: Props) {
|
|||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
title="Host Clients"
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
href={`/admin/hosts/${host_id}/clients`}
|
||||||
|
>
|
||||||
|
Clients
|
||||||
|
</Button>
|
||||||
|
<DeleteHostButton host_id={host_id} />
|
||||||
</Row>
|
</Row>
|
||||||
</Row>
|
</Row>
|
||||||
<Row className="gap-2 items-center flex-wrap">
|
<Row className="gap-2 items-center flex-wrap">
|
||||||
<Tag variant="outlined" color="gray">
|
{host.public_ip_address ? (
|
||||||
|
<Span size="smaller">
|
||||||
|
<code className="text-xs">
|
||||||
|
{host.public_ip_address} :{" "}
|
||||||
|
{host.listen_port || AppData["DefaultWGListenPort"]}
|
||||||
|
</code>
|
||||||
|
</Span>
|
||||||
|
) : null}
|
||||||
|
<Span size="smaller">
|
||||||
{client_count || 0}{" "}
|
{client_count || 0}{" "}
|
||||||
{client_count == 1 ? "client" : "clients"}
|
{client_count == 1 ? "client" : "clients"}
|
||||||
</Tag>
|
</Span>
|
||||||
{host.public_ip_address ? (
|
|
||||||
<Tag
|
|
||||||
variant="outlined"
|
|
||||||
color="success"
|
|
||||||
className="outline-success/50 bg-success/5!"
|
|
||||||
>
|
|
||||||
{host.public_ip_address}
|
|
||||||
</Tag>
|
|
||||||
) : null}
|
|
||||||
</Row>
|
</Row>
|
||||||
</AdminCard>
|
</AdminCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -8,11 +8,7 @@ import Row from "@/src/components/twui/layout/Row";
|
|||||||
import Span from "@/src/components/twui/layout/Span";
|
import Span from "@/src/components/twui/layout/Span";
|
||||||
import Stack from "@/src/components/twui/layout/Stack";
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
import deriveHostConfig from "../(functions)/derive-host-config";
|
import deriveHostConfig from "../(functions)/derive-host-config";
|
||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import Divider from "@/src/components/twui/layout/Divider";
|
import Divider from "@/src/components/twui/layout/Divider";
|
||||||
import H3 from "@/src/components/twui/layout/H3";
|
import H3 from "@/src/components/twui/layout/H3";
|
||||||
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
||||||
@@ -21,13 +17,11 @@ import { AppContext } from "@/src/pages/__root";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
||||||
variables?: BUN_SQLITE_WGUI_VARIABLES[];
|
|
||||||
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function InterfaceConfigSection({
|
export default function InterfaceConfigSection({
|
||||||
host,
|
host,
|
||||||
variables,
|
|
||||||
clients,
|
clients,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { pageProps } = useContext(AppContext);
|
const { pageProps } = useContext(AppContext);
|
||||||
@@ -38,7 +32,7 @@ export default function InterfaceConfigSection({
|
|||||||
dir_names: pageProps?.main_host_dir_names || undefined,
|
dir_names: pageProps?.main_host_dir_names || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = deriveHostConfig({ host: final_host, variables, clients });
|
const config = deriveHostConfig({ host: final_host, clients });
|
||||||
|
|
||||||
const rows = [
|
const rows = [
|
||||||
{ keyName: "Address", value: config.address || "—" },
|
{ keyName: "Address", value: config.address || "—" },
|
||||||
|
|||||||
@@ -5,20 +5,16 @@ import Span from "@/src/components/twui/layout/Span";
|
|||||||
import Stack from "@/src/components/twui/layout/Stack";
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
import deriveHostConfig from "../(functions)/derive-host-config";
|
import deriveHostConfig from "../(functions)/derive-host-config";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
host?: BUN_SQLITE_WGUI_HOSTS_JOIN;
|
||||||
variables?: BUN_SQLITE_WGUI_VARIABLES[];
|
|
||||||
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
clients?: BUN_SQLITE_WGUI_CLIENTS[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MainHostStatusSection({ host, variables, clients }: Props) {
|
export default function MainHostStatusSection({ host, clients }: Props) {
|
||||||
const config = deriveHostConfig({ host, variables, clients });
|
const config = deriveHostConfig({ host, clients });
|
||||||
|
|
||||||
const stats = [
|
const stats = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,14 +28,12 @@ const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
|||||||
const client = client_res.singleRes || null;
|
const client = client_res.singleRes || null;
|
||||||
|
|
||||||
const host_id = Number(
|
const host_id = Number(
|
||||||
client?.host_id ||
|
client?.host_id || page_query.host_id || AppData["WireguardMainHostID"],
|
||||||
page_query.host_id ||
|
|
||||||
AppData["WireguardHostID"],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let host: BUN_SQLITE_WGUI_HOSTS | null = null;
|
let host: BUN_SQLITE_WGUI_HOSTS | null = null;
|
||||||
|
|
||||||
if (host_id && host_id != AppData["WireguardHostID"]) {
|
if (host_id && host_id != AppData["WireguardMainHostID"]) {
|
||||||
const host_res = await BunSQLite.select<
|
const host_res = await BunSQLite.select<
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
TableType
|
TableType
|
||||||
@@ -72,4 +70,4 @@ const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default server;
|
export default server;
|
||||||
|
|||||||
+3
-3
@@ -21,7 +21,7 @@ export default async function grabNextAvailableClientIp({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!res?.success || !res.msg) {
|
if (!res?.success || !res.stringRes) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
msg: res?.msg || `Couldn't grab the next available client IP`,
|
msg: res?.msg || `Couldn't grab the next available client IP`,
|
||||||
@@ -30,8 +30,8 @@ export default async function grabNextAvailableClientIp({
|
|||||||
|
|
||||||
setForm((prev) => ({
|
setForm((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
wg_ip_address: res.msg,
|
wg_ip_address: res.stringRes || "",
|
||||||
allowed_ips: `${res.msg}/24`,
|
allowed_ips: `${res.stringRes}/24`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+3
@@ -24,6 +24,7 @@ export default async function submitAddClientForm(
|
|||||||
form,
|
form,
|
||||||
existing_full,
|
existing_full,
|
||||||
app_context,
|
app_context,
|
||||||
|
clearLocalForm,
|
||||||
}: ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_CLIENTS>>,
|
}: ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_CLIENTS>>,
|
||||||
{ host_id, rules }: Params,
|
{ host_id, rules }: Params,
|
||||||
) {
|
) {
|
||||||
@@ -113,6 +114,8 @@ export default async function submitAddClientForm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
|
clearLocalForm();
|
||||||
|
|
||||||
if (existing_full?.id) {
|
if (existing_full?.id) {
|
||||||
window.location.pathname = `/admin/hosts/${final_host_id}/clients/${existing_full.id}`;
|
window.location.pathname = `/admin/hosts/${final_host_id}/clients/${existing_full.id}`;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+9
@@ -38,6 +38,15 @@ export default function AddClientForm({
|
|||||||
existing: existing_client,
|
existing: existing_client,
|
||||||
existing_full: existing_client_full,
|
existing_full: existing_client_full,
|
||||||
title: "Add Client",
|
title: "Add Client",
|
||||||
|
async before_ready_function(params) {
|
||||||
|
params.setForm((prev) => ({
|
||||||
|
...prev,
|
||||||
|
wg_ip_address:
|
||||||
|
existing_client_full?.wg_ip_address ||
|
||||||
|
params.app_context.pageProps?.next_available_client_ip ||
|
||||||
|
"",
|
||||||
|
}));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [rules, setRules] = useState<ClientRuleDraft[]>(
|
const [rules, setRules] = useState<ClientRuleDraft[]>(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import grabNextAvailableClientIPAddress from "@/src/functions/backend/setup/grab-next-available-client-ip";
|
||||||
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
@@ -11,9 +12,27 @@ const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
|||||||
TableType
|
TableType
|
||||||
>({ table: "hosts", targetId: page_query.host_id });
|
>({ table: "hosts", targetId: page_query.host_id });
|
||||||
|
|
||||||
|
const host_record = host_record_res.singleRes || null;
|
||||||
|
|
||||||
|
if (!host_record) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: `/admin/hosts`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const next_available_client_ip_res = await grabNextAvailableClientIPAddress(
|
||||||
|
{
|
||||||
|
host: host_record,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
host: host_record_res.singleRes || null,
|
host: host_record,
|
||||||
|
next_available_client_ip:
|
||||||
|
next_available_client_ip_res.stringRes || null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import type {
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import { AppData } from "@/src/data/app-data";
|
|
||||||
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
@@ -10,9 +6,7 @@ import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
|||||||
const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
||||||
const page_query = query as PageQueryObject;
|
const page_query = query as PageQueryObject;
|
||||||
|
|
||||||
const host_id = Number(
|
const host_id = Number(page_query.host_id || 0);
|
||||||
page_query.host_id || AppData["WireguardHostID"],
|
|
||||||
);
|
|
||||||
|
|
||||||
const host_res = await BunSQLite.select<
|
const host_res = await BunSQLite.select<
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
@@ -22,31 +16,7 @@ const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
|||||||
targetId: host_id,
|
targetId: host_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
let host = host_res.singleRes || null;
|
const host = host_res.singleRes || null;
|
||||||
|
|
||||||
if (!host && host_id == AppData["WireguardHostID"]) {
|
|
||||||
const variables_res = await BunSQLite.select<
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({
|
|
||||||
table: "variables",
|
|
||||||
});
|
|
||||||
|
|
||||||
const variables = variables_res.payload || [];
|
|
||||||
|
|
||||||
host = {
|
|
||||||
id: AppData["WireguardHostID"],
|
|
||||||
wg_ip_address:
|
|
||||||
variables.find((v) => v.key == "main_host_wg_ip_address")
|
|
||||||
?.value || "",
|
|
||||||
public_ip_address:
|
|
||||||
variables.find((v) => v.key == "main_host_public_ip_address")
|
|
||||||
?.value || "",
|
|
||||||
public_key:
|
|
||||||
variables.find((v) => v.key == "main_host_wg_public_key")
|
|
||||||
?.value || "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
@@ -55,4 +25,4 @@ const server: BunextPageServerFn<PagePropsType> = async ({ query }) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default server;
|
export default server;
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import type {
|
import type { BUN_SQLITE_WGUI_CLIENTS, BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
BUN_SQLITE_WGUI_CLIENTS,
|
|
||||||
BUN_SQLITE_WGUI_HOSTS,
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
} from "@/db/types/db";
|
|
||||||
import grabHostDirnames from "@/src/functions/backend/setup/grab-host-dir-names";
|
import grabHostDirnames from "@/src/functions/backend/setup/grab-host-dir-names";
|
||||||
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
||||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
@@ -43,18 +39,12 @@ const server: BunextPageServerFn<PagePropsType> = async ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const variables_res = await BunSQLite.select<
|
|
||||||
BUN_SQLITE_WGUI_VARIABLES,
|
|
||||||
TableType
|
|
||||||
>({ table: "variables" });
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
host,
|
host,
|
||||||
clients: host_clients.payload || null,
|
clients: host_clients.payload || null,
|
||||||
variables: variables_res.payload || null,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default server;
|
export default server;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { BunextPageModuleMeta } from "@moduletrace/bunext/types";
|
import type { BunextPageModuleMeta } from "@moduletrace/bunext/types";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import AdminHero from "@/src/components/general/admin-hero";
|
import AdminHero from "@/src/components/general/admin-hero";
|
||||||
|
import DeleteHostButton from "@/src/components/general/delete-host-button";
|
||||||
import { SiteData } from "@/src/data/site-data";
|
import { SiteData } from "@/src/data/site-data";
|
||||||
import Button from "@/src/components/twui/layout/Button";
|
import Button from "@/src/components/twui/layout/Button";
|
||||||
import Divider from "@/src/components/twui/layout/Divider";
|
import Divider from "@/src/components/twui/layout/Divider";
|
||||||
@@ -17,11 +18,8 @@ export default function AdminSingleHostPage() {
|
|||||||
const host_id = Number(query?.host_id || pageProps?.host?.id || 0);
|
const host_id = Number(query?.host_id || pageProps?.host?.id || 0);
|
||||||
|
|
||||||
const host = pageProps?.host || undefined;
|
const host = pageProps?.host || undefined;
|
||||||
const variables = pageProps?.variables || [];
|
|
||||||
const clients = pageProps?.clients || [];
|
const clients = pageProps?.clients || [];
|
||||||
|
|
||||||
const is_main_host = !host || host_id == 0;
|
|
||||||
|
|
||||||
if (!pageProps?.host && host_id != 0) {
|
if (!pageProps?.host && host_id != 0) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -37,13 +35,23 @@ export default function AdminSingleHostPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const title = host_id == 0 ? "Main Host" : `Host #${host_id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AdminHero
|
<AdminHero
|
||||||
title={is_main_host ? "Host" : `Host #${host_id}`}
|
title={host ? title : "Host"}
|
||||||
description="WireGuard server configuration and interface details"
|
description="WireGuard server configuration and interface details"
|
||||||
buttons={
|
buttons={
|
||||||
<>
|
<>
|
||||||
|
<Button
|
||||||
|
title="Edit Host"
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
href={`/admin/hosts/${host_id}/edit`}
|
||||||
|
>
|
||||||
|
Edit Host
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
title="View Clients"
|
title="View Clients"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -54,21 +62,13 @@ export default function AdminSingleHostPage() {
|
|||||||
View Clients
|
View Clients
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
title="Edit Host"
|
title="Add Client"
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
href={`/admin/hosts/${host_id}/clients/add-client`}
|
||||||
href={`/admin/hosts/${host_id}/edit`}
|
|
||||||
>
|
>
|
||||||
Edit Host
|
Add Client
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
title="Add New Host"
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
href="/admin/hosts/add"
|
|
||||||
>
|
|
||||||
Add New Host
|
|
||||||
</Button>
|
</Button>
|
||||||
|
<DeleteHostButton host_id={host_id} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -76,26 +76,12 @@ export default function AdminSingleHostPage() {
|
|||||||
<Divider className="mb-6" />
|
<Divider className="mb-6" />
|
||||||
|
|
||||||
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
||||||
<MainHostStatusSection
|
<MainHostStatusSection host={host} clients={clients} />
|
||||||
host={host}
|
|
||||||
variables={variables}
|
|
||||||
clients={clients}
|
|
||||||
/>
|
|
||||||
<HostPublicIpSection
|
<HostPublicIpSection
|
||||||
host_id={host_id}
|
host_id={host_id}
|
||||||
current_ip={
|
current_ip={host?.public_ip_address || ""}
|
||||||
host?.public_ip_address ||
|
|
||||||
variables.find(
|
|
||||||
(v) => v.key == "main_host_public_ip_address",
|
|
||||||
)?.value ||
|
|
||||||
""
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<InterfaceConfigSection
|
|
||||||
host={host}
|
|
||||||
variables={variables}
|
|
||||||
clients={clients}
|
|
||||||
/>
|
/>
|
||||||
|
<InterfaceConfigSection host={host} clients={clients} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -104,4 +90,4 @@ export default function AdminSingleHostPage() {
|
|||||||
export const meta: BunextPageModuleMeta = {
|
export const meta: BunextPageModuleMeta = {
|
||||||
title: `Host | ${SiteData["SiteName"]}`,
|
title: `Host | ${SiteData["SiteName"]}`,
|
||||||
description: `WireGuard host page`,
|
description: `WireGuard host page`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export default async function submitAddHostForm({
|
|||||||
setLoading,
|
setLoading,
|
||||||
setStatus,
|
setStatus,
|
||||||
form,
|
form,
|
||||||
|
app_context,
|
||||||
|
clearLocalForm,
|
||||||
}: ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>) {
|
}: ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>) {
|
||||||
try {
|
try {
|
||||||
if (!window.confirm("Create this new host?")) {
|
if (!window.confirm("Create this new host?")) {
|
||||||
@@ -26,12 +28,17 @@ export default async function submitAddHostForm({
|
|||||||
interface: form.interface || "",
|
interface: form.interface || "",
|
||||||
name: form.name || "",
|
name: form.name || "",
|
||||||
short_description: form.short_description || "",
|
short_description: form.short_description || "",
|
||||||
listen_port: form.listen_port != null ? Number(form.listen_port) : null,
|
listen_port:
|
||||||
|
form.listen_port != null
|
||||||
|
? Number(form.listen_port)
|
||||||
|
: null,
|
||||||
|
is_main_host: app_context.pageProps?.is_main_host,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.success && res.numberRes) {
|
if (res.success) {
|
||||||
|
clearLocalForm();
|
||||||
window.location.pathname = `/admin/hosts/${res.numberRes}`;
|
window.location.pathname = `/admin/hosts/${res.numberRes}`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -46,4 +53,4 @@ export default async function submitAddHostForm({
|
|||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export default function AddHostFormName({ form, setForm }: Props) {
|
|||||||
name: v,
|
name: v,
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,16 +1,31 @@
|
|||||||
|
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||||
|
import { AppData } from "@/src/data/app-data";
|
||||||
import getNextAvailableListenPort from "@/src/functions/backend/setup/get-next-available-listen-port";
|
import getNextAvailableListenPort from "@/src/functions/backend/setup/get-next-available-listen-port";
|
||||||
import grabHostNetworkInterfaces from "@/src/functions/backend/setup/grab-host-network-interfaces";
|
import grabHostNetworkInterfaces from "@/src/functions/backend/setup/grab-host-network-interfaces";
|
||||||
import type { PagePropsType } from "@/src/types";
|
import type { PagePropsType, TableType } from "@/src/types";
|
||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
const server: BunextPageServerFn<PagePropsType> = async ({ req }) => {
|
const server: BunextPageServerFn<PagePropsType> = async ({ req }) => {
|
||||||
const network_interfaces = await grabHostNetworkInterfaces();
|
const network_interfaces = await grabHostNetworkInterfaces();
|
||||||
const next_listen_port = await getNextAvailableListenPort();
|
const next_listen_port = await getNextAvailableListenPort();
|
||||||
|
|
||||||
|
const main_host_record_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "hosts",
|
||||||
|
targetId: AppData["WireguardMainHostID"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const main_host_record = main_host_record_res.singleRes || null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
network_interfaces,
|
network_interfaces,
|
||||||
next_listen_port,
|
next_listen_port,
|
||||||
|
is_main_host:
|
||||||
|
main_host_record?.id !== AppData["WireguardMainHostID"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,13 +6,30 @@ import Divider from "@/src/components/twui/layout/Divider";
|
|||||||
import Stack from "@/src/components/twui/layout/Stack";
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import AddHostFormSection from "./(sections)/add-host-form-section";
|
import AddHostFormSection from "./(sections)/add-host-form-section";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "@/src/pages/__root";
|
||||||
|
|
||||||
export default function AdminAddHostPage() {
|
export default function AdminAddHostPage() {
|
||||||
|
const { pageProps } = useContext(AppContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AdminHero
|
<AdminHero
|
||||||
title="Add New Host"
|
title={
|
||||||
description="Create a new WireGuard host with a dedicated private subnet"
|
pageProps?.is_main_host
|
||||||
|
? "Create Main Host"
|
||||||
|
: "Add New Host"
|
||||||
|
}
|
||||||
|
description={
|
||||||
|
pageProps?.is_main_host ? (
|
||||||
|
<span>
|
||||||
|
Create the main wireguard host <code>(wgui0)</code>{" "}
|
||||||
|
for this server
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
"Create a new WireGuard host with a dedicated private subnet"
|
||||||
|
)
|
||||||
|
}
|
||||||
buttons={
|
buttons={
|
||||||
<Button
|
<Button
|
||||||
title="Back to Hosts"
|
title="Back to Hosts"
|
||||||
@@ -37,4 +54,4 @@ export default function AdminAddHostPage() {
|
|||||||
export const meta: BunextPageModuleMeta = {
|
export const meta: BunextPageModuleMeta = {
|
||||||
title: `Add New Host | ${SiteData["SiteName"]}`,
|
title: `Add New Host | ${SiteData["SiteName"]}`,
|
||||||
description: `WireGuard add host page`,
|
description: `WireGuard add host page`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import type {
|
||||||
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
|
BUN_SQLITE_WGUI_HOSTS,
|
||||||
|
} from "@/db/types/db";
|
||||||
|
import type { PagePropsType, PageQueryObject, TableType } from "@/src/types";
|
||||||
|
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||||
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
const server: BunextPageServerFn<PagePropsType> = async (ctx) => {
|
||||||
|
const props = ctx.props as PagePropsType;
|
||||||
|
|
||||||
|
if (!props.main_host?.name) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: `/admin/hosts/add`,
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const hosts_res = await BunSQLite.select<BUN_SQLITE_WGUI_HOSTS, TableType>({
|
||||||
|
table: "hosts",
|
||||||
|
});
|
||||||
|
|
||||||
|
const clients_res = await BunSQLite.select<
|
||||||
|
BUN_SQLITE_WGUI_CLIENTS,
|
||||||
|
TableType
|
||||||
|
>({
|
||||||
|
table: "clients",
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
hosts: hosts_res.payload || null,
|
||||||
|
clients: clients_res.payload || null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default server;
|
||||||
@@ -3,46 +3,13 @@ import AdminHero from "@/src/components/general/admin-hero";
|
|||||||
import Stack from "@/src/components/twui/layout/Stack";
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
import { SiteData } from "@/src/data/site-data";
|
import { SiteData } from "@/src/data/site-data";
|
||||||
import useHostData from "./(hooks)/use-host-data";
|
import useHostData from "./(hooks)/use-host-data";
|
||||||
import InterfaceConfigSection from "./(sections)/interface-config-section";
|
|
||||||
import Button from "@/src/components/twui/layout/Button";
|
import Button from "@/src/components/twui/layout/Button";
|
||||||
import MainHostStatusSection from "./(sections)/main-host-status-section";
|
|
||||||
import H2 from "@/src/components/twui/layout/H2";
|
|
||||||
import Divider from "@/src/components/twui/layout/Divider";
|
import Divider from "@/src/components/twui/layout/Divider";
|
||||||
import EmptyContent from "@/src/components/twui/elements/EmptyContent";
|
import EmptyContent from "@/src/components/twui/elements/EmptyContent";
|
||||||
import Span from "@/src/components/twui/layout/Span";
|
import HostCard from "./(partials)/host-card";
|
||||||
import checkIfMainHostIsSet from "@/src/functions/check-if-main-host-is-set";
|
|
||||||
import SetupMainHostButton from "@/src/components/general/setup-main-host-button";
|
|
||||||
import Row from "@/src/components/twui/layout/Row";
|
|
||||||
import { Plus } from "lucide-react";
|
|
||||||
import HostPublicIpSection from "./(sections)/host-public-ip-section";
|
|
||||||
import OtherHostCard from "./(partials)/other-host-card";
|
|
||||||
|
|
||||||
export default function AdminHostPage() {
|
export default function AdminHostPage() {
|
||||||
const { hosts, variables, clients } = useHostData();
|
const { hosts, clients } = useHostData();
|
||||||
|
|
||||||
const other_hosts = (hosts || []).filter((host) => (host.id || 0) != 0);
|
|
||||||
|
|
||||||
const main_host_public_ip = variables?.find(
|
|
||||||
(v) => v.key == "main_host_public_ip_address",
|
|
||||||
)?.value;
|
|
||||||
|
|
||||||
const is_main_host_set = checkIfMainHostIsSet({ variables });
|
|
||||||
|
|
||||||
if (!is_main_host_set) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AdminHero
|
|
||||||
title="Hosts"
|
|
||||||
description="WireGuard server configuration and interface details"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
|
||||||
<Span variant="faded">Main Host Not Set up</Span>
|
|
||||||
<SetupMainHostButton />
|
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -51,19 +18,7 @@ export default function AdminHostPage() {
|
|||||||
description="WireGuard server configuration and interface details"
|
description="WireGuard server configuration and interface details"
|
||||||
buttons={
|
buttons={
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button title="Add New Host" href="/admin/hosts/add">
|
||||||
title="View Hosts"
|
|
||||||
variant="outlined"
|
|
||||||
href="/admin/hosts"
|
|
||||||
color="gray"
|
|
||||||
>
|
|
||||||
View Hosts
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
title="Add New Host"
|
|
||||||
variant="outlined"
|
|
||||||
href="/admin/hosts/add"
|
|
||||||
>
|
|
||||||
Add New Host
|
Add New Host
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
@@ -73,49 +28,10 @@ export default function AdminHostPage() {
|
|||||||
<Divider className="mb-6" />
|
<Divider className="mb-6" />
|
||||||
|
|
||||||
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
||||||
<Row className="w-full justify-between">
|
{hosts?.[0] ? (
|
||||||
<H2>Main Host</H2>
|
|
||||||
|
|
||||||
<Row>
|
|
||||||
<Button
|
|
||||||
title="View Clients"
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
href={`/admin/hosts/0/clients`}
|
|
||||||
>
|
|
||||||
View Clients
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
title="Add Client"
|
|
||||||
beforeIcon={<Plus />}
|
|
||||||
size="small"
|
|
||||||
href={`/admin/hosts/0/clients/add-client`}
|
|
||||||
>
|
|
||||||
Add Client
|
|
||||||
</Button>
|
|
||||||
</Row>
|
|
||||||
</Row>
|
|
||||||
<MainHostStatusSection
|
|
||||||
variables={variables}
|
|
||||||
clients={clients}
|
|
||||||
/>
|
|
||||||
<HostPublicIpSection
|
|
||||||
host_id={0}
|
|
||||||
current_ip={main_host_public_ip || ""}
|
|
||||||
/>
|
|
||||||
<InterfaceConfigSection
|
|
||||||
variables={variables}
|
|
||||||
clients={clients}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Divider className="mb-6" />
|
|
||||||
<Stack className="w-full px-6 pb-8 gap-5 items-stretch">
|
|
||||||
<H2>Other Hosts</H2>
|
|
||||||
{other_hosts[0] ? (
|
|
||||||
<Stack className="w-full gap-4 items-stretch">
|
<Stack className="w-full gap-4 items-stretch">
|
||||||
{other_hosts.map((host) => (
|
{hosts.map((host) => (
|
||||||
<OtherHostCard
|
<HostCard
|
||||||
key={host.id}
|
key={host.id}
|
||||||
host={host}
|
host={host}
|
||||||
client_count={
|
client_count={
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { PagePropsType } from "@/src/types";
|
||||||
|
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
const server: BunextPageServerFn<PagePropsType> = async (ctx) => {
|
||||||
|
const props = ctx.props as PagePropsType;
|
||||||
|
|
||||||
|
if (!props.main_host?.name) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: `/admin/hosts/add`,
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default server;
|
||||||
@@ -8,7 +8,7 @@ import KpiSecondarySection from "./(sections)/kpi-secondary-section";
|
|||||||
import PeersTableSection from "./(sections)/peers-table-section";
|
import PeersTableSection from "./(sections)/peers-table-section";
|
||||||
|
|
||||||
export default function AdminDashboardPage() {
|
export default function AdminDashboardPage() {
|
||||||
const { clients, hosts, variables } = useDashboardData();
|
const { clients, hosts } = useDashboardData();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -21,7 +21,6 @@ export default function AdminDashboardPage() {
|
|||||||
<KpiSecondarySection
|
<KpiSecondarySection
|
||||||
clients={clients}
|
clients={clients}
|
||||||
hosts={hosts}
|
hosts={hosts}
|
||||||
variables={variables}
|
|
||||||
/>
|
/>
|
||||||
<PeersTableSection clients={clients} />
|
<PeersTableSection clients={clients} />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import type { BunextPageModuleMeta } from "@moduletrace/bunext/types";
|
||||||
|
import AdminHero from "@/src/components/general/admin-hero";
|
||||||
|
import { SiteData } from "@/src/data/site-data";
|
||||||
|
import Divider from "@/src/components/twui/layout/Divider";
|
||||||
|
import Stack from "@/src/components/twui/layout/Stack";
|
||||||
|
|
||||||
|
export default function AdminWireguardSetupPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AdminHero
|
||||||
|
title="Setup"
|
||||||
|
description="Setup wireguard and wg-ui. Check if dependencies are installed. Update wg-ui and related packages. Etc."
|
||||||
|
/>
|
||||||
|
<Divider className="mb-6" />
|
||||||
|
<Stack className="w-full px-6 pb-8 gap-5 items-stretch"></Stack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const meta: BunextPageModuleMeta = {
|
||||||
|
title: `Admin Wireguard Setup | ${SiteData["SiteName"]}`,
|
||||||
|
description: `Setup wireguard and wg-ui. Check if dependencies are installed. Update wg-ui and related packages. Etc.`,
|
||||||
|
};
|
||||||
@@ -47,6 +47,7 @@ export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
|||||||
short_description: body?.short_description,
|
short_description: body?.short_description,
|
||||||
listen_port: body?.listen_port,
|
listen_port: body?.listen_port,
|
||||||
user,
|
user,
|
||||||
|
is_main_host: body.is_main_host || undefined,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
@@ -54,4 +55,4 @@ export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
|||||||
msg: error.message,
|
msg: error.message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import checkUserAccess from "@/src/functions/backend/auth/check-user-access";
|
||||||
|
import userAuth from "@/src/functions/backend/auth/user-auth";
|
||||||
|
import deleteWireguardHost from "@/src/functions/backend/setup/delete-wireguard-host";
|
||||||
|
import type { ApiReqParams } from "@/src/types";
|
||||||
|
import type {
|
||||||
|
APIResponseObject,
|
||||||
|
BunextAPIRouteHandler,
|
||||||
|
} from "@moduletrace/bunext/types";
|
||||||
|
|
||||||
|
export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
||||||
|
params,
|
||||||
|
) => {
|
||||||
|
const req = params.req;
|
||||||
|
const body = params.body as ApiReqParams;
|
||||||
|
|
||||||
|
if (req.method !== "DELETE") {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { user, user_types } = await userAuth({ req });
|
||||||
|
|
||||||
|
if (!user?.logged_in_status) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
msg: `Unauthorized`,
|
||||||
|
logoutUser: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const is_super_admin = checkUserAccess({ user_types });
|
||||||
|
|
||||||
|
if (!is_super_admin.success) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
msg: `Unauthorized`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const host_id = body?.host_id;
|
||||||
|
|
||||||
|
if (typeof host_id !== "number" && typeof host_id !== "string") {
|
||||||
|
throw new Error(`Please pass host ID to be deleted!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const delete_host_res = await deleteWireguardHost({
|
||||||
|
host_id: Number(host_id),
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
|
||||||
|
return delete_host_res;
|
||||||
|
} catch (error: any) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
msg: error.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import checkUserAccess from "@/src/functions/backend/auth/check-user-access";
|
import checkUserAccess from "@/src/functions/backend/auth/check-user-access";
|
||||||
import userAuth from "@/src/functions/backend/auth/user-auth";
|
import userAuth from "@/src/functions/backend/auth/user-auth";
|
||||||
import setupWireguardHost from "@/src/functions/backend/setup/setup-wireguard-host";
|
import createWireguardHost from "@/src/functions/backend/setup/create-wireguard-host";
|
||||||
import type { ApiReqParams } from "@/src/types";
|
import type { ApiReqParams } from "@/src/types";
|
||||||
import type {
|
import type {
|
||||||
APIResponseObject,
|
APIResponseObject,
|
||||||
BunextAPIRouteHandler,
|
BunextAPIRouteHandler,
|
||||||
} from "@moduletrace/bunext/types";
|
} from "@moduletrace/bunext/types";
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
||||||
params,
|
params,
|
||||||
@@ -40,11 +39,12 @@ export const handler: BunextAPIRouteHandler<APIResponseObject> = async (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return await setupWireguardHost({
|
return await createWireguardHost({
|
||||||
host: {
|
wg_ip_address: body.ip_address,
|
||||||
wg_ip_address: body.ip_address,
|
interface: body.interface,
|
||||||
},
|
name: "Main",
|
||||||
user,
|
user,
|
||||||
|
is_main_host: true,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ export type PagePropsType = {
|
|||||||
main_host_dir_names?: ReturnType<typeof grabHostDirnames> | null;
|
main_host_dir_names?: ReturnType<typeof grabHostDirnames> | null;
|
||||||
network_interfaces?: string[] | null;
|
network_interfaces?: string[] | null;
|
||||||
next_listen_port?: number | null;
|
next_listen_port?: number | null;
|
||||||
|
is_main_host?: boolean | null;
|
||||||
|
main_host?: BUN_SQLITE_WGUI_HOSTS | null;
|
||||||
|
next_available_client_ip?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AppContextObject = {
|
export type AppContextObject = {
|
||||||
@@ -262,6 +265,7 @@ export type ApiReqParams<
|
|||||||
|
|
||||||
ip_address?: string;
|
ip_address?: string;
|
||||||
wg_ip_address?: string | null;
|
wg_ip_address?: string | null;
|
||||||
|
is_main_host?: boolean | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserAuthReturn = {
|
export type UserAuthReturn = {
|
||||||
|
|||||||
Reference in New Issue
Block a user