mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-25 21:45:24 +02:00
Fix #2937
This commit is contained in:
@@ -23,6 +23,12 @@ export async function createCertificate(
|
|||||||
throw new Error(`Domain with ID ${domainId} not found`);
|
throw new Error(`Domain with ID ${domainId} not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: certificates.domain has a global UNIQUE constraint (it is not
|
||||||
|
// scoped per-domainId), so existence must be checked by domain value
|
||||||
|
// alone. Filtering on domainId here as well can cause this check to
|
||||||
|
// miss an existing cert (e.g. if it was stored under a different but
|
||||||
|
// still-valid domainId), leading to an INSERT that then fails on the
|
||||||
|
// unique constraint.
|
||||||
let existing: Certificate[] = [];
|
let existing: Certificate[] = [];
|
||||||
if (domainRecord.type == "ns" || domainRecord.type == "wildcard") {
|
if (domainRecord.type == "ns" || domainRecord.type == "wildcard") {
|
||||||
const domainLevelDown = domain.split(".").slice(1).join(".");
|
const domainLevelDown = domain.split(".").slice(1).join(".");
|
||||||
@@ -32,8 +38,6 @@ export async function createCertificate(
|
|||||||
.select()
|
.select()
|
||||||
.from(certificates)
|
.from(certificates)
|
||||||
.where(
|
.where(
|
||||||
and(
|
|
||||||
eq(certificates.domainId, domainId),
|
|
||||||
or(
|
or(
|
||||||
eq(certificates.domain, domain),
|
eq(certificates.domain, domain),
|
||||||
and(
|
and(
|
||||||
@@ -44,19 +48,13 @@ export async function createCertificate(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// For non-NS domains, we only match exact domain names
|
// For non-NS domains, we only match exact domain names
|
||||||
existing = await trx
|
existing = await trx
|
||||||
.select()
|
.select()
|
||||||
.from(certificates)
|
.from(certificates)
|
||||||
.where(
|
.where(eq(certificates.domain, domain)); // exact match for non-NS domains
|
||||||
and(
|
|
||||||
eq(certificates.domainId, domainId),
|
|
||||||
eq(certificates.domain, domain) // exact match for non-NS domains
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existing.length > 0) {
|
if (existing.length > 0) {
|
||||||
@@ -87,8 +85,13 @@ export async function createCertificate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No cert found, create a new one in pending state
|
// No cert found, create a new one in pending state. onConflictDoNothing
|
||||||
await trx.insert(certificates).values({
|
// guards against the domain having been inserted concurrently (or under
|
||||||
|
// a different domainId) between the existence check above and this
|
||||||
|
// insert, since certificates.domain is globally unique.
|
||||||
|
await trx
|
||||||
|
.insert(certificates)
|
||||||
|
.values({
|
||||||
domain: domainToWrite,
|
domain: domainToWrite,
|
||||||
domainId,
|
domainId,
|
||||||
wildcard:
|
wildcard:
|
||||||
@@ -98,5 +101,6 @@ export async function createCertificate(
|
|||||||
status: "pending",
|
status: "pending",
|
||||||
updatedAt: Math.floor(Date.now() / 1000),
|
updatedAt: Math.floor(Date.now() / 1000),
|
||||||
createdAt: Math.floor(Date.now() / 1000)
|
createdAt: Math.floor(Date.now() / 1000)
|
||||||
});
|
})
|
||||||
|
.onConflictDoNothing();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user