mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-10 14:38:22 +02:00
Properly lock the ip selection through writes to db
This commit is contained in:
@@ -203,84 +203,82 @@ export async function registerNewt(
|
||||
|
||||
let newSiteId: number | undefined;
|
||||
|
||||
await db.transaction(async (trx) => {
|
||||
const newClientAddress = await getNextAvailableClientSubnet(orgId);
|
||||
if (!newClientAddress) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.INTERNAL_SERVER_ERROR,
|
||||
"No available subnet found"
|
||||
)
|
||||
);
|
||||
}
|
||||
const { value: newClientAddress, release: releaseSubnetLock } =
|
||||
await getNextAvailableClientSubnet(orgId);
|
||||
try {
|
||||
await db.transaction(async (trx) => {
|
||||
let clientAddress = newClientAddress.split("/")[0];
|
||||
clientAddress = `${clientAddress}/${org.subnet!.split("/")[1]}`; // we want the block size of the whole org
|
||||
|
||||
let clientAddress = newClientAddress.split("/")[0];
|
||||
clientAddress = `${clientAddress}/${org.subnet!.split("/")[1]}`; // we want the block size of the whole org
|
||||
// Create the site (type "newt", name = niceId)
|
||||
const [newSite] = await trx
|
||||
.insert(sites)
|
||||
.values({
|
||||
orgId,
|
||||
name: name || niceId,
|
||||
niceId,
|
||||
address: clientAddress,
|
||||
type: "newt",
|
||||
dockerSocketEnabled: true,
|
||||
status: keyRecord.approveNewSites
|
||||
? "approved"
|
||||
: "pending"
|
||||
})
|
||||
.returning();
|
||||
|
||||
// Create the site (type "newt", name = niceId)
|
||||
const [newSite] = await trx
|
||||
.insert(sites)
|
||||
.values({
|
||||
orgId,
|
||||
name: name || niceId,
|
||||
niceId,
|
||||
address: clientAddress,
|
||||
type: "newt",
|
||||
dockerSocketEnabled: true,
|
||||
status: keyRecord.approveNewSites ? "approved" : "pending"
|
||||
})
|
||||
.returning();
|
||||
await logsDb.insert(statusHistory).values({
|
||||
entityType: "site",
|
||||
entityId: newSite.siteId,
|
||||
orgId: orgId,
|
||||
status: "offline",
|
||||
timestamp: Math.floor(Date.now() / 1000)
|
||||
});
|
||||
|
||||
await logsDb.insert(statusHistory).values({
|
||||
entityType: "site",
|
||||
entityId: newSite.siteId,
|
||||
orgId: orgId,
|
||||
status: "offline",
|
||||
timestamp: Math.floor(Date.now() / 1000)
|
||||
newSiteId = newSite.siteId;
|
||||
|
||||
// Grant admin role access to the new site
|
||||
const [adminRole] = await trx
|
||||
.select()
|
||||
.from(roles)
|
||||
.where(and(eq(roles.isAdmin, true), eq(roles.orgId, orgId)))
|
||||
.limit(1);
|
||||
|
||||
if (!adminRole) {
|
||||
throw new Error(`Admin role not found for org ${orgId}`);
|
||||
}
|
||||
|
||||
await trx.insert(roleSites).values({
|
||||
roleId: adminRole.roleId,
|
||||
siteId: newSite.siteId
|
||||
});
|
||||
|
||||
// Create the newt for this site
|
||||
await trx.insert(newts).values({
|
||||
newtId,
|
||||
secretHash,
|
||||
siteId: newSite.siteId,
|
||||
dateCreated: moment().toISOString()
|
||||
});
|
||||
|
||||
// Consume the provisioning key - cascade removes siteProvisioningKeyOrg
|
||||
await trx
|
||||
.update(siteProvisioningKeys)
|
||||
.set({
|
||||
lastUsed: moment().toISOString(),
|
||||
numUsed: sql`${siteProvisioningKeys.numUsed} + 1`
|
||||
})
|
||||
.where(
|
||||
eq(
|
||||
siteProvisioningKeys.siteProvisioningKeyId,
|
||||
provisioningKeyId
|
||||
)
|
||||
);
|
||||
|
||||
await usageService.add(orgId, FeatureId.SITES, 1, trx);
|
||||
});
|
||||
|
||||
newSiteId = newSite.siteId;
|
||||
|
||||
// Grant admin role access to the new site
|
||||
const [adminRole] = await trx
|
||||
.select()
|
||||
.from(roles)
|
||||
.where(and(eq(roles.isAdmin, true), eq(roles.orgId, orgId)))
|
||||
.limit(1);
|
||||
|
||||
if (!adminRole) {
|
||||
throw new Error(`Admin role not found for org ${orgId}`);
|
||||
}
|
||||
|
||||
await trx.insert(roleSites).values({
|
||||
roleId: adminRole.roleId,
|
||||
siteId: newSite.siteId
|
||||
});
|
||||
|
||||
// Create the newt for this site
|
||||
await trx.insert(newts).values({
|
||||
newtId,
|
||||
secretHash,
|
||||
siteId: newSite.siteId,
|
||||
dateCreated: moment().toISOString()
|
||||
});
|
||||
|
||||
// Consume the provisioning key - cascade removes siteProvisioningKeyOrg
|
||||
await trx
|
||||
.update(siteProvisioningKeys)
|
||||
.set({
|
||||
lastUsed: moment().toISOString(),
|
||||
numUsed: sql`${siteProvisioningKeys.numUsed} + 1`
|
||||
})
|
||||
.where(
|
||||
eq(
|
||||
siteProvisioningKeys.siteProvisioningKeyId,
|
||||
provisioningKeyId
|
||||
)
|
||||
);
|
||||
|
||||
await usageService.add(orgId, FeatureId.SITES, 1, trx);
|
||||
});
|
||||
} finally {
|
||||
await releaseSubnetLock();
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Provisioned new site (ID: ${newSiteId}) and newt (ID: ${newtId}) for org ${orgId} via provisioning key ${provisioningKeyId}`
|
||||
|
||||
Reference in New Issue
Block a user