gristlabs_grist-core/stubs/app/server/server.ts
Jarosław Sadziński 76d94483ad (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
2024-06-18 15:05:57 +02:00

154 lines
4.7 KiB
TypeScript

/**
* Main entrypoint for grist-core server.
*
* By default, starts up on port 8484.
*/
import {commonUrls} from 'app/common/gristUrls';
import {isAffirmative} from 'app/common/gutil';
import {HomeDBManager} from 'app/gen-server/lib/HomeDBManager';
import {fixSiteProducts} from 'app/gen-server/lib/Housekeeper';
const debugging = isAffirmative(process.env.DEBUG) || isAffirmative(process.env.VERBOSE);
// Set log levels before importing anything.
if (!debugging) {
// Be a lot less noisy by default.
setDefaultEnv('GRIST_LOG_LEVEL', 'error');
setDefaultEnv('GRIST_LOG_SKIP_HTTP', 'true');
}
// Use a distinct cookie. Bump version to 2.
setDefaultEnv('GRIST_SESSION_COOKIE', 'grist_core2');
setDefaultEnv('GRIST_SERVE_SAME_ORIGIN', 'true');
setDefaultEnv('GRIST_SINGLE_PORT', 'true');
setDefaultEnv('GRIST_DEFAULT_PRODUCT', 'Free');
if (!process.env.GRIST_SINGLE_ORG) {
// org identifiers in domains are fiddly to configure right, so by
// default don't do that.
setDefaultEnv('GRIST_ORG_IN_PATH', 'true');
}
setDefaultEnv('GRIST_UI_FEATURES',
'helpCenter,billing,templates,multiSite,multiAccounts,sendToDrive,createSite,supportGrist');
setDefaultEnv('GRIST_WIDGET_LIST_URL', commonUrls.gristLabsWidgetRepository);
import {updateDb} from 'app/server/lib/dbUtils';
import {main as mergedServerMain, parseServerTypes} from 'app/server/mergedServerMain';
import * as fse from 'fs-extra';
import {runPrometheusExporter} from './prometheus-exporter';
const G = {
port: parseInt(process.env.PORT!, 10) || 8484,
};
// Set a default for an environment variable.
function setDefaultEnv(name: string, value: string) {
if (process.env[name] === undefined) {
process.env[name] = value;
}
}
async function setupDb() {
// Make a blank db if needed.
if (process.env.TEST_CLEAN_DATABASE) {
const {createInitialDb} = require('test/gen-server/seed');
await createInitialDb();
} else {
await updateDb();
}
const db = new HomeDBManager();
await db.connect();
await db.initializeSpecialIds({skipWorkspaces: true});
// If a team/organization is specified, make sure it exists.
const org = process.env.GRIST_SINGLE_ORG;
if (org && org !== 'docs') {
try {
db.unwrapQueryResult(await db.getOrg({
userId: db.getPreviewerUserId(),
includeSupport: false,
}, org));
} catch(e) {
if (!String(e).match(/organization not found/)) {
throw e;
}
const email = process.env.GRIST_DEFAULT_EMAIL;
if (!email) {
throw new Error('need GRIST_DEFAULT_EMAIL to create site');
}
const profile = {email, name: email};
const user = await db.getUserByLogin(email, {profile});
if (!user) {
// This should not happen.
throw new Error('failed to create GRIST_DEFAULT_EMAIL user');
}
db.unwrapQueryResult(await db.addOrg(user, {
name: org,
domain: org,
}, {
setUserAsOwner: false,
useNewPlan: true,
}));
}
}
}
// tslint:disable:no-console
export async function main() {
console.log('Welcome to Grist.');
if (!debugging) {
console.log(`In quiet mode, see http://localhost:${G.port} to use.`);
console.log('For full logs, re-run with DEBUG=1');
}
if (process.env.GRIST_PROMCLIENT_PORT) {
runPrometheusExporter(parseInt(process.env.GRIST_PROMCLIENT_PORT, 10));
}
// If SAML is not configured, there's no login system, so provide a default email address.
setDefaultEnv('GRIST_DEFAULT_EMAIL', 'you@example.com');
// Set directory for uploaded documents.
setDefaultEnv('GRIST_DATA_DIR', 'docs');
setDefaultEnv('GRIST_SERVERS', 'home,docs,static');
if (process.env.GRIST_SERVERS?.includes('home')) {
// By default, we will now start an untrusted port alongside a
// home server, for bundled custom widgets.
// Suppress with GRIST_UNTRUSTED_PORT=''
setDefaultEnv('GRIST_UNTRUSTED_PORT', '0');
}
const serverTypes = parseServerTypes(process.env.GRIST_SERVERS);
await fse.mkdirp(process.env.GRIST_DATA_DIR!);
if (serverTypes.includes("home")) {
console.log('Setting up database...');
await setupDb();
console.log('Database setup complete.');
}
// Launch single-port, self-contained version of Grist.
const server = await mergedServerMain(G.port, serverTypes);
if (process.env.GRIST_TESTING_SOCKET) {
await server.addTestingHooks();
}
if (process.env.GRIST_SERVE_PLUGINS_PORT) {
await server.startCopy('pluginServer', parseInt(process.env.GRIST_SERVE_PLUGINS_PORT, 10));
}
await fixSiteProducts({
deploymentType: server.getDeploymentType(),
db: server.getHomeDBManager(),
dry: true
});
return server;
}
if (require.main === module) {
main().catch((err) => {
console.error(err);
});
}