diff --git a/src/lib/opnsense/wg.ts b/src/lib/opnsense/wg.ts index 3bef846..9c4c54a 100644 --- a/src/lib/opnsense/wg.ts +++ b/src/lib/opnsense/wg.ts @@ -67,3 +67,41 @@ export interface OpnsenseWgServers { uuid: string; }[]; } + +/** + * Sample response for OPNsense WireGuard clients + * ```json + * { + * "rows": [ + * { + * "uuid": "d99334de-7671-4ca7-9c9b-5f5578acae70", + * "enabled": "1", + * "name": "Yura-TPX13", + * "pubkey": "iJa5JmJbMHNlbEluNwoB2Q8LyrPAfb7S/mluanMcI08=", + * "tunneladdress": "fd00::1/112,10.6.0.3/32", + * "serveraddress": "", + * "serverport": "", + * "servers": "wg0" + * } + * ], + * "rowCount": 1, + * "total": 10, + * "current": 1 + * } + * ``` + */ +export interface OpnsenseWgClients { + rowCount: number; + total: number; + current: number; + rows: { + uuid: string; + enabled: string; + name: string; + pubkey: string; + tunneladdress: string; + serveraddress: string; + serverport: string; + servers: string; + }[]; +} diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts index 6b51959..5ad7bd0 100644 --- a/src/lib/server/db/schema.ts +++ b/src/lib/server/db/schema.ts @@ -49,7 +49,14 @@ export const wgClients = sqliteTable('wg_clients', { }); export const wgClientsRelations = relations(wgClients, ({ one }) => ({ - ipAllocation: one(ipAllocations), + user: one(users, { + fields: [wgClients.userId], + references: [users.id], + }), + ipAllocation: one(ipAllocations, { + fields: [wgClients.id], + references: [ipAllocations.clientId], + }), })); export type WgClient = typeof wgClients.$inferSelect; diff --git a/src/lib/server/db/seed.ts b/src/lib/server/db/seed.ts index 92f1418..1ebb61e 100644 --- a/src/lib/server/db/seed.ts +++ b/src/lib/server/db/seed.ts @@ -1,4 +1,4 @@ -import { users, wgClients } from './schema'; +import { ipAllocations, users, wgClients } from './schema'; import { eq } from 'drizzle-orm'; import assert from 'node:assert'; import { drizzle } from 'drizzle-orm/libsql'; @@ -7,23 +7,27 @@ import * as schema from '$lib/server/db/schema'; assert(process.env.DATABASE_URL, 'DATABASE_URL is not set'); const db = drizzle(process.env.DATABASE_URL, { schema }); -export async function seed() { +async function seed() { const user = await db.query.users.findFirst({ where: eq(users.username, 'CaZzzer') }); assert(user, 'User not found'); - const clients = [ + const clients: typeof wgClients.$inferInsert[] = [ { userId: user.id, name: 'Client1', publicKey: 'BJ5faPVJsDP4CCxNYilmKnwlQXOtXEOJjqIwb4U/CgM=', privateKey: 'KKqsHDu30WCSrVsyzMkOKbE3saQ+wlx0sBwGs61UGXk=', preSharedKey: '0LWopbrISXBNHUxr+WOhCSAg+0hD8j3TLmpyzHkBHCQ=', - ipIndex: 1, + // ipIndex: 1, // allowedIps: '10.18.11.101/32,fd00::1/112', - } - ] + }, + ]; + const returned = await db.insert(wgClients).values(clients).returning({ insertedId: wgClients.id }); - await db.insert(wgClients).values(clients); + const ipAllocation: typeof ipAllocations.$inferInsert = { + clientId: returned[0].insertedId, + }; + await db.insert(ipAllocations).values(ipAllocation); } seed(); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 6bdb547..28f08c6 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -19,6 +19,7 @@ {#if user} Profile Connections + Clients {/if} diff --git a/src/routes/api/clients/+server.ts b/src/routes/api/clients/+server.ts new file mode 100644 index 0000000..5053d83 --- /dev/null +++ b/src/routes/api/clients/+server.ts @@ -0,0 +1,28 @@ +import { error, type RequestHandler } from '@sveltejs/kit'; +import { wgClients } from '$lib/server/db/schema'; +import { db } from '$lib/server/db'; +import { eq } from 'drizzle-orm'; + +export const GET: RequestHandler = async (event) => { + if (!event.locals.user) { + return error(401, 'Unauthorized'); + } + + const clients = await findClients(event.locals.user.id); + return new Response( + JSON.stringify({ + clients, + }) + ); +}; + +async function findClients(userId: string) { + return db.query.wgClients.findMany({ + where: eq(wgClients.userId, userId), + with: { + ipAllocation: true + } + }); +} + +export type Clients = Awaited>; diff --git a/src/routes/clients/+page.svelte b/src/routes/clients/+page.svelte new file mode 100644 index 0000000..a8afd60 --- /dev/null +++ b/src/routes/clients/+page.svelte @@ -0,0 +1,34 @@ + + + + Clients + + + + + Name + Public Key + Private Key + Pre-Shared Key + IP Allocation + + + {#each data.clients as client} + + {client.name} + {client.publicKey} + {client.privateKey} + {client.preSharedKey} + + {client.ipAllocation.id} + + + {/each} + + diff --git a/src/routes/clients/+page.ts b/src/routes/clients/+page.ts new file mode 100644 index 0000000..643cd24 --- /dev/null +++ b/src/routes/clients/+page.ts @@ -0,0 +1,9 @@ +import type { PageLoad } from './$types'; +import type { Clients } from '../api/clients/+server'; + +export const load: PageLoad = async ({ fetch }) => { + const res = await fetch('/api/clients'); + const { clients } = await res.json() as { clients: Clients }; + + return { clients }; +};