Merge pull request #2959 from fosrl/dev

1.18.1-s.4
This commit is contained in:
Owen Schwartz
2026-05-01 15:05:59 -07:00
committed by GitHub
5 changed files with 32 additions and 20 deletions

View File

@@ -64,7 +64,7 @@ export const NotifyTrialExpiring = ({
<EmailText> <EmailText>
Some features and resources may now be Some features and resources may now be
restricted or disconnected. To restore full restricted. To restore full
access and continue using all the features access and continue using all the features
you had during your trial, please upgrade to you had during your trial, please upgrade to
a paid plan. a paid plan.
@@ -85,7 +85,7 @@ export const NotifyTrialExpiring = ({
<strong>{orgName}</strong> will end on{" "} <strong>{orgName}</strong> will end on{" "}
<strong>{trialEndsAt}</strong> <strong>{trialEndsAt}</strong>
{isLastDay {isLastDay
? " that's tomorrow!" ? " - that's tomorrow!"
: `, in ${daysRemaining} days`} : `, in ${daysRemaining} days`}
. .
</EmailText> </EmailText>
@@ -93,8 +93,7 @@ export const NotifyTrialExpiring = ({
<EmailText> <EmailText>
After your trial ends, your account will be After your trial ends, your account will be
moved to the free plan and some moved to the free plan and some
functionality may be restricted or your functionality may be restricted.
sites may disconnect.
</EmailText> </EmailText>
<EmailText> <EmailText>

View File

@@ -25,7 +25,7 @@ export const tier1LimitSet: LimitSet = {
export const tier2LimitSet: LimitSet = { export const tier2LimitSet: LimitSet = {
[FeatureId.USERS]: { [FeatureId.USERS]: {
value: 100, value: 50,
description: "Team limit" description: "Team limit"
}, },
[FeatureId.SITES]: { [FeatureId.SITES]: {
@@ -48,7 +48,7 @@ export const tier2LimitSet: LimitSet = {
export const tier3LimitSet: LimitSet = { export const tier3LimitSet: LimitSet = {
[FeatureId.USERS]: { [FeatureId.USERS]: {
value: 500, value: 250,
description: "Business limit" description: "Business limit"
}, },
[FeatureId.SITES]: { [FeatureId.SITES]: {

View File

@@ -19,12 +19,13 @@ import { eq, and, ne } from "drizzle-orm";
export async function getOrgTierData( export async function getOrgTierData(
orgId: string orgId: string
): Promise<{ tier: Tier | null; active: boolean }> { ): Promise<{ tier: Tier | null; active: boolean; isTrial: boolean }> {
let tier: Tier | null = null; let tier: Tier | null = null;
let active = false; let active = false;
let isTrial = false;
if (build !== "saas") { if (build !== "saas") {
return { tier, active }; return { tier, active, isTrial };
} }
try { try {
@@ -35,7 +36,7 @@ export async function getOrgTierData(
.limit(1); .limit(1);
if (!org) { if (!org) {
return { tier, active }; return { tier, active, isTrial };
} }
let orgIdToUse = org.orgId; let orgIdToUse = org.orgId;
@@ -44,7 +45,7 @@ export async function getOrgTierData(
logger.warn( logger.warn(
`Org ${orgId} is not a billing org and does not have a billingOrgId` `Org ${orgId} is not a billing org and does not have a billingOrgId`
); );
return { tier, active }; return { tier, active, isTrial };
} }
orgIdToUse = org.billingOrgId; orgIdToUse = org.billingOrgId;
} }
@@ -57,7 +58,7 @@ export async function getOrgTierData(
.limit(1); .limit(1);
if (!customer) { if (!customer) {
return { tier, active }; return { tier, active, isTrial };
} }
// Query for active subscriptions that are not license type // Query for active subscriptions that are not license type
@@ -84,11 +85,13 @@ export async function getOrgTierData(
tier = subscription.type; tier = subscription.type;
active = true; active = true;
} }
isTrial = subscription.trial ?? false;
} }
} catch (error) { } catch (error) {
// If org not found or error occurs, return null tier and inactive // If org not found or error occurs, return null tier and inactive
// This is acceptable behavior as per the function signature // This is acceptable behavior as per the function signature
} }
return { tier, active }; return { tier, active, isTrial };
} }

View File

@@ -104,8 +104,9 @@ export async function deleteMyAccount(
(r) => r.isBillingOrg && r.isOwner (r) => r.isBillingOrg && r.isOwner
)?.orgId; )?.orgId;
if (primaryOrgId) { if (primaryOrgId) {
const { tier, active } = await getOrgTierData(primaryOrgId); const { tier, active, isTrial } =
if (active && tier) { await getOrgTierData(primaryOrgId);
if (active && tier && !isTrial) {
return next( return next(
createHttpError( createHttpError(
HttpCode.BAD_REQUEST, HttpCode.BAD_REQUEST,

View File

@@ -63,17 +63,26 @@ export async function deleteSiteResource(
); );
} }
await db.transaction(async (trx) => { // Delete the site resource
// Delete the site resource const [removedSiteResource] = await db
const [removedSiteResource] = await trx .delete(siteResources)
.delete(siteResources) .where(eq(siteResources.siteResourceId, siteResourceId))
.where(eq(siteResources.siteResourceId, siteResourceId)) .returning();
.returning();
// Run in the background after the response is sent. Wrapped in its
// own transaction so it always executes on the primary — avoiding any
// replica-lag issues while still allowing the HTTP response to return
// early.
db.transaction(async (trx) => {
await rebuildClientAssociationsFromSiteResource( await rebuildClientAssociationsFromSiteResource(
removedSiteResource, removedSiteResource,
trx trx
); );
}).catch((err) => {
logger.error(
`Error rebuilding client associations for site resource ${removedSiteResource!.siteResourceId}:`,
err
);
}); });
logger.info(`Deleted site resource ${siteResourceId}`); logger.info(`Deleted site resource ${siteResourceId}`);