117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
import {
|
|
SiteResource,
|
|
siteResources,
|
|
Transaction,
|
|
} from "@server/db";
|
|
import { sites } from "@server/db";
|
|
import { eq, and } from "drizzle-orm";
|
|
import {
|
|
Config,
|
|
} from "./types";
|
|
import logger from "@server/logger";
|
|
|
|
export type ClientResourcesResults = {
|
|
resource: SiteResource;
|
|
}[];
|
|
|
|
export async function updateClientResources(
|
|
orgId: string,
|
|
config: Config,
|
|
trx: Transaction,
|
|
siteId?: number
|
|
): Promise<ClientResourcesResults> {
|
|
const results: ClientResourcesResults = [];
|
|
|
|
for (const [resourceNiceId, resourceData] of Object.entries(
|
|
config["client-resources"]
|
|
)) {
|
|
const [existingResource] = await trx
|
|
.select()
|
|
.from(siteResources)
|
|
.where(
|
|
and(
|
|
eq(siteResources.orgId, orgId),
|
|
eq(siteResources.niceId, resourceNiceId)
|
|
)
|
|
)
|
|
.limit(1);
|
|
|
|
const resourceSiteId = resourceData.site;
|
|
let site;
|
|
|
|
if (resourceSiteId) {
|
|
// Look up site by niceId
|
|
[site] = await trx
|
|
.select({ siteId: sites.siteId })
|
|
.from(sites)
|
|
.where(
|
|
and(
|
|
eq(sites.niceId, resourceSiteId),
|
|
eq(sites.orgId, orgId)
|
|
)
|
|
)
|
|
.limit(1);
|
|
} else if (siteId) {
|
|
// Use the provided siteId directly, but verify it belongs to the org
|
|
[site] = await trx
|
|
.select({ siteId: sites.siteId })
|
|
.from(sites)
|
|
.where(and(eq(sites.siteId, siteId), eq(sites.orgId, orgId)))
|
|
.limit(1);
|
|
} else {
|
|
throw new Error(`Target site is required`);
|
|
}
|
|
|
|
if (!site) {
|
|
throw new Error(
|
|
`Site not found: ${resourceSiteId} in org ${orgId}`
|
|
);
|
|
}
|
|
|
|
if (existingResource) {
|
|
// Update existing resource
|
|
const [updatedResource] = await trx
|
|
.update(siteResources)
|
|
.set({
|
|
name: resourceData.name || resourceNiceId,
|
|
siteId: site.siteId,
|
|
proxyPort: resourceData["proxy-port"]!,
|
|
destinationIp: resourceData.hostname,
|
|
destinationPort: resourceData["internal-port"],
|
|
protocol: resourceData.protocol
|
|
})
|
|
.where(
|
|
eq(
|
|
siteResources.siteResourceId,
|
|
existingResource.siteResourceId
|
|
)
|
|
)
|
|
.returning();
|
|
|
|
results.push({ resource: updatedResource });
|
|
} else {
|
|
// Create new resource
|
|
const [newResource] = await trx
|
|
.insert(siteResources)
|
|
.values({
|
|
orgId: orgId,
|
|
siteId: site.siteId,
|
|
niceId: resourceNiceId,
|
|
name: resourceData.name || resourceNiceId,
|
|
proxyPort: resourceData["proxy-port"]!,
|
|
destinationIp: resourceData.hostname,
|
|
destinationPort: resourceData["internal-port"],
|
|
protocol: resourceData.protocol
|
|
})
|
|
.returning();
|
|
|
|
logger.info(
|
|
`Created new client resource ${newResource.name} (${newResource.siteResourceId}) for org ${orgId}`
|
|
);
|
|
|
|
results.push({ resource: newResource });
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|