diff --git a/src/app.css b/src/app.css index c7bf8da..60d4abc 100644 --- a/src/app.css +++ b/src/app.css @@ -4,16 +4,16 @@ @layer base { :root { - --background: 0 0% 100%; + --background: 0 0% 90%; --foreground: 222.2 84% 4.9%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; - --popover: 0 0% 100%; + --popover: 0 0% 90%; --popover-foreground: 222.2 84% 4.9%; - --card: 0 0% 100%; + --card: 0 0% 90%; --card-foreground: 222.2 84% 4.9%; --border: 214.3 31.8% 91.4%; @@ -22,10 +22,10 @@ --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; - --secondary: 210 40% 96.1%; + --secondary: 210 26% 86%; --secondary-foreground: 222.2 47.4% 11.2%; - --accent: 210 40% 96.1%; + --accent: 210 26% 86%; --accent-foreground: 222.2 47.4% 11.2%; --destructive: 0 72.2% 50.6%; @@ -39,31 +39,31 @@ @media (prefers-color-scheme: dark) { :root { --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; + --foreground: 210 40% 90%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; + --popover-foreground: 210 40% 90%; --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; + --card-foreground: 210 40% 90%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; - --primary: 210 40% 98%; + --primary: 210 40% 90%; --primary-foreground: 222.2 47.4% 11.2%; --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; + --secondary-foreground: 210 40% 90%; --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; + --accent-foreground: 210 40% 90%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; + --destructive-foreground: 210 40% 90%; --ring: 212.7 26.8% 83.9%; } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index ae3130b..72151c6 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -31,14 +31,17 @@ const handleAuth: Handle = async ({ event, resolve }) => { }; -const authRequired = new Set([ - '/user', - '/connections', - '/api/connections', -]); +const authRequired = [ + /^\/api/, + /^\/user/, + /^\/connections/, + /^\/clients/, +]; const handleProtectedPaths: Handle = ({ event, resolve }) => { - if (authRequired.has(event.url.pathname) && !event.locals.user) { - return redirect(302, '/'); + const isProtected = authRequired.some((re) => re.test(event.url.pathname)); + + if (!event.locals.user && isProtected) { + return redirect(302, '/'); } return resolve(event); } diff --git a/src/lib/server/clients.ts b/src/lib/server/clients.ts index 08a4849..b0bf3af 100644 --- a/src/lib/server/clients.ts +++ b/src/lib/server/clients.ts @@ -140,7 +140,7 @@ export async function createClient(params: { username: params.user.username, pubkey: keys.pubkey, psk: keys.psk, - allowedIps: getIpsFromIndex(ipAllocationId - 1).join(','), + allowedIps: getIpsFromIndex(ipAllocationId).join(','), }); const opnsenseResJson = await opnsenseRes.json(); if (opnsenseResJson['result'] !== 'saved') { @@ -178,6 +178,7 @@ async function getKeys() { } export function getIpsFromIndex(ipIndex: number) { + ipIndex -= 1; // 1-indexed in the db const v4StartingAddr = new Address4(IPV4_STARTING_ADDR); const v6StartingAddr = new Address6(IPV6_STARTING_ADDR); const v4Allowed = Address4.fromBigInt(v4StartingAddr.bigInt() + BigInt(ipIndex)); diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts index 5ad7bd0..a806c2d 100644 --- a/src/lib/server/db/schema.ts +++ b/src/lib/server/db/schema.ts @@ -26,7 +26,7 @@ export const ipAllocations = sqliteTable('ip_allocations', { // unique for now, only allowing one allocation per client clientId: integer('client_id') .unique() - .references(() => wgClients.id), + .references(() => wgClients.id, { onDelete: 'set null' }), }); export const wgClients = sqliteTable('wg_clients', { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 03fcda6..b3b910e 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -6,20 +6,20 @@ const { data, children } = $props(); const { user } = data; - function getNavClass(path: string) { + function getNavClass(path: RegExp) { return cn('hover:text-foreground/80 transition-colors', - $page.url.pathname.startsWith(path) ? 'text-foreground' : 'text-foreground/60'); + path.test($page.url.pathname) ? 'text-foreground' : 'text-foreground/60'); }
VPGen
diff --git a/src/routes/api/clients/+server.ts b/src/routes/api/clients/+server.ts index 5083c6c..3fa49f9 100644 --- a/src/routes/api/clients/+server.ts +++ b/src/routes/api/clients/+server.ts @@ -1,9 +1,6 @@ import { error } from '@sveltejs/kit'; -import { wgClients } from '$lib/server/db/schema'; -import { db } from '$lib/server/db'; -import { eq } from 'drizzle-orm'; import type { RequestHandler } from './$types'; -import { createClient, getIpsFromIndex } from '$lib/server/clients'; +import { createClient, findClients, mapClientToDetails } from '$lib/server/clients'; export const GET: RequestHandler = async (event) => { if (!event.locals.user) { @@ -13,38 +10,11 @@ export const GET: RequestHandler = async (event) => { const clients = await findClients(event.locals.user.id); return new Response( JSON.stringify({ - clients, + clients: clients.map(mapClientToDetails), }), ); }; -async function findClients(userId: string) { - const clientsData = await db.query.wgClients.findMany({ - columns: { - id: true, - name: true, - publicKey: true, - privateKey: true, - preSharedKey: true, - }, - with: { - ipAllocation: true, - }, - where: eq(wgClients.userId, userId), - }); - // replace ip index with actual addresses - return clientsData.map((client) => { - const ips = getIpsFromIndex(client.ipAllocation.id); - return { - id: client.id, - name: client.name, - publicKey: client.publicKey, - privateKey: client.privateKey, - preSharedKey: client.preSharedKey, - ips, - }; - }); -} export type Clients = Awaited>; diff --git a/src/routes/clients/+page.server.ts b/src/routes/clients/+page.server.ts index bff4fa8..512d681 100644 --- a/src/routes/clients/+page.server.ts +++ b/src/routes/clients/+page.server.ts @@ -5,9 +5,11 @@ import { error } from '@sveltejs/kit'; export const actions = { create: async (event) => { if (!event.locals.user) return error(401, 'Unauthorized'); - const name = 'New Client Name'; + const formData = await event.request.formData(); + const name = formData.get('name'); + if (typeof name !== 'string' || name.trim() === '') return error(400, 'Invalid name'); const res = await createClient({ - name, + name: name.trim(), user: event.locals.user, }); diff --git a/src/routes/clients/+page.svelte b/src/routes/clients/+page.svelte index 282aa18..9e6f3f2 100644 --- a/src/routes/clients/+page.svelte +++ b/src/routes/clients/+page.svelte @@ -2,6 +2,7 @@ import * as Table from '$lib/components/ui/table'; import { Badge } from '$lib/components/ui/badge'; import { Button } from '$lib/components/ui/button'; + import { Input } from '$lib/components/ui/input'; import type { PageData } from './$types'; import { LucidePlus } from 'lucide-svelte'; @@ -12,26 +13,28 @@ Clients - + - Name - Public Key - Private Key - Pre-Shared Key - IP Allocation + + Name + Public Key + + + IP Allocation + - + {#each data.clients as client} - - - + + + {client.name} - - - {client.publicKey} - {client.privateKey} - {client.preSharedKey} - + + + {client.publicKey} + + + {#each client.ips as ip} {ip} {/each} @@ -42,9 +45,11 @@ -
+ + +
diff --git a/src/routes/clients/+page.ts b/src/routes/clients/+page.ts index 643cd24..520bb6e 100644 --- a/src/routes/clients/+page.ts +++ b/src/routes/clients/+page.ts @@ -1,9 +1,9 @@ import type { PageLoad } from './$types'; -import type { Clients } from '../api/clients/+server'; +import type { ClientDetails } from '$lib/types/clients'; export const load: PageLoad = async ({ fetch }) => { const res = await fetch('/api/clients'); - const { clients } = await res.json() as { clients: Clients }; + const { clients } = await res.json() as { clients: ClientDetails[] }; return { clients }; }; diff --git a/src/routes/clients/[id]/+page.svelte b/src/routes/clients/[id]/+page.svelte index cfee559..37f5324 100644 --- a/src/routes/clients/[id]/+page.svelte +++ b/src/routes/clients/[id]/+page.svelte @@ -1,19 +1,19 @@ @@ -21,21 +21,24 @@ -

Client: {data.client.name}

+

{data.client.name}

-
-
{data.config}
+
+
+
{data.config}
- -
- - + + +
+ + +
-
\ No newline at end of file +
diff --git a/src/routes/clients/[id]/+page.ts b/src/routes/clients/[id]/+page.ts index 8a3b993..bd27d3b 100644 --- a/src/routes/clients/[id]/+page.ts +++ b/src/routes/clients/[id]/+page.ts @@ -1,10 +1,15 @@ import type { PageLoad } from './$types'; import type { ClientDetails } from '$lib/types/clients'; import { clientDetailsToConfig } from '$lib/clients'; +import { error } from '@sveltejs/kit'; export const load: PageLoad = async ({ fetch, params }) => { const res = await fetch(`/api/clients/${params.id}`); - const client = (await res.json()) as ClientDetails; + const resJson = await res.json(); + if (!res.ok) { + return error(res.status, resJson['message']); + } + const client = resJson as ClientDetails; const config = clientDetailsToConfig(client); return { client, config }; diff --git a/src/routes/connections/+page.svelte b/src/routes/connections/+page.svelte index 567e317..8873f85 100644 --- a/src/routes/connections/+page.svelte +++ b/src/routes/connections/+page.svelte @@ -33,22 +33,24 @@ Connections - + - Name - Public Key - Endpoint - Allowed IPs - Latest Handshake - RX - TX - - + + Name + Public Key + Endpoint + Allowed IPs + Latest Handshake + RX + TX + + + - + {#each data.peers.rows as peer} - - {peer.name} + + {peer.name} {peer['public-key']} {peer.endpoint}