mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-08 19:56:37 +00:00
delete org domains and resources on org delete
This commit is contained in:
@@ -1,14 +1,8 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { db, resources } from "@server/db";
|
import { db, domains, orgDomains, resources } from "@server/db";
|
||||||
import {
|
import { newts, newtSessions, orgs, sites, userActions } from "@server/db";
|
||||||
newts,
|
import { eq, and, inArray, sql } from "drizzle-orm";
|
||||||
newtSessions,
|
|
||||||
orgs,
|
|
||||||
sites,
|
|
||||||
userActions
|
|
||||||
} from "@server/db";
|
|
||||||
import { eq } from "drizzle-orm";
|
|
||||||
import response from "@server/lib/response";
|
import response from "@server/lib/response";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
@@ -126,8 +120,45 @@ export async function deleteOrg(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await trx.delete(orgs).where(eq(orgs.orgId, orgId));
|
const allOrgDomains = await trx
|
||||||
|
.select()
|
||||||
|
.from(orgDomains)
|
||||||
|
.innerJoin(domains, eq(domains.domainId, orgDomains.domainId))
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(orgDomains.orgId, orgId),
|
||||||
|
eq(domains.configManaged, false)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// For each domain, check if it belongs to multiple organizations
|
||||||
|
const domainIdsToDelete: string[] = [];
|
||||||
|
for (const orgDomain of allOrgDomains) {
|
||||||
|
const domainId = orgDomain.domains.domainId;
|
||||||
|
|
||||||
|
// Count how many organizations this domain belongs to
|
||||||
|
const orgCount = await trx
|
||||||
|
.select({ count: sql<number>`count(*)` })
|
||||||
|
.from(orgDomains)
|
||||||
|
.where(eq(orgDomains.domainId, domainId));
|
||||||
|
|
||||||
|
// Only delete the domain if it belongs to exactly 1 organization (the one being deleted)
|
||||||
|
if (orgCount[0].count === 1) {
|
||||||
|
domainIdsToDelete.push(domainId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete domains that belong exclusively to this organization
|
||||||
|
if (domainIdsToDelete.length > 0) {
|
||||||
|
await trx
|
||||||
|
.delete(domains)
|
||||||
|
.where(inArray(domains.domainId, domainIdsToDelete));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete resources
|
||||||
await trx.delete(resources).where(eq(resources.orgId, orgId));
|
await trx.delete(resources).where(eq(resources.orgId, orgId));
|
||||||
|
|
||||||
|
await trx.delete(orgs).where(eq(orgs.orgId, orgId));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send termination messages outside of transaction to prevent blocking
|
// Send termination messages outside of transaction to prevent blocking
|
||||||
@@ -137,8 +168,11 @@ export async function deleteOrg(
|
|||||||
data: {}
|
data: {}
|
||||||
};
|
};
|
||||||
// Don't await this to prevent blocking the response
|
// Don't await this to prevent blocking the response
|
||||||
sendToClient(newtId, payload).catch(error => {
|
sendToClient(newtId, payload).catch((error) => {
|
||||||
logger.error("Failed to send termination message to newt:", error);
|
logger.error(
|
||||||
|
"Failed to send termination message to newt:",
|
||||||
|
error
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ export default function DomainPicker({
|
|||||||
|
|
||||||
if (!userInput.trim()) return options;
|
if (!userInput.trim()) return options;
|
||||||
|
|
||||||
// Check if input is more than one level deep (contains multiple dots)
|
|
||||||
const isMultiLevel = (userInput.match(/\./g) || []).length > 1;
|
|
||||||
|
|
||||||
// Add organization domain options
|
// Add organization domain options
|
||||||
organizationDomains.forEach((orgDomain) => {
|
organizationDomains.forEach((orgDomain) => {
|
||||||
if (orgDomain.type === "cname") {
|
if (orgDomain.type === "cname") {
|
||||||
@@ -319,6 +316,8 @@ export default function DomainPicker({
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
setUserInput(validInput);
|
setUserInput(validInput);
|
||||||
|
// Clear selection when input changes
|
||||||
|
setSelectedOption(null);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
|
|||||||
Reference in New Issue
Block a user