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 👋
+ (isOpen = true)}>
+
+ Create Server
+
-
-
- Welcome to SvelteKit
- Visit kit.svelte.dev to read the documentation
-
- Button
-
-
+
+ {#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'}
+ Online
+ Up
+ {:else}
+ Offline
+ Down
+ {/if}
+
+
+
+
+
+ Manage
+
+
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}
+
+ (dialogOpen = true)}>Add Client
+
+ {/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