diff --git a/.env.example b/.env.example
index 54809c2..d3c3a69 100644
--- a/.env.example
+++ b/.env.example
@@ -3,6 +3,8 @@ AUTH_DOMAIN=auth.lab.cazzzer.com
AUTH_CLIENT_ID=
AUTH_CLIENT_SECRET=
AUTH_REDIRECT_URI=http://localhost:5173/auth/authentik/callback
+
OPNSENSE_API_URL=https://opnsense.home
OPNSENSE_API_KEY=
OPNSENSE_API_SECRET=
+OPNSENSE_WG_IFNAME=wg2
diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte
new file mode 100644
index 0000000..e8817f4
--- /dev/null
+++ b/src/lib/components/ui/badge/badge.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts
new file mode 100644
index 0000000..59c0767
--- /dev/null
+++ b/src/lib/components/ui/badge/index.ts
@@ -0,0 +1,21 @@
+import { type VariantProps, tv } from "tailwind-variants";
+export { default as Badge } from "./badge.svelte";
+
+export const badgeVariants = tv({
+ base: "focus:ring-ring inline-flex select-none items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/80 border-transparent",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent",
+ outline: "text-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+});
+
+export type Variant = VariantProps["variant"];
diff --git a/src/lib/opnsense/wg.ts b/src/lib/opnsense/wg.ts
index 59872fd..b463f58 100644
--- a/src/lib/opnsense/wg.ts
+++ b/src/lib/opnsense/wg.ts
@@ -12,6 +12,31 @@ export interface PeerRow {
ifname: string;
}
+/**
+ * Sample response from OPNsense WireGuard API
+ * ```json
+ * {
+ * "total": 17,
+ * "rowCount": 7,
+ * "current": 1,
+ * "rows": [
+ * {
+ * "if": "wg0",
+ * "type": "peer",
+ * "public-key": "iJa5JmJbMHNlbEluNwoB2Q8LyrPAfb7S/mluanMcI08=",
+ * "endpoint": "10.17.20.107:42516",
+ * "allowed-ips": "fd00::1/112,10.6.0.3/32",
+ * "latest-handshake": 1729319339,
+ * "transfer-rx": 1052194743,
+ * "transfer-tx": 25203263456,
+ * "persistent-keepalive": "off",
+ * "name": "Yura-TPX13",
+ * "ifname": "wg0"
+ * }
+ * ]
+ * }
+ * ```
+ */
export interface OpnsenseWgPeers {
total: number;
rowCount: number;
@@ -19,38 +44,18 @@ export interface OpnsenseWgPeers {
rows: PeerRow[];
}
-// Sample request to OPNsense WireGuard API
-// const url = 'https://opnsense.home/api/wireguard/service/show';
-// const options = {
-// method: 'POST',
-// headers: {
-// Authorization: 'Basic ...',
-// 'Content-Type': 'application/json',
-// Accept: 'application/json',
-// 'content-type': 'application/json'
-// },
-// body: '{"current":1,"rowCount":7,"sort":{},"searchPhrase":"","type":["peer"]}'
-// };
-
-
-// Sample response from OPNsense WireGuard API
-// {
-// "total": 17,
-// "rowCount": 7,
-// "current": 1,
-// "rows": [
-// {
-// "if": "wg0",
-// "type": "peer",
-// "public-key": "iJa5JmJbMHNlbEluNwoB2Q8LyrPAfb7S/mluanMcI08=",
-// "endpoint": "10.17.20.107:42516",
-// "allowed-ips": "fd00::1/112,10.6.0.3/32",
-// "latest-handshake": 1729319339,
-// "transfer-rx": 1052194743,
-// "transfer-tx": 25203263456,
-// "persistent-keepalive": "off",
-// "name": "Yura-TPX13",
-// "ifname": "wg0"
-// }
-// ]
-// }
+/**
+ * Sample request to OPNsense WireGuard API
+ * ```js
+ * const url = 'https://opnsense.home/api/wireguard/service/show';
+ * const options = {
+ * method: 'POST',
+ * headers: {
+ * Authorization: 'Basic ...',
+ * 'Content-Type': 'application/json',
+ * Accept: 'application/json',
+ * },
+ * body: '{"current":1,"rowCount":7,"sort":{},"searchPhrase":"","type":["peer"]}'
+ * };
+ * ```
+ */
diff --git a/src/lib/server/opnsense.ts b/src/lib/server/opnsense.ts
new file mode 100644
index 0000000..58655b0
--- /dev/null
+++ b/src/lib/server/opnsense.ts
@@ -0,0 +1,16 @@
+import { env } from '$env/dynamic/private';
+import assert from 'node:assert';
+import { encodeBasicCredentials } from 'arctic/dist/request';
+import { dev } from '$app/environment';
+
+assert(env.OPNSENSE_API_URL, 'OPNSENSE_API_URL is not set');
+assert(env.OPNSENSE_API_KEY, 'OPNSENSE_API_KEY is not set');
+assert(env.OPNSENSE_API_SECRET, 'OPNSENSE_API_SECRET is not set');
+assert(env.OPNSENSE_WG_IFNAME, 'OPNSENSE_WG_IFNAME is not set');
+
+export const opnsenseUrl = env.OPNSENSE_API_URL;
+export const opnsenseAuth = "Basic " + encodeBasicCredentials(env.OPNSENSE_API_KEY, env.OPNSENSE_API_SECRET);
+export const opnsenseIfname = env.OPNSENSE_WG_IFNAME;
+
+// unset secret for security
+if (!dev) env.OPNSENSE_API_SECRET = "";
diff --git a/src/routes/api/connections/+server.ts b/src/routes/api/connections/+server.ts
index 8644078..4b2e343 100644
--- a/src/routes/api/connections/+server.ts
+++ b/src/routes/api/connections/+server.ts
@@ -1,14 +1,14 @@
import { error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
-import { env } from '$env/dynamic/private';
+import { opnsenseAuth, opnsenseIfname, opnsenseUrl } from '$lib/server/opnsense';
import type { OpnsenseWgPeers } from '$lib/opnsense/wg';
-export const GET: RequestHandler = async ({ url }) => {
- const apiUrl = `${env.OPNSENSE_API_URL}/api/wireguard/service/show`;
+export const GET: RequestHandler = async () => {
+ const apiUrl = `${opnsenseUrl}/api/wireguard/service/show`;
const options: RequestInit = {
method: 'POST',
headers: {
- Authorization: `Basic ${Buffer.from(`${env.OPNSENSE_API_KEY}:${env.OPNSENSE_API_SECRET}`).toString('base64')}`,
+ Authorization: opnsenseAuth,
Accept: 'application/json',
'Content-Type': 'application/json',
},
@@ -24,6 +24,7 @@ export const GET: RequestHandler = async ({ url }) => {
const res = await fetch(apiUrl, options);
const peers = await res.json() as OpnsenseWgPeers;
+ peers.rows = peers.rows.filter(peer => peer['latest-handshake'] && peer.ifname === opnsenseIfname)
if (!peers) {
error(500, "Error getting info from OPNsense API");
diff --git a/src/routes/connections/+page.svelte b/src/routes/connections/+page.svelte
index 77a617c..f447f5e 100644
--- a/src/routes/connections/+page.svelte
+++ b/src/routes/connections/+page.svelte
@@ -1,13 +1,10 @@