mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Adding fixSiteProducts that changes orgs from teamFree to Free product if it was set be default
Summary: After release on 2024-06-12 (1.1.15) the GRIST_DEFAULT_PRODUCT env variable wasn't respected by the method that started the server in single org mode. In all deployments (apart from saas), the default product used for new sites is set to `Free`, but the code that starts the server enforced `teamFree` product. This change adds a fix routine that fixes this issue by rewriting team sites from `teamFree` product to `Free` product only if: - The default product is set to `Free` - The deployment type is something other then 'saas'. Additionally there is a test that will fail after 2024.10.01, as this fix should be removed before this date. Test Plan: Added test Reviewers: paulfitz Reviewed By: paulfitz Subscribers: paulfitz Differential Revision: https://phab.getgrist.com/D4272
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { ApiError } from 'app/common/ApiError';
|
||||
import { delay } from 'app/common/delay';
|
||||
import { buildUrlId } from 'app/common/gristUrls';
|
||||
import { BillingAccount } from 'app/gen-server/entity/BillingAccount';
|
||||
import { Document } from 'app/gen-server/entity/Document';
|
||||
import { Organization } from 'app/gen-server/entity/Organization';
|
||||
import { Product } from 'app/gen-server/entity/Product';
|
||||
import { Workspace } from 'app/gen-server/entity/Workspace';
|
||||
import { HomeDBManager, Scope } from 'app/gen-server/lib/HomeDBManager';
|
||||
import { fromNow } from 'app/gen-server/sqlUtils';
|
||||
@@ -462,3 +464,79 @@ async function forEachWithBreaks<T>(logText: string, items: T[], callback: (item
|
||||
}
|
||||
log.rawInfo(logText, {itemsProcesssed, itemsTotal, timeMs: Date.now() - start});
|
||||
}
|
||||
|
||||
/**
|
||||
* For a brief moment file `stubs/app/server/server.ts` was ignoring the GRIST_DEFAULT_PRODUCT
|
||||
* variable, which is currently set for all deployment types to 'Free' product. As a result orgs
|
||||
* created after 2024-06-12 (1.1.15) were created with 'teamFree' product instead of 'Free'.
|
||||
* It only affected deployments that were using:
|
||||
* - GRIST_DEFAULT_PRODUCT variable set to 'Free'
|
||||
* - GRIST_SINGLE_ORG set to enforce single org mode.
|
||||
*
|
||||
* This method fixes the product for all orgs created with 'teamFree' product, if the default
|
||||
* product that should be used is 'Free' and the deployment type is not 'saas' ('saas' deployment
|
||||
* isn't using GRIST_DEFAULT_PRODUCT variable). This method should be removed after 2024.10.01.
|
||||
*
|
||||
* There is a corresponding test that will fail if this method (and that test) are not removed.
|
||||
*
|
||||
* @returns true if the method was run, false otherwise.
|
||||
*/
|
||||
export async function fixSiteProducts(options: {
|
||||
deploymentType: string,
|
||||
db: HomeDBManager,
|
||||
dry?: boolean,
|
||||
}) {
|
||||
const {deploymentType, dry, db} = options;
|
||||
|
||||
const hasDefaultProduct = () => Boolean(process.env.GRIST_DEFAULT_PRODUCT);
|
||||
const defaultProductIsFree = () => process.env.GRIST_DEFAULT_PRODUCT === 'Free';
|
||||
const notSaasDeployment = () => deploymentType !== 'saas';
|
||||
const mustRun = hasDefaultProduct() && defaultProductIsFree() && notSaasDeployment();
|
||||
if (!mustRun) {
|
||||
return false;
|
||||
}
|
||||
const removeMeDate = new Date('2024-10-01');
|
||||
const warningMessage = `WARNING: This method should be removed after ${removeMeDate.toDateString()}.`;
|
||||
if (new Date() > removeMeDate) {
|
||||
console.warn(warningMessage);
|
||||
}
|
||||
|
||||
// Find all billing accounts on teamFree product and change them to the Free.
|
||||
|
||||
return await db.connection.transaction(async (t) => {
|
||||
const freeProduct = await t.findOne(Product, {where: {name: 'Free'}});
|
||||
|
||||
const freeTeamProduct = await t.findOne(Product, {where: {name: 'teamFree'}});
|
||||
|
||||
if (!freeTeamProduct) {
|
||||
console.warn('teamFree product not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!freeProduct) {
|
||||
console.warn('Free product not found.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dry) {
|
||||
await t.createQueryBuilder()
|
||||
.select('ba')
|
||||
.from(BillingAccount, 'ba')
|
||||
.where('ba.product = :productId', {productId: freeTeamProduct.id})
|
||||
.getMany()
|
||||
.then((accounts) => {
|
||||
accounts.forEach(a => {
|
||||
console.log(`Would change account ${a.id} from ${a.product.id} to ${freeProduct.id}`);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
await t.createQueryBuilder()
|
||||
.update(BillingAccount)
|
||||
.set({product: freeProduct.id})
|
||||
.where({product: freeTeamProduct.id})
|
||||
.execute();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user