From aa0a2929433ace23bbd73fde4fe3ec14c4006d0b Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Sun, 20 Sep 2026 17:04:17 +0100 Subject: [PATCH] Updates --- src/components/general/client-row.tsx | 4 +- .../backend/setup/setup-wireguard-host.ts | 8 +- .../admin/(sections)/peers-table-section.tsx | 61 +++++++++++-- .../hosts/[host_id]/edit/index.server.ts | 15 +++- .../admin/hosts/[host_id]/edit/index.tsx | 13 ++- .../admin/hosts/[host_id]/index.server.ts | 11 ++- src/pages/admin/hosts/[host_id]/index.tsx | 2 +- .../add/(functions)/submit-add-host-form.ts | 47 ++++++---- .../add-host-form/add-host-form-action.tsx | 7 +- .../add-host-form/add-host-form-interface.tsx | 13 +++ .../add-host-form-listen-port.tsx | 17 +++- .../add-host-form/add-host-form-public-ip.tsx | 29 ++++-- .../add-host-form-wg-ip-address.tsx | 12 +++ .../add-host-form/add-host-form.tsx | 15 +++- src/pages/api/admin/update-host.ts | 90 +++++++++++++++++++ src/types/index.ts | 1 + 16 files changed, 295 insertions(+), 50 deletions(-) create mode 100644 src/pages/api/admin/update-host.ts diff --git a/src/components/general/client-row.tsx b/src/components/general/client-row.tsx index 2d73867..6ce15ba 100644 --- a/src/components/general/client-row.tsx +++ b/src/components/general/client-row.tsx @@ -76,7 +76,9 @@ export default function ClientRow({ client, rules }: Props) { {client.wg_ip_address || "—"} - {client.allowed_ips || "—"} + {client.allow_all_ips + ? "0.0.0.0/0, ::/0" + : client.allowed_ips || "—"} ( + { + table: "client_rules", + sql_query: { + limit: 500, + }, + }, + ); + + const rules_by_client_id = useMemo(() => { + const map = new Map(); + + for (let i = 0; i < (client_rules || []).length; i++) { + const rule = client_rules?.[i]; + const client_id = Number(rule?.client_id); + + if (!rule || !client_id) { + continue; + } + + const existing = map.get(client_id) || []; + existing.push(rule); + map.set(client_id, existing); + } + + return map; + }, [client_rules]); + return ( @@ -40,24 +73,40 @@ export default function PeersTableSection({ clients }: Props) { {recent.length ? (
- - + + + + + {recent.map((client) => ( - + ))}
ClientHost Tunnel IP Allowed IPsAccess List Public key CreatedActions
) : ( - + No clients yet @@ -68,4 +117,4 @@ export default function PeersTableSection({ clients }: Props) { )}
); -} \ No newline at end of file +} diff --git a/src/pages/admin/hosts/[host_id]/edit/index.server.ts b/src/pages/admin/hosts/[host_id]/edit/index.server.ts index c366ab5..dd25204 100644 --- a/src/pages/admin/hosts/[host_id]/edit/index.server.ts +++ b/src/pages/admin/hosts/[host_id]/edit/index.server.ts @@ -1,4 +1,7 @@ import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db"; +import getInterfaceLocalIP from "@/src/functions/backend/setup/get-interface-local-ip"; +import grabHostNetworkInterfaces from "@/src/functions/backend/setup/grab-host-network-interfaces"; +import grabHostPublicIPAddress from "@/src/functions/backend/setup/grab-host-public-ip-address"; import type { PagePropsType, PageQueryObject, TableType } from "@/src/types"; import BunSQLite from "@moduletrace/bun-sqlite"; import type { BunextPageServerFn } from "@moduletrace/bunext/types"; @@ -8,19 +11,23 @@ const server: BunextPageServerFn = async ({ query }) => { const host_id = Number(page_query.host_id || 0); - const host_res = await BunSQLite.select< - BUN_SQLITE_WGUI_HOSTS, - TableType - >({ + const host_res = await BunSQLite.select({ table: "hosts", targetId: host_id, }); const host = host_res.singleRes || null; + const network_interfaces = await grabHostNetworkInterfaces(); + const local_ip = host?.interface + ? await getInterfaceLocalIP(host?.interface) + : null; + return { props: { host, + network_interfaces, + is_local_ip: local_ip == host?.public_ip_address, }, }; }; diff --git a/src/pages/admin/hosts/[host_id]/edit/index.tsx b/src/pages/admin/hosts/[host_id]/edit/index.tsx index 585f6eb..cb894e5 100644 --- a/src/pages/admin/hosts/[host_id]/edit/index.tsx +++ b/src/pages/admin/hosts/[host_id]/edit/index.tsx @@ -9,6 +9,9 @@ import { ArrowLeft } from "lucide-react"; import { useContext } from "react"; import { AppContext } from "@/src/pages/__root"; import EditHostFormSection from "./(sections)/edit-host-form-section"; +import AddHostForm from "../../add/(partials)/add-host-form/add-host-form"; +import _ from "lodash"; +import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins"; export default function AdminEditHostPage() { const { pageProps, query } = useContext(AppContext); @@ -40,7 +43,13 @@ export default function AdminEditHostPage() { {pageProps?.host ? ( - + (pageProps.host, ["name", "short_description"])} + existing_host_full={pageProps.host} + /> ) : ( )} @@ -52,4 +61,4 @@ export default function AdminEditHostPage() { export const meta: BunextPageModuleMeta = { title: `Edit Host | ${SiteData["SiteName"]}`, description: `WireGuard edit host page`, -}; \ No newline at end of file +}; diff --git a/src/pages/admin/hosts/[host_id]/index.server.ts b/src/pages/admin/hosts/[host_id]/index.server.ts index 1d8d9e8..a4269c5 100644 --- a/src/pages/admin/hosts/[host_id]/index.server.ts +++ b/src/pages/admin/hosts/[host_id]/index.server.ts @@ -1,14 +1,13 @@ -import type { BUN_SQLITE_WGUI_CLIENTS, BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db"; +import type { + BUN_SQLITE_WGUI_CLIENTS, + BUN_SQLITE_WGUI_HOSTS, +} from "@/db/types/db"; import grabHostDirnames from "@/src/functions/backend/setup/grab-host-dir-names"; import type { PagePropsType, PageQueryObject, TableType } from "@/src/types"; import BunSQLite from "@moduletrace/bun-sqlite"; import type { BunextPageServerFn } from "@moduletrace/bunext/types"; -const server: BunextPageServerFn = async ({ - req, - url, - query, -}) => { +const server: BunextPageServerFn = async ({ query }) => { const page_query = query as PageQueryObject; const host_record_res = await BunSQLite.select< diff --git a/src/pages/admin/hosts/[host_id]/index.tsx b/src/pages/admin/hosts/[host_id]/index.tsx index 9f31dd0..74f2a76 100644 --- a/src/pages/admin/hosts/[host_id]/index.tsx +++ b/src/pages/admin/hosts/[host_id]/index.tsx @@ -59,7 +59,7 @@ export default function AdminSingleHostPage() { color="primary" href={`/admin/hosts/${host_id}/clients`} > - View Clients + Clients ); -} \ No newline at end of file +} diff --git a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-interface.tsx b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-interface.tsx index d9131de..eec78e1 100644 --- a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-interface.tsx +++ b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-interface.tsx @@ -1,4 +1,5 @@ import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db"; +import Input from "@/src/components/twui/form/Input"; import Select from "@/src/components/twui/form/Select"; import Stack from "@/src/components/twui/layout/Stack"; import useFormInit from "@/src/hooks/use-form-init"; @@ -9,9 +10,21 @@ export default function AddHostFormInterface({ form, setForm, app_context, + existing_full, }: Props) { const interfaces = app_context.pageProps?.network_interfaces || []; + if (existing_full?.id) { + return ( + + ); + } + return ( + ); + } + async function handleGrabNext() { setBusy(true); try { diff --git a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-public-ip.tsx b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-public-ip.tsx index 5ccc573..ebfe239 100644 --- a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-public-ip.tsx +++ b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-public-ip.tsx @@ -1,9 +1,6 @@ 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 Row from "@/src/components/twui/layout/Row"; -import Span from "@/src/components/twui/layout/Span"; -import Toggle from "@/src/components/twui/elements/Toggle"; import useFormInit from "@/src/hooks/use-form-init"; import { useEffect, useState } from "react"; import fetchApi from "@/src/components/twui/utils/fetch/fetchApi"; @@ -16,10 +13,17 @@ import LoadingOverlay from "@/src/components/twui/elements/LoadingOverlay"; type Props = ReturnType>; -export default function AddHostFormPublicIP({ form, setForm }: Props) { +export default function AddHostFormPublicIP({ + form, + setForm, + app_context, + existing_full, +}: Props) { const [useLocalIP, setUseLocalIP] = useState(false); - const { loading, setLoading } = useStatus({ initialLoading: true }); + const { loading, setLoading } = useStatus({ + initialLoading: existing_full?.id ? false : true, + }); function fetchIP(iface: string, local: boolean) { if (!iface) return; @@ -53,6 +57,17 @@ export default function AddHostFormPublicIP({ form, setForm }: Props) { fetchIP(form.interface, useLocalIP); }, [form.interface, useLocalIP]); + if (existing_full?.id) { + return ( + + ); + } + return ( {loading ? : null} @@ -76,7 +91,9 @@ export default function AddHostFormPublicIP({ form, setForm }: Props) { label={ Use Local IP? } - defaultChecked={useLocalIP} + defaultChecked={ + useLocalIP || Boolean(app_context.pageProps?.is_local_ip) + } /> ); diff --git a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-wg-ip-address.tsx b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-wg-ip-address.tsx index 7469595..98d7865 100644 --- a/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-wg-ip-address.tsx +++ b/src/pages/admin/hosts/add/(partials)/add-host-form/add-host-form-wg-ip-address.tsx @@ -3,6 +3,7 @@ import GrabNextSubnetButton from "@/src/components/general/grab-next-subnet-butt import HostWgIpField, { type HostWgIpFieldStatus, } from "@/src/components/general/host-wg-ip-field"; +import Input from "@/src/components/twui/form/Input"; import Stack from "@/src/components/twui/layout/Stack"; import useFormInit from "@/src/hooks/use-form-init"; @@ -14,6 +15,17 @@ export default function AddHostFormWgIpAddress({ setIpStatus, ...props }: Props) { + if (props.existing_full?.wg_ip_address) { + return ( + + ); + } + return ( ({ default: { wg_ip_address: AppData["DefaultPrivateIP"], @@ -26,6 +33,8 @@ export default function AddHostForm() { }, title: "new_host", async before_ready_function(params) { + if (existing_host_full?.id) return; + params.setForm((prev) => ({ ...prev, interface: @@ -38,6 +47,8 @@ export default function AddHostForm() { undefined, })); }, + existing: existing_host, + existing_full: existing_host_full, }); const [ipStatus, setIpStatus] = useState("checking"); diff --git a/src/pages/api/admin/update-host.ts b/src/pages/api/admin/update-host.ts new file mode 100644 index 0000000..72bcb59 --- /dev/null +++ b/src/pages/api/admin/update-host.ts @@ -0,0 +1,90 @@ +import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db"; +import checkUserAccess from "@/src/functions/backend/auth/check-user-access"; +import userAuth from "@/src/functions/backend/auth/user-auth"; +import createWireguardHost from "@/src/functions/backend/setup/create-wireguard-host"; +import setupWireguardHost from "@/src/functions/backend/setup/setup-wireguard-host"; +import type { ApiReqParams, TableType } from "@/src/types"; +import BunSQLite from "@moduletrace/bun-sqlite"; +import type { + APIResponseObject, + BunextAPIRouteHandler, +} from "@moduletrace/bunext/types"; + +export const handler: BunextAPIRouteHandler = async ( + params, +) => { + const req = params.req; + const body = params.body as ApiReqParams; + + if (req.method !== "POST") { + 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`, + }; + } + + if (typeof body.host_id !== "number") { + throw new Error(`Invalid host id`); + } + + const host_record_res = await BunSQLite.select< + BUN_SQLITE_WGUI_HOSTS, + TableType + >({ + table: "hosts", + targetId: body.host_id, + }); + + const host = host_record_res.singleRes; + + if (!host?.created_at) { + throw new Error(`Couldn't find host record`); + } + + if (!body.update_data) { + throw new Error(`No data to update`); + } + + const update_host_record = await BunSQLite.update< + BUN_SQLITE_WGUI_HOSTS, + TableType + >({ + table: "hosts", + data: body.update_data, + targetId: String(host.id), + }); + + const update = await setupWireguardHost({ + host, + user, + }); + + return { + success: true, + }; + } catch (error: any) { + return { + success: false, + msg: error.message, + }; + } +}; diff --git a/src/types/index.ts b/src/types/index.ts index 414712d..df8eec3 100755 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -70,6 +70,7 @@ export type PagePropsType = { is_main_host?: boolean | null; main_host?: BUN_SQLITE_WGUI_HOSTS | null; next_available_client_ip?: string | null; + is_local_ip?: boolean | null; }; export type AppContextObject = {