Standardize db rebuildClientAssociationsFromClient

This commit is contained in:
Owen
2026-06-23 17:14:29 -04:00
parent c11d24e10a
commit 7731849a2f
14 changed files with 336 additions and 588 deletions
+25 -158
View File
@@ -3,7 +3,6 @@ import {
newts, newts,
blueprints, blueprints,
Blueprint, Blueprint,
Site,
siteResources, siteResources,
roleSiteResources, roleSiteResources,
userSiteResources, userSiteResources,
@@ -60,30 +59,26 @@ export async function applyBlueprint({
const config: Config = validationResult.data; const config: Config = validationResult.data;
let proxyResourcesResults: PublicResourcesResults = []; let publicResourcesResults: PublicResourcesResults = [];
let clientResourcesResults: ClientResourcesResults = []; let privateResourcesResults: ClientResourcesResults = [];
await db.transaction(async (trx) => { await db.transaction(async (trx) => {
await updateResourcePolicies(orgId, config, trx); await updateResourcePolicies(orgId, config, trx);
proxyResourcesResults = await updatePublicResources( publicResourcesResults = await updatePublicResources(
orgId, orgId,
config, config,
trx, trx,
siteId siteId
); );
clientResourcesResults = await updatePrivateResources( privateResourcesResults = await updatePrivateResources(
orgId, orgId,
config, config,
trx, trx,
siteId siteId
); );
logger.debug(
`Successfully updated proxy resources for org ${orgId}: ${JSON.stringify(proxyResourcesResults)}`
);
// We need to update the targets on the newts from the successfully updated information // We need to update the targets on the newts from the successfully updated information
for (const result of proxyResourcesResults) { for (const result of publicResourcesResults) {
for (const target of result.targetsToUpdate) { for (const target of result.targetsToUpdate) {
const [site] = await trx const [site] = await trx
.select() .select()
@@ -136,166 +131,38 @@ export async function applyBlueprint({
} }
logger.debug( logger.debug(
`Successfully updated client resources for org ${orgId}: ${JSON.stringify(clientResourcesResults)}` `Successfully updated public resources for org ${orgId}: ${JSON.stringify(publicResourcesResults)}`
); );
// We need to update the targets on the newts from the successfully updated information // We need to update the targets on the newts from the successfully updated information
for (const result of clientResourcesResults) { for (const result of privateResourcesResults) {
if ( rebuildClientAssociationsFromSiteResource(
result.oldSiteResource && result.newSiteResource
JSON.stringify(result.newSites?.sort()) !== ).catch((e) => {
JSON.stringify(result.oldSites?.sort()) logger.error(
) { `Failed to rebuild client associations for site resource ${result.newSiteResource.siteResourceId}. Error: ${e}`
// query existing associations
const existingRoleIds = await trx
.select()
.from(roleSiteResources)
.where(
eq(
roleSiteResources.siteResourceId,
result.oldSiteResource.siteResourceId
)
)
.then((rows) => rows.map((row) => row.roleId));
const existingUserIds = await trx
.select()
.from(userSiteResources)
.where(
eq(
userSiteResources.siteResourceId,
result.oldSiteResource.siteResourceId
)
)
.then((rows) => rows.map((row) => row.userId));
const existingClientIds = await trx
.select()
.from(clientSiteResources)
.where(
eq(
clientSiteResources.siteResourceId,
result.oldSiteResource.siteResourceId
)
)
.then((rows) => rows.map((row) => row.clientId));
// delete the existing site resource
await trx
.delete(siteResources)
.where(
and(
eq(
siteResources.siteResourceId,
result.oldSiteResource.siteResourceId
)
)
); );
});
await rebuildClientAssociationsFromSiteResource( handleMessagingForUpdatedSiteResource(
result.oldSiteResource,
trx
);
const [insertedSiteResource] = await trx
.insert(siteResources)
.values({
...result.newSiteResource
})
.returning();
// wait some time to allow for messages to be handled
await new Promise((resolve) => setTimeout(resolve, 750));
//////////////////// update the associations ////////////////////
if (existingRoleIds.length > 0) {
await trx.insert(roleSiteResources).values(
existingRoleIds.map((roleId) => ({
roleId,
siteResourceId:
insertedSiteResource!.siteResourceId
}))
);
}
if (existingUserIds.length > 0) {
await trx.insert(userSiteResources).values(
existingUserIds.map((userId) => ({
userId,
siteResourceId:
insertedSiteResource!.siteResourceId
}))
);
}
if (existingClientIds.length > 0) {
await trx.insert(clientSiteResources).values(
existingClientIds.map((clientId) => ({
clientId,
siteResourceId:
insertedSiteResource!.siteResourceId
}))
);
}
await rebuildClientAssociationsFromSiteResource(
insertedSiteResource,
trx
);
} else {
let good = true;
for (const newSite of result.newSites) {
const [site] = await trx
.select()
.from(sites)
.innerJoin(newts, eq(sites.siteId, newts.siteId))
.where(
and(
eq(sites.siteId, newSite.siteId),
eq(sites.orgId, orgId),
eq(sites.type, "newt"),
isNotNull(sites.pubKey)
)
)
.limit(1);
if (!site) {
logger.debug(
`No newt sites found for client resource ${result.newSiteResource.siteResourceId}, skipping target update`
);
good = false;
break;
}
logger.debug(
`Updating client resource ${result.newSiteResource.siteResourceId} on site ${newSite.siteId}`
);
}
if (!good) {
continue;
}
await handleMessagingForUpdatedSiteResource(
result.oldSiteResource, result.oldSiteResource,
result.newSiteResource, result.newSiteResource,
result.newSites.map((site) => ({ result.oldSites.map((site) => ({
// only need to run this on the old sites because the new sites are added above
siteId: site.siteId, siteId: site.siteId,
orgId: result.newSiteResource.orgId orgId: result.newSiteResource.orgId
})), }))
trx ).catch((err) => {
logger.error(
`Error handling messaging for updated site resource ${result.newSiteResource.siteResourceId}:`,
err
); );
});
} }
// await addClientTargets( logger.debug(
// site.newt.newtId, `Successfully updated private resources for org ${orgId}: ${JSON.stringify(privateResourcesResults)}`
// result.resource.destination, );
// result.resource.destinationPort,
// result.resource.protocol,
// result.resource.proxyPort
// );
}
}); });
blueprintSucceeded = true; blueprintSucceeded = true;
+3 -6
View File
@@ -160,9 +160,9 @@ export async function getClientSiteResourceAccess(
} }
export async function rebuildClientAssociationsFromSiteResource( export async function rebuildClientAssociationsFromSiteResource(
siteResource: SiteResource, siteResource: SiteResource
trx: Transaction | typeof db = db
) { ) {
const trx = primaryDb;
try { try {
return await lockManager.withLock( return await lockManager.withLock(
`rebuild-client-associations:site-resource:${siteResource.siteResourceId}`, `rebuild-client-associations:site-resource:${siteResource.siteResourceId}`,
@@ -2119,10 +2119,7 @@ export function startRebuildQueueProcessor(): void {
return; return;
} }
await rebuildClientAssociationsFromSiteResource( await rebuildClientAssociationsFromSiteResource(siteResource);
siteResource,
primaryDb
);
}, },
onClient: async (clientId: number) => { onClient: async (clientId: number) => {
const [client] = await primaryDb const [client] = await primaryDb
@@ -153,8 +153,12 @@ export async function addClientToSiteResource(
clientId, clientId,
siteResourceId siteResourceId
}); });
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -160,8 +160,12 @@ export async function addRoleToSiteResource(
roleId, roleId,
siteResourceId siteResourceId
}); });
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -129,8 +129,12 @@ export async function addUserToSiteResource(
userId, userId,
siteResourceId siteResourceId
}); });
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -625,15 +625,14 @@ export async function createSiteResource(
// own transaction so it always executes on the primary — avoiding any // own transaction so it always executes on the primary — avoiding any
// replica-lag issues while still allowing the HTTP response to return // replica-lag issues while still allowing the HTTP response to return
// early. // early.
rebuildClientAssociationsFromSiteResource( rebuildClientAssociationsFromSiteResource(newSiteResource!).catch(
newSiteResource!, (err) => {
primaryDb
).catch((err) => {
logger.error( logger.error(
`Error rebuilding client associations for site resource ${newSiteResource!.siteResourceId}:`, `Error rebuilding client associations for site resource ${newSiteResource!.siteResourceId}:`,
err err
); );
}); }
);
return response(res, { return response(res, {
data: newSiteResource, data: newSiteResource,
@@ -88,15 +88,14 @@ export async function deleteSiteResource(
// own transaction so it always executes on the primary — avoiding any // own transaction so it always executes on the primary — avoiding any
// replica-lag issues while still allowing the HTTP response to return // replica-lag issues while still allowing the HTTP response to return
// early. // early.
rebuildClientAssociationsFromSiteResource( rebuildClientAssociationsFromSiteResource(removedSiteResource).catch(
removedSiteResource, (err) => {
primaryDb
).catch((err) => {
logger.error( logger.error(
`Error rebuilding client associations for site resource ${removedSiteResource!.siteResourceId}:`, `Error rebuilding client associations for site resource ${removedSiteResource!.siteResourceId}:`,
err err
); );
}); }
);
logger.info(`Deleted site resource ${siteResourceId}`); logger.info(`Deleted site resource ${siteResourceId}`);
@@ -157,8 +157,12 @@ export async function removeClientFromSiteResource(
eq(clientSiteResources.clientId, clientId) eq(clientSiteResources.clientId, clientId)
) )
); );
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -165,8 +165,12 @@ export async function removeRoleFromSiteResource(
eq(roleSiteResources.roleId, roleId) eq(roleSiteResources.roleId, roleId)
) )
); );
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -135,8 +135,12 @@ export async function removeUserFromSiteResource(
eq(userSiteResources.userId, userId) eq(userSiteResources.userId, userId)
) )
); );
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId} after removing user ${userId}: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -141,8 +141,12 @@ export async function setSiteResourceClients(
})) }))
); );
} }
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -165,8 +165,12 @@ export async function setSiteResourceRoles(
roleIds.map((roleId) => ({ roleId, siteResourceId })) roleIds.map((roleId) => ({ roleId, siteResourceId }))
); );
} }
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
@@ -10,6 +10,7 @@ import { fromError } from "zod-validation-error";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations"; import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations";
import { error } from "node:console";
const setSiteResourceUsersBodySchema = z const setSiteResourceUsersBodySchema = z
.object({ .object({
@@ -120,8 +121,12 @@ export async function setSiteResourceUsers(
userIds.map((userId) => ({ userId, siteResourceId })) userIds.map((userId) => ({ userId, siteResourceId }))
); );
} }
});
await rebuildClientAssociationsFromSiteResource(siteResource, trx); rebuildClientAssociationsFromSiteResource(siteResource).catch((e) => {
logger.error(
`Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
);
}); });
return response(res, { return response(res, {
+106 -257
View File
@@ -12,7 +12,8 @@ import {
sites, sites,
networks, networks,
Transaction, Transaction,
userSiteResources userSiteResources,
primaryDb
} from "@server/db"; } from "@server/db";
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix"; import { TierFeature, tierMatrix } from "@server/lib/billing/tierMatrix";
@@ -474,167 +475,6 @@ export async function updateSiteResource(
let updatedSiteResource: SiteResource | undefined; let updatedSiteResource: SiteResource | undefined;
await db.transaction(async (trx) => { await db.transaction(async (trx) => {
// if the site is changed we need to delete and recreate the resource to avoid complications with the rebuild function otherwise we can just update in place
if (sitesChanged) {
// delete the existing site resource
await trx
.delete(siteResources)
.where(
and(eq(siteResources.siteResourceId, siteResourceId))
);
await rebuildClientAssociationsFromSiteResource(
existingSiteResource,
trx
);
// create the new site resource from the removed one - the ID should stay the same
const [insertedSiteResource] = await trx
.insert(siteResources)
.values({
...existingSiteResource
})
.returning();
const sshPamSet =
isLicensedSshPam &&
(authDaemonPort !== undefined ||
authDaemonMode !== undefined ||
pamMode !== undefined)
? {
...(authDaemonPort !== undefined && {
authDaemonPort
}),
...(authDaemonMode !== undefined && {
authDaemonMode
}),
...(pamMode !== undefined && {
pamMode
})
}
: {};
let tcpPortRangeStringAdjusted = tcpPortRangeString;
if (mode === "http") {
tcpPortRangeStringAdjusted = "443,80";
} else if (mode === "ssh") {
tcpPortRangeStringAdjusted = destinationPort
? destinationPort.toString()
: "22";
}
[updatedSiteResource] = await trx
.update(siteResources)
.set({
name,
niceId,
mode,
scheme,
ssl,
destination,
destinationPort,
enabled,
alias: alias ? alias.trim() : null,
tcpPortRangeString: tcpPortRangeStringAdjusted,
udpPortRangeString:
mode == "http" || mode == "ssh"
? ""
: udpPortRangeString,
disableIcmp:
disableIcmp ||
(mode == "http" || mode == "ssh" ? true : false), // default to true for http resources, otherwise false
domainId,
subdomain: finalSubdomain,
fullDomain,
...sshPamSet
})
.where(
and(
eq(
siteResources.siteResourceId,
insertedSiteResource.siteResourceId
)
)
)
.returning();
if (!updatedSiteResource) {
throw new Error(
"Failed to create updated site resource after site change"
);
}
//////////////////// update the associations ////////////////////
// delete the site - site resources associations
await trx
.delete(siteNetworks)
.where(
eq(
siteNetworks.networkId,
updatedSiteResource.networkId!
)
);
for (const siteId of siteIds) {
await trx.insert(siteNetworks).values({
siteId: siteId,
networkId: updatedSiteResource.networkId!
});
}
const [adminRole] = await trx
.select()
.from(roles)
.where(
and(
eq(roles.isAdmin, true),
eq(roles.orgId, updatedSiteResource.orgId)
)
)
.limit(1);
if (!adminRole) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Admin role not found`
)
);
}
await trx.insert(roleSiteResources).values({
roleId: adminRole.roleId,
siteResourceId: updatedSiteResource.siteResourceId
});
if (roleIds.length > 0) {
await trx.insert(roleSiteResources).values(
roleIds.map((roleId) => ({
roleId,
siteResourceId: updatedSiteResource!.siteResourceId
}))
);
}
if (userIds.length > 0) {
await trx.insert(userSiteResources).values(
userIds.map((userId) => ({
userId,
siteResourceId: updatedSiteResource!.siteResourceId
}))
);
}
if (clientIds.length > 0) {
await trx.insert(clientSiteResources).values(
clientIds.map((clientId) => ({
clientId,
siteResourceId: updatedSiteResource!.siteResourceId
}))
);
}
} else {
// Update the site resource // Update the site resource
const sshPamSet = const sshPamSet =
isLicensedSshPam && isLicensedSshPam &&
@@ -687,9 +527,7 @@ export async function updateSiteResource(
fullDomain, fullDomain,
...sshPamSet ...sshPamSet
}) })
.where( .where(and(eq(siteResources.siteResourceId, siteResourceId)))
and(eq(siteResources.siteResourceId, siteResourceId))
)
.returning(); .returning();
//////////////////// update the associations //////////////////// //////////////////// update the associations ////////////////////
@@ -698,10 +536,7 @@ export async function updateSiteResource(
await trx await trx
.delete(siteNetworks) .delete(siteNetworks)
.where( .where(
eq( eq(siteNetworks.networkId, updatedSiteResource.networkId!)
siteNetworks.networkId,
updatedSiteResource.networkId!
)
); );
for (const siteId of siteIds) { for (const siteId of siteIds) {
@@ -713,9 +548,7 @@ export async function updateSiteResource(
await trx await trx
.delete(clientSiteResources) .delete(clientSiteResources)
.where( .where(eq(clientSiteResources.siteResourceId, siteResourceId));
eq(clientSiteResources.siteResourceId, siteResourceId)
);
if (clientIds.length > 0) { if (clientIds.length > 0) {
await trx.insert(clientSiteResources).values( await trx.insert(clientSiteResources).values(
@@ -728,9 +561,7 @@ export async function updateSiteResource(
await trx await trx
.delete(userSiteResources) .delete(userSiteResources)
.where( .where(eq(userSiteResources.siteResourceId, siteResourceId));
eq(userSiteResources.siteResourceId, siteResourceId)
);
if (userIds.length > 0) { if (userIds.length > 0) {
await trx.insert(userSiteResources).values( await trx.insert(userSiteResources).values(
@@ -756,10 +587,7 @@ export async function updateSiteResource(
if (adminRoleIds.length > 0) { if (adminRoleIds.length > 0) {
await trx.delete(roleSiteResources).where( await trx.delete(roleSiteResources).where(
and( and(
eq( eq(roleSiteResources.siteResourceId, siteResourceId),
roleSiteResources.siteResourceId,
siteResourceId
),
ne(roleSiteResources.roleId, adminRoleIds[0]) // delete all but the admin role ne(roleSiteResources.roleId, adminRoleIds[0]) // delete all but the admin role
) )
); );
@@ -781,38 +609,33 @@ export async function updateSiteResource(
} }
logger.info(`Updated site resource ${siteResourceId}`); logger.info(`Updated site resource ${siteResourceId}`);
}
}); });
// Background: wait for removal messages to propagate, then rebuild
// associations for the re-created resource. Own transaction ensures
// execution on the primary against fully committed state.
(async () => {
await db.transaction(async (trx) => {
if (!updatedSiteResource) { if (!updatedSiteResource) {
throw new Error("No updated resource found after update"); throw new Error("No updated resource found after update");
} }
if (sitesChanged) { if (sitesChanged) {
await new Promise((resolve) => setTimeout(resolve, 750)); rebuildClientAssociationsFromSiteResource(
await rebuildClientAssociationsFromSiteResource( updatedSiteResource
updatedSiteResource, ).catch((e) => {
trx logger.error(
); `Failed to rebuild client associations for site resource ${siteResourceId}. Error: ${e}`
}
await handleMessagingForUpdatedSiteResource(
existingSiteResource,
updatedSiteResource,
siteIds.map((siteId) => ({
siteId,
orgId: existingSiteResource.orgId
})),
trx
); );
}); });
})().catch((err) => { }
handleMessagingForUpdatedSiteResource(
existingSiteResource,
updatedSiteResource,
Array.from(existingSiteIdSet).map((siteId: number) => ({
// we already added to the new sites above in the rebuild function so we only need to update the ones that did not change
siteId,
orgId: existingSiteResource.orgId
}))
).catch((e) => {
logger.error( logger.error(
`Error rebuilding client associations for site resource ${updatedSiteResource?.siteResourceId}:`, `Failed to handle messaging for updated site resource ${siteResourceId}. Error: ${e}`
err
); );
}); });
@@ -837,9 +660,9 @@ export async function updateSiteResource(
export async function handleMessagingForUpdatedSiteResource( export async function handleMessagingForUpdatedSiteResource(
existingSiteResource: SiteResource | undefined, existingSiteResource: SiteResource | undefined,
updatedSiteResource: SiteResource, updatedSiteResource: SiteResource,
sites: { siteId: number; orgId: string }[], sites: { siteId: number; orgId: string }[]
trx: Transaction
) { ) {
const trx = primaryDb;
logger.debug( logger.debug(
"handleMessagingForUpdatedSiteResource: existingSiteResource is: ", "handleMessagingForUpdatedSiteResource: existingSiteResource is: ",
existingSiteResource existingSiteResource
@@ -849,17 +672,14 @@ export async function handleMessagingForUpdatedSiteResource(
updatedSiteResource updatedSiteResource
); );
await rebuildClientAssociationsFromSiteResource(
existingSiteResource || updatedSiteResource, // we want to rebuild based on the existing resource then we will apply the change to the destination below
trx
);
const { sitesList, mergedAllClients, mergedAllClientIds } = const { sitesList, mergedAllClients, mergedAllClientIds } =
await getClientSiteResourceAccess( await getClientSiteResourceAccess(
existingSiteResource || updatedSiteResource, existingSiteResource || updatedSiteResource,
trx trx
); );
const siteIds = sites.map((site) => site.siteId);
// after everything is rebuilt above we still need to update the targets and remote subnets if the destination changed // after everything is rebuilt above we still need to update the targets and remote subnets if the destination changed
const destinationChanged = const destinationChanged =
existingSiteResource && existingSiteResource &&
@@ -896,56 +716,28 @@ export async function handleMessagingForUpdatedSiteResource(
portRangesChanged || portRangesChanged ||
destinationPortChanged destinationPortChanged
) { ) {
for (const site of sites) { const newtsForSites =
const [newt] = await trx siteIds.length > 0
? await trx
.select() .select()
.from(newts) .from(newts)
.where(eq(newts.siteId, site.siteId)) .where(inArray(newts.siteId, siteIds))
.limit(1); : [];
const newtBySiteId = new Map(
if (!newt) { newtsForSites.map((newt) => [newt.siteId, newt])
throw new Error(
"Newt not found for site during site resource update"
); );
}
// Only update targets on newt if these items change const oldDestinationStillInUseClientSitePairs = new Set<string>();
if ( if (
destinationChanged || existingSiteResource?.destination &&
sslChanged || // we need to push a new cert if the ssl changed siteIds.length > 0 &&
portRangesChanged || mergedAllClientIds.length > 0
fullDomainChanged || // if the domain changes we need to update the certs and stuff
destinationPortChanged
) { ) {
const oldTargets = await generateSubnetProxyTargetV2( const oldDestinationStillInUseRows = await trx
existingSiteResource, .select({
mergedAllClients clientId: clientSiteResourcesAssociationsCache.clientId,
); siteId: siteNetworks.siteId
const newTargets = await generateSubnetProxyTargetV2( })
updatedSiteResource,
mergedAllClients
);
await updateTargets(
newt.newtId,
{
oldTargets: oldTargets ? oldTargets : [],
newTargets: newTargets ? newTargets : []
},
newt.version
);
}
const olmJobs: Promise<void>[] = [];
for (const client of mergedAllClients) {
// does this client have access to another resource on this site that has the same destination still? if so we dont want to remove it from their olm yet
// todo: optimize this query if needed
if (!existingSiteResource.destination) {
continue;
}
const oldDestinationStillInUseSites = await trx
.select()
.from(siteResources) .from(siteResources)
.innerJoin( .innerJoin(
clientSiteResourcesAssociationsCache, clientSiteResourcesAssociationsCache,
@@ -960,11 +752,11 @@ export async function handleMessagingForUpdatedSiteResource(
) )
.where( .where(
and( and(
eq( inArray(
clientSiteResourcesAssociationsCache.clientId, clientSiteResourcesAssociationsCache.clientId,
client.clientId mergedAllClientIds
), ),
eq(siteNetworks.siteId, site.siteId), inArray(siteNetworks.siteId, siteIds),
eq( eq(
siteResources.destination, siteResources.destination,
existingSiteResource.destination existingSiteResource.destination
@@ -976,12 +768,69 @@ export async function handleMessagingForUpdatedSiteResource(
) )
); );
for (const row of oldDestinationStillInUseRows) {
oldDestinationStillInUseClientSitePairs.add(
`${row.clientId}:${row.siteId}`
);
}
}
const shouldUpdateTargets =
destinationChanged ||
sslChanged ||
portRangesChanged ||
fullDomainChanged ||
destinationPortChanged;
const oldTargets = shouldUpdateTargets
? await generateSubnetProxyTargetV2(
existingSiteResource,
mergedAllClients
)
: [];
const newTargets = shouldUpdateTargets
? await generateSubnetProxyTargetV2(
updatedSiteResource,
mergedAllClients
)
: [];
for (const site of sites) {
const newt = newtBySiteId.get(site.siteId);
if (!newt) {
throw new Error(
"Newt not found for site during site resource update"
);
}
// Only update targets on newt if these items change
if (shouldUpdateTargets) {
await updateTargets(
newt.newtId,
{
oldTargets: oldTargets ? oldTargets : [],
newTargets: newTargets ? newTargets : []
},
newt.version
);
}
const olmJobs: Promise<void>[] = [];
for (const client of mergedAllClients) {
// does this client have access to another resource on this site that has the same destination still? if so we dont want to remove it from their olm yet
if (!existingSiteResource.destination) {
continue;
}
const oldDestinationStillInUseByASite = const oldDestinationStillInUseByASite =
oldDestinationStillInUseSites.length > 0; oldDestinationStillInUseClientSitePairs.has(
`${client.clientId}:${site.siteId}`
);
// we also need to update the remote subnets on the olms for each client that has access to this site // we also need to update the remote subnets on the olms for each client that has access to this site
olmJobs.push( olmJobs.push(
updatePeerData( updatePeerData(
// TODO: THIS SHOULD BE UPDATED TO WORK I A BATCH
client.clientId, client.clientId,
site.siteId, site.siteId,
destinationChanged destinationChanged