From 2c166582fd685c775975bf890113a8b95427ee80 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Thu, 1 Feb 2024 12:09:41 -0600 Subject: [PATCH] Added config option to disable db backups (#19614) refs https://linear.app/tryghost/issue/ENG-600 - users need an option so they can perform actions like delete users without blowing up Ghost as large dbs can OOM node --- ghost/core/core/server/data/db/backup.js | 8 +++++++- ghost/core/core/server/services/Users.js | 8 ++++++-- ghost/core/core/shared/config/defaults.json | 3 ++- ghost/core/test/unit/server/data/db/backup.test.js | 13 +++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ghost/core/core/server/data/db/backup.js b/ghost/core/core/server/data/db/backup.js index 8153d1a3ce..55c99abb0b 100644 --- a/ghost/core/core/server/data/db/backup.js +++ b/ghost/core/core/server/data/db/backup.js @@ -42,9 +42,15 @@ const readBackup = async (filename) => { * Does an export, and stores this in a local file * * @param {Object} options - * @returns {Promise} + * @returns {Promise | null} */ const backup = async function backup(options = {}) { + // do not create backup if disabled in config (this is intended for large customers who will OOM node) + if (config.get('disableJSBackups')) { + logging.info('Database backup is disabled in Ghost config'); + return null; + } + logging.info('Creating database backup'); const filename = await exporter.fileName(options); diff --git a/ghost/core/core/server/services/Users.js b/ghost/core/core/server/services/Users.js index 745de78b0d..a688517d8d 100644 --- a/ghost/core/core/server/services/Users.js +++ b/ghost/core/core/server/services/Users.js @@ -148,9 +148,13 @@ class Users { * @returns */ async destroyUser(frameOptions) { + let filename = null; const backupPath = await this.dbBackup.backup(); - const parsedFileName = path.parse(backupPath); - const filename = `${parsedFileName.name}${parsedFileName.ext}`; + + if (backupPath) { + const parsedFileName = path.parse(backupPath); + filename = `${parsedFileName.name}${parsedFileName.ext}`; + } return this.models.Base.transaction(async (t) => { frameOptions.transacting = t; diff --git a/ghost/core/core/shared/config/defaults.json b/ghost/core/core/shared/config/defaults.json index 2c392bd25b..d0b55bda8d 100644 --- a/ghost/core/core/shared/config/defaults.json +++ b/ghost/core/core/shared/config/defaults.json @@ -228,5 +228,6 @@ }, "bulkEmail": { "batchSize": 1000 - } + }, + "disableJSBackups": false } diff --git a/ghost/core/test/unit/server/data/db/backup.test.js b/ghost/core/test/unit/server/data/db/backup.test.js index f5c0be4e0c..f2ddd95e55 100644 --- a/ghost/core/test/unit/server/data/db/backup.test.js +++ b/ghost/core/test/unit/server/data/db/backup.test.js @@ -4,6 +4,7 @@ const fs = require('fs-extra'); const models = require('../../../../../core/server/models'); const exporter = require('../../../../../core/server/data/exporter'); const dbBackup = require('../../../../../core/server/data/db/backup'); +const configUtils = require('../../../../utils/configUtils'); describe('Backup', function () { let exportStub; @@ -33,4 +34,16 @@ describe('Backup', function () { done(); }).catch(done); }); + + it('should not create a backup JSON file if disabled', function (done) { + configUtils.set('disableJSBackups', true); + + dbBackup.backup().then(function () { + exportStub.called.should.be.false(); + filenameStub.called.should.be.false(); + fsStub.called.should.be.false(); + + done(); + }).catch(done); + }); });