From e9368c05f8a895fe9bcb3d9886dc91ad1757acea Mon Sep 17 00:00:00 2001 From: Bernd Storath <999999bst@gmail.com> Date: Mon, 14 Oct 2024 14:27:17 +0200 Subject: [PATCH] add client page, move api routes --- src/app/components/Client/Address4.vue | 60 ---------- src/app/components/Client/Delete.vue | 17 --- src/app/components/Client/ExpireDate.vue | 91 -------------- src/app/components/Client/Name.vue | 65 ---------- src/app/components/ClientCard/Address4.vue | 11 ++ .../{Client => ClientCard}/Avatar.vue | 0 .../{Client => ClientCard}/Charts.vue | 0 .../Client.vue => ClientCard/ClientCard.vue} | 28 ++--- .../{Client => ClientCard}/Config.vue | 2 +- src/app/components/ClientCard/Edit.vue | 14 +++ src/app/components/ClientCard/ExpireDate.vue | 25 ++++ .../{Client => ClientCard}/InlineTransfer.vue | 0 .../{Client => ClientCard}/LastSeen.vue | 0 src/app/components/ClientCard/Name.vue | 16 +++ .../{Client => ClientCard}/OneTimeLink.vue | 0 .../{Client => ClientCard}/OneTimeLinkBtn.vue | 0 .../{Client => ClientCard}/QRCode.vue | 4 +- .../{Client => ClientCard}/Switch.vue | 0 .../{Client => ClientCard}/Transfer.vue | 0 src/app/components/Clients/Clients.vue | 2 +- src/app/pages/clients/[id].vue | 112 ++++++++++++++++++ src/app/utils/api.ts | 20 ++-- src/server/api/admin/migration.post.ts | 50 -------- .../client/[clientId]/address4.put.ts | 0 .../client/[clientId]/configuration.get.ts | 0 .../client/[clientId]/disable.post.ts | 0 .../client/[clientId]/enable.post.ts | 0 .../client/[clientId]/expireDate.put.ts | 0 .../[clientId]/generateOneTimeLink.post.ts | 0 .../client/[clientId]/index.delete.ts | 0 src/server/api/client/[clientId]/index.get.ts | 7 ++ .../client/[clientId]/name.put.ts | 0 .../client/[clientId]/qrcode.svg.get.ts | 0 .../api/{wireguard => }/client/index.get.ts | 0 .../api/{wireguard => }/client/index.post.ts | 0 src/server/api/setup/migration.post.ts | 83 +++++++++++++ src/server/utils/config.ts | 71 ----------- 37 files changed, 295 insertions(+), 383 deletions(-) delete mode 100644 src/app/components/Client/Address4.vue delete mode 100644 src/app/components/Client/Delete.vue delete mode 100644 src/app/components/Client/ExpireDate.vue delete mode 100644 src/app/components/Client/Name.vue create mode 100644 src/app/components/ClientCard/Address4.vue rename src/app/components/{Client => ClientCard}/Avatar.vue (100%) rename src/app/components/{Client => ClientCard}/Charts.vue (100%) rename src/app/components/{Client/Client.vue => ClientCard/ClientCard.vue} (64%) rename src/app/components/{Client => ClientCard}/Config.vue (91%) create mode 100644 src/app/components/ClientCard/Edit.vue create mode 100644 src/app/components/ClientCard/ExpireDate.vue rename src/app/components/{Client => ClientCard}/InlineTransfer.vue (100%) rename src/app/components/{Client => ClientCard}/LastSeen.vue (100%) create mode 100644 src/app/components/ClientCard/Name.vue rename src/app/components/{Client => ClientCard}/OneTimeLink.vue (100%) rename src/app/components/{Client => ClientCard}/OneTimeLinkBtn.vue (100%) rename src/app/components/{Client => ClientCard}/QRCode.vue (86%) rename src/app/components/{Client => ClientCard}/Switch.vue (100%) rename src/app/components/{Client => ClientCard}/Transfer.vue (100%) create mode 100644 src/app/pages/clients/[id].vue delete mode 100644 src/server/api/admin/migration.post.ts rename src/server/api/{wireguard => }/client/[clientId]/address4.put.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/configuration.get.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/disable.post.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/enable.post.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/expireDate.put.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/generateOneTimeLink.post.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/index.delete.ts (100%) create mode 100644 src/server/api/client/[clientId]/index.get.ts rename src/server/api/{wireguard => }/client/[clientId]/name.put.ts (100%) rename src/server/api/{wireguard => }/client/[clientId]/qrcode.svg.get.ts (100%) rename src/server/api/{wireguard => }/client/index.get.ts (100%) rename src/server/api/{wireguard => }/client/index.post.ts (100%) create mode 100644 src/server/api/setup/migration.post.ts diff --git a/src/app/components/Client/Address4.vue b/src/app/components/Client/Address4.vue deleted file mode 100644 index e4cdfde5..00000000 --- a/src/app/components/Client/Address4.vue +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/src/app/components/Client/Delete.vue b/src/app/components/Client/Delete.vue deleted file mode 100644 index d0e962e0..00000000 --- a/src/app/components/Client/Delete.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/app/components/Client/ExpireDate.vue b/src/app/components/Client/ExpireDate.vue deleted file mode 100644 index c36f4a58..00000000 --- a/src/app/components/Client/ExpireDate.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - diff --git a/src/app/components/Client/Name.vue b/src/app/components/Client/Name.vue deleted file mode 100644 index 360f46a5..00000000 --- a/src/app/components/Client/Name.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/src/app/components/ClientCard/Address4.vue b/src/app/components/ClientCard/Address4.vue new file mode 100644 index 00000000..3865bf3d --- /dev/null +++ b/src/app/components/ClientCard/Address4.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/app/components/Client/Avatar.vue b/src/app/components/ClientCard/Avatar.vue similarity index 100% rename from src/app/components/Client/Avatar.vue rename to src/app/components/ClientCard/Avatar.vue diff --git a/src/app/components/Client/Charts.vue b/src/app/components/ClientCard/Charts.vue similarity index 100% rename from src/app/components/Client/Charts.vue rename to src/app/components/ClientCard/Charts.vue diff --git a/src/app/components/Client/Client.vue b/src/app/components/ClientCard/ClientCard.vue similarity index 64% rename from src/app/components/Client/Client.vue rename to src/app/components/ClientCard/ClientCard.vue index b5cecb7c..7d6f46d5 100644 --- a/src/app/components/Client/Client.vue +++ b/src/app/components/ClientCard/ClientCard.vue @@ -1,26 +1,26 @@ diff --git a/src/app/pages/clients/[id].vue b/src/app/pages/clients/[id].vue new file mode 100644 index 00000000..9c7f2325 --- /dev/null +++ b/src/app/pages/clients/[id].vue @@ -0,0 +1,112 @@ + + + diff --git a/src/app/utils/api.ts b/src/app/utils/api.ts index 0dda4d85..e4639cc6 100644 --- a/src/app/utils/api.ts +++ b/src/app/utils/api.ts @@ -27,7 +27,7 @@ class API { } async getClients() { - return useFetch('/api/wireguard/client', { + return useFetch('/api/client', { method: 'get', }); } @@ -39,32 +39,32 @@ class API { name: string; expireDate: string | null; }) { - return $fetch('/api/wireguard/client', { + return $fetch('/api/client', { method: 'post', body: { name, expireDate }, }); } async deleteClient({ clientId }: { clientId: string }) { - return $fetch(`/api/wireguard/client/${clientId}`, { + return $fetch(`/api/client/${clientId}`, { method: 'delete', }); } async showOneTimeLink({ clientId }: { clientId: string }) { - return $fetch(`/api/wireguard/client/${clientId}/generateOneTimeLink`, { + return $fetch(`/api/client/${clientId}/generateOneTimeLink`, { method: 'post', }); } async enableClient({ clientId }: { clientId: string }) { - return $fetch(`/api/wireguard/client/${clientId}/enable`, { + return $fetch(`/api/client/${clientId}/enable`, { method: 'post', }); } async disableClient({ clientId }: { clientId: string }) { - return $fetch(`/api/wireguard/client/${clientId}/disable`, { + return $fetch(`/api/client/${clientId}/disable`, { method: 'post', }); } @@ -76,7 +76,7 @@ class API { clientId: string; name: string; }) { - return $fetch(`/api/wireguard/client/${clientId}/name`, { + return $fetch(`/api/client/${clientId}/name`, { method: 'put', body: { name }, }); @@ -89,7 +89,7 @@ class API { clientId: string; address4: string; }) { - return $fetch(`/api/wireguard/client/${clientId}/address4`, { + return $fetch(`/api/client/${clientId}/address4`, { method: 'put', body: { address4 }, }); @@ -102,7 +102,7 @@ class API { clientId: string; expireDate: string | null; }) { - return $fetch(`/api/wireguard/client/${clientId}/expireDate`, { + return $fetch(`/api/client/${clientId}/expireDate`, { method: 'put', body: { expireDate }, }); @@ -145,7 +145,7 @@ class API { } async setupMigration({ file }: { file: string }) { - return $fetch('/api/admin/migration', { + return $fetch('/api/setup/migration', { method: 'post', body: { file }, }); diff --git a/src/server/api/admin/migration.post.ts b/src/server/api/admin/migration.post.ts deleted file mode 100644 index b112c004..00000000 --- a/src/server/api/admin/migration.post.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { parseCidr } from 'cidr-tools'; -import { stringifyIp } from 'ip-bigint'; -import { z } from 'zod'; - -// TODO: check what are missing -const clientSchema = z.object({ - id: z.string(), - name: z.string(), - address: z.string(), - privateKey: z.string(), - publicKey: z.string(), - preSharedKey: z.string(), - createdAt: z.string(), - updatedAt: z.string(), - enabled: z.boolean(), -}); - -const oldConfigSchema = z.object({ - server: z.object({ - privateKey: z.string(), - publicKey: z.string(), - address: z.string(), - }), - clients: z.record(z.string(), clientSchema), -}); - -export default defineEventHandler(async (event) => { - const { file } = await readValidatedBody(event, validateZod(fileType, event)); - const file_ = await oldConfigSchema.parseAsync(JSON.parse(file)); - - for (const [_, value] of Object.entries(file_.clients)) { - // remove the unused field - const { address: _, ...filterValue } = value; - const cidr4 = parseCidr(value.address); - const address4 = stringifyIp({ number: cidr4.start + 0n, version: 4 }); - - await Database.client.create({ - ...filterValue, - address4, - address6: '', - expiresAt: null, - allowedIPs: ['0.0.0.0/0', '::/0'], - oneTimeLink: null, - serverAllowedIPs: [], - persistentKeepalive: 0, - }); - } - - return { success: true }; -}); diff --git a/src/server/api/wireguard/client/[clientId]/address4.put.ts b/src/server/api/client/[clientId]/address4.put.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/address4.put.ts rename to src/server/api/client/[clientId]/address4.put.ts diff --git a/src/server/api/wireguard/client/[clientId]/configuration.get.ts b/src/server/api/client/[clientId]/configuration.get.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/configuration.get.ts rename to src/server/api/client/[clientId]/configuration.get.ts diff --git a/src/server/api/wireguard/client/[clientId]/disable.post.ts b/src/server/api/client/[clientId]/disable.post.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/disable.post.ts rename to src/server/api/client/[clientId]/disable.post.ts diff --git a/src/server/api/wireguard/client/[clientId]/enable.post.ts b/src/server/api/client/[clientId]/enable.post.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/enable.post.ts rename to src/server/api/client/[clientId]/enable.post.ts diff --git a/src/server/api/wireguard/client/[clientId]/expireDate.put.ts b/src/server/api/client/[clientId]/expireDate.put.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/expireDate.put.ts rename to src/server/api/client/[clientId]/expireDate.put.ts diff --git a/src/server/api/wireguard/client/[clientId]/generateOneTimeLink.post.ts b/src/server/api/client/[clientId]/generateOneTimeLink.post.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/generateOneTimeLink.post.ts rename to src/server/api/client/[clientId]/generateOneTimeLink.post.ts diff --git a/src/server/api/wireguard/client/[clientId]/index.delete.ts b/src/server/api/client/[clientId]/index.delete.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/index.delete.ts rename to src/server/api/client/[clientId]/index.delete.ts diff --git a/src/server/api/client/[clientId]/index.get.ts b/src/server/api/client/[clientId]/index.get.ts new file mode 100644 index 00000000..e5a2ca8d --- /dev/null +++ b/src/server/api/client/[clientId]/index.get.ts @@ -0,0 +1,7 @@ +export default defineEventHandler(async (event) => { + const { clientId } = await getValidatedRouterParams( + event, + validateZod(clientIdType) + ); + return WireGuard.getClient({ clientId }); +}); diff --git a/src/server/api/wireguard/client/[clientId]/name.put.ts b/src/server/api/client/[clientId]/name.put.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/name.put.ts rename to src/server/api/client/[clientId]/name.put.ts diff --git a/src/server/api/wireguard/client/[clientId]/qrcode.svg.get.ts b/src/server/api/client/[clientId]/qrcode.svg.get.ts similarity index 100% rename from src/server/api/wireguard/client/[clientId]/qrcode.svg.get.ts rename to src/server/api/client/[clientId]/qrcode.svg.get.ts diff --git a/src/server/api/wireguard/client/index.get.ts b/src/server/api/client/index.get.ts similarity index 100% rename from src/server/api/wireguard/client/index.get.ts rename to src/server/api/client/index.get.ts diff --git a/src/server/api/wireguard/client/index.post.ts b/src/server/api/client/index.post.ts similarity index 100% rename from src/server/api/wireguard/client/index.post.ts rename to src/server/api/client/index.post.ts diff --git a/src/server/api/setup/migration.post.ts b/src/server/api/setup/migration.post.ts new file mode 100644 index 00000000..53b18c22 --- /dev/null +++ b/src/server/api/setup/migration.post.ts @@ -0,0 +1,83 @@ +import { parseCidr } from 'cidr-tools'; +import { stringifyIp } from 'ip-bigint'; +import { z } from 'zod'; +import type { Database } from '~~/services/database/repositories/database'; + +export default defineEventHandler(async (event) => { + const { file } = await readValidatedBody(event, validateZod(fileType, event)); + const setupDone = await Database.setup.done(); + if (setupDone) { + throw createError({ + statusCode: 400, + statusMessage: 'Invalid state', + }); + } + + const schema = z.object({ + server: z.object({ + privateKey: z.string(), + publicKey: z.string(), + address: z.string(), + }), + clients: z.record( + z.string(), + z.object({ + name: z.string(), + address: z.string(), + privateKey: z.string(), + publicKey: z.string(), + preSharedKey: z.string(), + createdAt: z.string(), + updatedAt: z.string(), + enabled: z.boolean(), + }) + ), + }); + const res = await schema.safeParseAsync(JSON.parse(file)); + if (!res.success) { + throw new Error('Invalid Config'); + } + const system = await Database.system.get(); + const oldConfig = res.data; + const oldCidr = parseCidr(oldConfig.server.address + '/24'); + const db = { + system: { + ...system, + // TODO: migrate to db calls + interface: { + ...system.interface, + address4: oldConfig.server.address, + privateKey: oldConfig.server.privateKey, + publicKey: oldConfig.server.publicKey, + }, + userConfig: { + ...system.userConfig, + address4Range: + stringifyIp({ number: oldCidr.start, version: 4 }) + '/24', + }, + } satisfies Partial, + clients: {} as Database['clients'], + }; + + for (const [oldId, oldClient] of Object.entries(oldConfig.clients)) { + const address6 = nextIPv6(db.system, db.clients); + + await Database.client.create({ + id: oldId, + address4: oldClient.address, + enabled: oldClient.enabled, + name: oldClient.name, + preSharedKey: oldClient.preSharedKey, + privateKey: oldClient.privateKey, + publicKey: oldClient.publicKey, + expiresAt: null, + oneTimeLink: null, + allowedIPs: db.system.userConfig.allowedIps, + serverAllowedIPs: [], + persistentKeepalive: 0, + address6: address6, + }); + } + + return { success: true }; +}); diff --git a/src/server/utils/config.ts b/src/server/utils/config.ts index 65f4da3b..5636e59b 100644 --- a/src/server/utils/config.ts +++ b/src/server/utils/config.ts @@ -1,77 +1,6 @@ import debug from 'debug'; import packageJson from '@@/package.json'; -import { z } from 'zod'; -import type { Database } from '~~/services/database/repositories/database'; -import { parseCidr } from 'cidr-tools'; -import { stringifyIp } from 'ip-bigint'; export const RELEASE = 'v' + packageJson.version; export const SERVER_DEBUG = debug('Server'); - -export async function migrateConfig(input: unknown) { - const schema = z.object({ - server: z.object({ - privateKey: z.string(), - publicKey: z.string(), - address: z.string(), - }), - clients: z.record( - z.string(), - z.object({ - name: z.string(), - address: z.string(), - privateKey: z.string(), - publicKey: z.string(), - preSharedKey: z.string(), - createdAt: z.string(), - updatedAt: z.string(), - enabled: z.boolean(), - }) - ), - }); - const res = await schema.safeParseAsync(input); - if (!res.success) { - throw new Error('Invalid Config'); - } - const system = await Database.system.get(); - const oldConfig = res.data; - const oldCidr = parseCidr(oldConfig.server.address + '/24'); - const db = { - system: { - ...system, - interface: { - ...system.interface, - address4: oldConfig.server.address, - privateKey: oldConfig.server.privateKey, - publicKey: oldConfig.server.publicKey, - }, - userConfig: { - ...system.userConfig, - address4Range: - stringifyIp({ number: oldCidr.start, version: 4 }) + '/24', - }, - } satisfies Partial, - clients: {} as Database['clients'], - }; - for (const [oldId, oldClient] of Object.entries(oldConfig.clients)) { - const address6 = nextIPv6(db.system, db.clients); - db.clients[oldId] = { - id: oldId, - address4: oldClient.address, - createdAt: oldClient.createdAt, - enabled: oldClient.enabled, - name: oldClient.name, - preSharedKey: oldClient.preSharedKey, - privateKey: oldClient.privateKey, - publicKey: oldClient.publicKey, - updatedAt: oldClient.updatedAt, - expiresAt: null, - oneTimeLink: null, - allowedIPs: db.system.userConfig.allowedIps, - serverAllowedIPs: [], - persistentKeepalive: 0, - address6: address6, - }; - } -}