Merge branch 'clients-user' into refactor/separate-tables

This commit is contained in:
Fred KISSIE
2025-12-03 17:01:50 +01:00
committed by GitHub
50 changed files with 1945 additions and 562 deletions

View File

@@ -17,17 +17,15 @@ import { eq, and, ne } from "drizzle-orm";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import { updatePeerData, updateTargets } from "@server/routers/client/targets";
import {
updateRemoteSubnets,
updateTargets
} from "@server/routers/client/targets";
import {
generateAliasConfig,
generateRemoteSubnets,
generateSubnetProxyTargets
} from "@server/lib/ip";
import {
getClientSiteResourceAccess,
rebuildClientAssociations
rebuildClientAssociationsFromSiteResource
} from "@server/lib/rebuildClientAssociations";
const updateSiteResourceParamsSchema = z.strictObject({
@@ -51,7 +49,44 @@ const updateSiteResourceSchema = z
roleIds: z.array(z.int()),
clientIds: z.array(z.int())
})
.strict();
.strict()
.refine(
(data) => {
if (data.mode === "host" && data.destination) {
// Check if it's a valid IP address using zod (v4 or v6)
const isValidIP = z
.union([z.ipv4(), z.ipv6()])
.safeParse(data.destination).success;
// Check if it's a valid domain (hostname pattern, TLD not required)
const domainRegex =
/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
const isValidDomain = domainRegex.test(data.destination);
return isValidIP || isValidDomain;
}
return true;
},
{
message:
"Destination must be a valid IP address or domain name for host mode"
}
)
.refine(
(data) => {
if (data.mode === "cidr" && data.destination) {
// Check if it's a valid CIDR (v4 or v6)
const isValidCIDR = z
.union([z.cidrv4(), z.cidrv6()])
.safeParse(data.destination).success;
return isValidCIDR;
}
return true;
},
{
message: "Destination must be a valid CIDR notation for cidr mode"
}
);
export type UpdateSiteResourceBody = z.infer<typeof updateSiteResourceSchema>;
export type UpdateSiteResourceResponse = SiteResource;
@@ -226,16 +261,20 @@ export async function updateSiteResource(
);
}
const { mergedAllClients } = await rebuildClientAssociations(
existingSiteResource, // we want to rebuild based on the existing resource then we will apply the change to the destination below
trx
);
const { mergedAllClients } =
await rebuildClientAssociationsFromSiteResource(
existingSiteResource, // we want to rebuild based on the existing resource then we will apply the change to the destination below
trx
);
// after everything is rebuilt above we still need to update the targets and remote subnets if the destination changed
if (
const destinationChanged =
existingSiteResource.destination !==
updatedSiteResource.destination
) {
updatedSiteResource.destination;
const aliasChanged =
existingSiteResource.alias !== updatedSiteResource.alias;
if (destinationChanged || aliasChanged) {
const [newt] = await trx
.select()
.from(newts)
@@ -248,25 +287,28 @@ export async function updateSiteResource(
);
}
const oldTargets = generateSubnetProxyTargets(
existingSiteResource,
mergedAllClients
);
const newTargets = generateSubnetProxyTargets(
updatedSiteResource,
mergedAllClients
);
// Only update targets on newt if destination changed
if (destinationChanged) {
const oldTargets = generateSubnetProxyTargets(
existingSiteResource,
mergedAllClients
);
const newTargets = generateSubnetProxyTargets(
updatedSiteResource,
mergedAllClients
);
await updateTargets(newt.newtId, {
oldTargets: oldTargets,
newTargets: newTargets
});
await updateTargets(newt.newtId, {
oldTargets: oldTargets,
newTargets: newTargets
});
}
const olmJobs: Promise<void>[] = [];
for (const client of mergedAllClients) {
// we also need to update the remote subnets on the olms for each client that has access to this site
olmJobs.push(
updateRemoteSubnets(
updatePeerData(
client.clientId,
updatedSiteResource.siteId,
{
@@ -276,8 +318,22 @@ export async function updateSiteResource(
newRemoteSubnets: generateRemoteSubnets([
updatedSiteResource
])
},
{
oldAliases: generateAliasConfig([
existingSiteResource
]),
newAliases: generateAliasConfig([
updatedSiteResource
])
}
)
).catch((error) => {
// this is okay because sometimes the olm is not online to receive the update or associated with the client yet
logger.warn(
`Error updating peer data for client ${client.clientId}:`,
error
);
})
);
}