From 437d7e61c0a7cad3c4ae4b9c2bbd225737a9218f Mon Sep 17 00:00:00 2001 From: jarek Date: Tue, 1 Oct 2024 17:33:50 +0200 Subject: [PATCH] Removing fixSiteProducts method (#1236) Context: Removing an obsolete method that was fixing an issue with default site products. Details can be found here 76d9448 Proposed solution: Removing this method and its test. Test plan: not needed https://github.com/gristlabs/grist-core/pull/1236 --- app/gen-server/lib/Housekeeper.ts | 62 ------------- stubs/app/server/server.ts | 5 - test/server/fixSiteProducts.ts | 146 ------------------------------ 3 files changed, 213 deletions(-) delete mode 100644 test/server/fixSiteProducts.ts diff --git a/app/gen-server/lib/Housekeeper.ts b/app/gen-server/lib/Housekeeper.ts index c3012bec..d380dd11 100644 --- a/app/gen-server/lib/Housekeeper.ts +++ b/app/gen-server/lib/Housekeeper.ts @@ -2,10 +2,8 @@ import { ApiError } from 'app/common/ApiError'; import { delay } from 'app/common/delay'; import { buildUrlId } from 'app/common/gristUrls'; import { normalizedDateTimeString } from 'app/common/normalizedDateTimeString'; -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/homedb/HomeDBManager'; import { fromNow } from 'app/gen-server/sqlUtils'; @@ -438,63 +436,3 @@ async function forEachWithBreaks(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 -}) { - const {deploymentType, 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; - } - - await t.createQueryBuilder() - .update(BillingAccount) - .set({product: freeProduct.id}) - .where({product: freeTeamProduct.id}) - .execute(); - - return true; - }); -} diff --git a/stubs/app/server/server.ts b/stubs/app/server/server.ts index c7e5b9eb..6f5f63fa 100644 --- a/stubs/app/server/server.ts +++ b/stubs/app/server/server.ts @@ -7,7 +7,6 @@ import {commonUrls} from 'app/common/gristUrls'; import {isAffirmative} from 'app/common/gutil'; import {HomeDBManager} from 'app/gen-server/lib/homedb/HomeDBManager'; -import {fixSiteProducts} from 'app/gen-server/lib/Housekeeper'; const debugging = isAffirmative(process.env.DEBUG) || isAffirmative(process.env.VERBOSE); @@ -132,10 +131,6 @@ export async function main() { if (process.env.GRIST_SERVE_PLUGINS_PORT) { await mergedServer.flexServer.startCopy('pluginServer', parseInt(process.env.GRIST_SERVE_PLUGINS_PORT, 10)); } - await fixSiteProducts({ - deploymentType: mergedServer.flexServer.getDeploymentType(), - db: mergedServer.flexServer.getHomeDBManager() - }); return mergedServer.flexServer; } diff --git a/test/server/fixSiteProducts.ts b/test/server/fixSiteProducts.ts deleted file mode 100644 index 353b4ac8..00000000 --- a/test/server/fixSiteProducts.ts +++ /dev/null @@ -1,146 +0,0 @@ -import {Organization} from 'app/gen-server/entity/Organization'; -import {fixSiteProducts} from 'app/gen-server/lib/Housekeeper'; -import {TestServer} from 'test/gen-server/apiUtils'; -import * as testUtils from 'test/server/testUtils'; -import {assert} from 'chai'; -import sinon from "sinon"; -import {getDefaultProductNames} from 'app/gen-server/entity/Product'; - -const email = 'chimpy@getgrist.com'; -const profile = {email, name: email}; -const org = 'single-org'; - -describe('fixSiteProducts', function() { - this.timeout(6000); - - let oldEnv: testUtils.EnvironmentSnapshot; - let server: TestServer; - - before(async function() { - oldEnv = new testUtils.EnvironmentSnapshot(); - // By default we will simulate 'core' deployment that has 'Free' team site as default product. - process.env.GRIST_TEST_SERVER_DEPLOYMENT_TYPE = 'core'; - process.env.GRIST_DEFAULT_PRODUCT = 'Free'; - server = new TestServer(this); - await server.start(); - }); - - after(async function() { - oldEnv.restore(); - await server.stop(); - }); - - it('fix should be deleted after 2024-10-01', async function() { - const now = new Date(); - const remove_date = new Date('2024-10-01'); - assert.isTrue(now < remove_date, 'This test and a fix method should be deleted after 2024-10-01'); - }); - - it('fixes sites that where created with a wrong product', async function() { - const db = server.dbManager; - const user = await db.getUserByLogin(email, {profile}) as any; - const getOrg = (id: number) => db.connection.manager.findOne( - Organization, - {where: {id}, relations: ['billingAccount', 'billingAccount.product']}); - - const productOrg = (id: number) => getOrg(id)?.then(org => org?.billingAccount?.product?.name); - - const freeOrgId = db.unwrapQueryResult(await db.addOrg(user, { - name: org, - domain: org, - }, { - setUserAsOwner: false, - useNewPlan: true, - product: 'teamFree', - })); - - const teamOrgId = db.unwrapQueryResult(await db.addOrg(user, { - name: 'fix-team-org', - domain: 'fix-team-org', - }, { - setUserAsOwner: false, - useNewPlan: true, - product: 'team', - })); - - // Make sure it is created with teamFree product. - assert.equal(await productOrg(freeOrgId), 'teamFree'); - - // Run the fixer. - assert.isTrue(await fixSiteProducts({ - db, - deploymentType: server.server.getDeploymentType(), - })); - - // Make sure we fixed the product is on Free product. - assert.equal(await productOrg(freeOrgId), 'Free'); - - // Make sure the other org is still on team product. - assert.equal(await productOrg(teamOrgId), 'team'); - }); - - it("doesn't run when on saas deployment", async function() { - process.env.GRIST_TEST_SERVER_DEPLOYMENT_TYPE = 'saas'; - - // Stub it in the server. Notice that we assume some knowledge about how the server is implemented - that it won't - // cache this value (nor any other component) and always read it when needed. Otherwise we would need to recreate - // the server each time. - const sandbox = sinon.createSandbox(); - sandbox.stub(server.server, 'getDeploymentType').returns('saas'); - assert.equal(server.server.getDeploymentType(), 'saas'); - - assert.isFalse(await fixSiteProducts({ - db: server.dbManager, - deploymentType: server.server.getDeploymentType(), - })); - - sandbox.restore(); - }); - - it("doesn't run when default product is not set", async function() { - // Make sure we are in 'core'. - assert.equal(server.server.getDeploymentType(), 'core'); - - // But only when Free product is the default one. - process.env.GRIST_DEFAULT_PRODUCT = 'teamFree'; - assert.equal(getDefaultProductNames().teamInitial, 'teamFree'); // sanity check that Grist sees it. - - assert.isFalse(await fixSiteProducts({ - db: server.dbManager, - deploymentType: server.server.getDeploymentType(), - })); - - process.env.GRIST_DEFAULT_PRODUCT = 'team'; - assert.equal(getDefaultProductNames().teamInitial, 'team'); - - assert.isFalse(await fixSiteProducts({ - db: server.dbManager, - deploymentType: server.server.getDeploymentType(), - })); - - delete process.env.GRIST_DEFAULT_PRODUCT; - assert.equal(getDefaultProductNames().teamInitial, 'stub'); - - const db = server.dbManager; - const user = await db.getUserByLogin(email, {profile}); - const orgId = db.unwrapQueryResult(await db.addOrg(user, { - name: 'sanity-check-org', - domain: 'sanity-check-org', - }, { - setUserAsOwner: false, - useNewPlan: true, - product: 'teamFree', - })); - - const getOrg = (id: number) => db.connection.manager.findOne(Organization, - {where: {id}, relations: ['billingAccount', 'billingAccount.product']}); - const productOrg = (id: number) => getOrg(id)?.then(org => org?.billingAccount?.product?.name); - assert.equal(await productOrg(orgId), 'teamFree'); - - assert.isFalse(await fixSiteProducts({ - db: server.dbManager, - deploymentType: server.server.getDeploymentType(), - })); - assert.equal(await productOrg(orgId), 'teamFree'); - }); -});