diff --git a/web/src/lib/assets/vps.29373866.svg b/web/src/lib/assets/vps.29373866.svg deleted file mode 100644 index 40f6fa9..0000000 --- a/web/src/lib/assets/vps.29373866.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - vps - Created with Sketch. - - - - diff --git a/web/src/routes/+page.server.ts b/web/src/routes/+page.server.ts index 959e4ec..6023fe0 100644 --- a/web/src/routes/+page.server.ts +++ b/web/src/routes/+page.server.ts @@ -1,12 +1,36 @@ -import type { Actions } from '@sveltejs/kit'; +import { type Actions, error } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; +import { findServer, getServers, WGServer } from '$lib/wireguard'; +import { superValidate } from 'sveltekit-superforms/server'; +import { CreateServerSchema } from './schema'; +import { NameSchema } from '$lib/wireguard/schema'; -export const load: PageServerLoad = () => { - return {}; +export const load: PageServerLoad = async () => { + return { + servers: (await getServers()).map((s) => s), + form: superValidate(CreateServerSchema), + }; }; export const actions: Actions = { - default: async ({ request, cookies }) => { - return { message: 'Success!' }; + rename: async ({ request, params }) => { + const form = await request.formData(); + const serverId = (form.get('id') ?? '').toString(); + const name = (form.get('name') ?? '').toString(); + + const server = await findServer(serverId ?? ''); + if (!server) { + console.error('Server not found'); + return error(404, 'Not found'); + } + + if (!NameSchema.safeParse(name).success) { + console.error('Peer name is invalid'); + return error(400, 'Bad Request'); + } + + await WGServer.update(server.id, { name }); + + return { ok: true }; }, }; diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 6188415..5a2fe04 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -1,20 +1,62 @@

Hello there 👋

+
- - -

Welcome to SvelteKit

-

Visit kit.svelte.dev to read the documentation

- - -
-
+
+ {#if data.servers?.length < 1} + No Servers Found + {:else} + + + Servers + + {#each data.servers as server} + { + handleRename(server.id.toString(), detail); + }} + /> + {/each} + + {/if} +
+ + diff --git a/web/src/routes/Server.svelte b/web/src/routes/Server.svelte new file mode 100644 index 0000000..4714d61 --- /dev/null +++ b/web/src/routes/Server.svelte @@ -0,0 +1,61 @@ + + +
+
+
+
+ +
+ +
+ { + dispatch('rename', detail.value.toString()); + }} + let:editMode + asChild + > + + {server.name} + + + + {addressPort} + +
+
+
+ + {#if server.status === 'up'} + + Up + {:else} + + Down + {/if} + +
+
+ + +
diff --git a/web/src/routes/[serverId]/+layout.svelte b/web/src/routes/[serverId]/+layout.svelte new file mode 100644 index 0000000..fbe3726 --- /dev/null +++ b/web/src/routes/[serverId]/+layout.svelte @@ -0,0 +1,19 @@ + + + + + +
+ +
+
diff --git a/web/src/routes/[serverId]/+page.server.ts b/web/src/routes/[serverId]/+page.server.ts new file mode 100644 index 0000000..a415d3c --- /dev/null +++ b/web/src/routes/[serverId]/+page.server.ts @@ -0,0 +1,46 @@ +import { type Actions, error } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; +import { findServer, WGServer } from '$lib/wireguard'; +import { NameSchema } from '$lib/wireguard/schema'; + +export const load: PageServerLoad = async ({ params }) => { + const { serverId } = params; + const server = await findServer(serverId); + + if (server) { + return { server }; + } + + throw error(404, 'Not found'); +}; + +export const actions: Actions = { + rename: async ({ request, params }) => { + const { serverId } = params; + + const server = await findServer(serverId ?? ''); + if (!server) { + console.error('Server not found'); + return error(404, 'Not found'); + } + + + const form = await request.formData(); + const peerId = (form.get('id') ?? '').toString(); + const peer = server.peers.find((p) => p.id === peerId); + if (!peer) { + console.error('Peer not found'); + return error(404, 'Not found'); + } + + const name = (form.get('name') ?? '').toString(); + if (!NameSchema.safeParse(name).success) { + console.error('Peer name is invalid'); + return error(400, 'Bad Request'); + } + + await WGServer.updatePeer(server.id, peer.publicKey, { name }); + + return { ok: true }; + }, +}; diff --git a/web/src/routes/[serverId]/+page.svelte b/web/src/routes/[serverId]/+page.svelte new file mode 100644 index 0000000..576d84a --- /dev/null +++ b/web/src/routes/[serverId]/+page.svelte @@ -0,0 +1,82 @@ + + + + +Hello there! + + + + Clients + + + + {#each data.server.peers as peer} + { + handleRename(peer.id.toString(), detail); + }} + on:remove={() => { + handleRemove(peer.id.toString()); + }} + /> + {/each} + + {#if data.server.peers.length > 0} + + + + {/if} + diff --git a/web/src/routes/[serverId]/Peer.svelte b/web/src/routes/[serverId]/Peer.svelte new file mode 100644 index 0000000..2235a1e --- /dev/null +++ b/web/src/routes/[serverId]/Peer.svelte @@ -0,0 +1,97 @@ + + +
+
+
+ +
+ +
+ { + handleRename(detail.value); + }} + /> + + {peer.allowedIps} + +
+
+
+ + + + + + + + + + + + + + +
+
diff --git a/web/src/routes/[serverId]/PeerActionButton.svelte b/web/src/routes/[serverId]/PeerActionButton.svelte new file mode 100644 index 0000000..f8c3f14 --- /dev/null +++ b/web/src/routes/[serverId]/PeerActionButton.svelte @@ -0,0 +1,35 @@ + + +
{ + if (e.key === 'Enter') handleClick(); + }} +> + +
diff --git a/web/src/routes/api/host/+server.ts b/web/src/routes/api/host/+server.ts new file mode 100644 index 0000000..9cf3e8f --- /dev/null +++ b/web/src/routes/api/host/+server.ts @@ -0,0 +1,22 @@ +import type { RequestHandler } from '@sveltejs/kit'; +import { WG_HOST } from '$env/static/private'; +import Shell from '$lib/shell'; + +export const GET: RequestHandler = async () => { + + let HOSTNAME = WG_HOST; + + // if the host is not set, then we are using the server's public IP + if (!HOSTNAME) { + const resp = await Shell.exec('curl -s ifconfig.me', true); + HOSTNAME = resp.trim(); + } + + // check if WG_HOST is still not set + if (!HOSTNAME) { + console.error('WG_HOST is not set'); + return new Response('NOT_SET', { status: 500, headers: { 'Content-Type': 'text/plain' } }); + } + + return new Response(HOSTNAME, { status: 200, headers: { 'Content-Type': 'text/plain' } }); +}; diff --git a/web/src/routes/schema.ts b/web/src/routes/schema.ts index b8fd21b..d8e9e24 100644 --- a/web/src/routes/schema.ts +++ b/web/src/routes/schema.ts @@ -9,3 +9,5 @@ export const CreateServerSchema = z.object({ dns: DnsSchema, mtu: MtuSchema, }); + +export type CreateServerSchemaType = typeof CreateServerSchema; \ No newline at end of file