diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 79545cf2..212b162a 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -193,7 +193,8 @@ }, "interface": { "cidr": "CIDR", - "device": "Device" + "device": "Device", + "cidrValid": "CIDR must be valid" }, "otl": "One Time link", "stringMalformed": "String is malformed", diff --git a/src/server/database/repositories/interface/service.ts b/src/server/database/repositories/interface/service.ts index 9edfb96b..ac191975 100644 --- a/src/server/database/repositories/interface/service.ts +++ b/src/server/database/repositories/interface/service.ts @@ -1,4 +1,3 @@ -import isCidr from 'is-cidr'; import { eq, sql } from 'drizzle-orm'; import { parseCidr } from 'cidr-tools'; import { wgInterface } from './schema'; @@ -58,10 +57,18 @@ export class InterfaceService { } updateCidr(data: InterfaceCidrUpdateType) { - if (!isCidr(data.ipv4Cidr) || !isCidr(data.ipv6Cidr)) { - throw new Error('Invalid CIDR'); - } return this.#db.transaction(async (tx) => { + const oldCidr = await tx.query.wgInterface + .findFirst({ + where: eq(wgInterface.name, 'wg0'), + columns: { ipv4Cidr: true, ipv6Cidr: true }, + }) + .execute(); + + if (!oldCidr) { + throw new Error('Interface not found'); + } + await tx .update(wgInterface) .set(data) @@ -74,8 +81,17 @@ export class InterfaceService { // TODO: optimize const clients = await tx.query.client.findMany().execute(); - const nextIpv4 = nextIP(4, parseCidr(data.ipv4Cidr), clients); - const nextIpv6 = nextIP(6, parseCidr(data.ipv6Cidr), clients); + // only calculate ip if cidr has changed + + let nextIpv4 = client.ipv4Address; + if (data.ipv4Cidr !== oldCidr.ipv4Cidr) { + nextIpv4 = nextIP(4, parseCidr(data.ipv4Cidr), clients); + } + + let nextIpv6 = client.ipv6Address; + if (data.ipv6Cidr !== oldCidr.ipv6Cidr) { + nextIpv6 = nextIP(6, parseCidr(data.ipv6Cidr), clients); + } await tx .update(clientSchema) diff --git a/src/server/database/repositories/interface/types.ts b/src/server/database/repositories/interface/types.ts index d109fb96..5d604c1e 100644 --- a/src/server/database/repositories/interface/types.ts +++ b/src/server/database/repositories/interface/types.ts @@ -1,5 +1,6 @@ import type { InferSelectModel } from 'drizzle-orm'; import z from 'zod'; +import isCidr from 'is-cidr'; import type { wgInterface } from './schema'; export type InterfaceType = InferSelectModel; @@ -22,6 +23,7 @@ const device = z const cidr = z .string({ message: t('zod.interface.cidr') }) .min(1, { message: t('zod.interface.cidr') }) + .refine((value) => isCidr(value), { message: t('zod.interface.cidrValid') }) .pipe(safeStringRefine); export const InterfaceUpdateSchema = schemaForType()(