From 3f07b05a63cbaa94dd02a26b66a83901e0bdab3c Mon Sep 17 00:00:00 2001 From: Austin Burdine Date: Tue, 2 Jun 2020 20:26:13 -0400 Subject: [PATCH] feat(sqlite): ensure sqlite db path is absolute - ensure dbpath argument is absolute by default - add migration to make relative sqlite paths absolute --- lib/migrations.js | 20 +++++++++++-- lib/tasks/configure/options.js | 8 ++++-- test/unit/migrations-spec.js | 34 +++++++++++++++++++++-- test/unit/tasks/configure/options-spec.js | 5 ++-- 4 files changed, 57 insertions(+), 10 deletions(-) diff --git a/lib/migrations.js b/lib/migrations.js index a1b345af0..8dce416a2 100644 --- a/lib/migrations.js +++ b/lib/migrations.js @@ -1,7 +1,6 @@ -'use strict'; +const path = require('path'); async function ensureSettingsFolder(context) { - const path = require('path'); const ghostUser = require('./utils/use-ghost-user'); const contentDir = context.instance.config.get('paths.contentPath'); @@ -14,8 +13,25 @@ async function ensureSettingsFolder(context) { } } +async function makeSqliteAbsolute({instance}) { + const configs = await instance.getAvailableConfigs(); + + Object.values(configs).forEach((config) => { + const currentFilename = config.get('database.connection.filename', null); + if (!currentFilename || path.isAbsolute(currentFilename)) { + return; + } + + config.set('database.connection.filename', path.resolve(instance.dir, currentFilename)).save(); + }); +} + module.exports = [{ before: '1.7.0', title: 'Create content/settings directory', task: ensureSettingsFolder +}, { + before: '1.14.1', + title: 'Fix Sqlite DB path', + task: makeSqliteAbsolute }]; diff --git a/lib/tasks/configure/options.js b/lib/tasks/configure/options.js index 77f3c69ff..ce063e81d 100644 --- a/lib/tasks/configure/options.js +++ b/lib/tasks/configure/options.js @@ -1,10 +1,10 @@ -'use strict'; // Advanced options for the config command const portfinder = require('portfinder'); const toString = require('lodash/toString'); const validator = require('validator'); const urlUtils = require('../../utils/url'); const url = require('url'); +const path = require('path'); const BASE_PORT = 2368; const knownMailServices = [ @@ -24,6 +24,7 @@ module.exports = { description: 'Site domain E.g. loveghost.com', validate: urlUtils.validate, transform: urlUtils.ensureProtocol, + type: 'string', group: 'Ghost Options:' }, @@ -83,8 +84,9 @@ module.exports = { } const dbFile = (environment === 'production') ? 'ghost.db' : 'ghost-dev.db'; - return `./content/data/${dbFile}`; - } + return path.resolve(`./content/data/${dbFile}`); + }, + transform: path.resolve }, dbhost: { description: 'Database host', diff --git a/test/unit/migrations-spec.js b/test/unit/migrations-spec.js index d98d294f0..325d70fec 100644 --- a/test/unit/migrations-spec.js +++ b/test/unit/migrations-spec.js @@ -1,6 +1,4 @@ -'use strict'; - -const expect = require('chai').expect; +const {expect} = require('chai'); const sinon = require('sinon'); const createConfig = require('../utils/config-stub'); @@ -53,4 +51,34 @@ describe('Unit: Migrations', function () { }); }); }); + + it('makeSqliteAbsolute makes sqlite filepaths absolute', async () => { + const configs = { + development: createConfig(), + staging: createConfig(), + production: createConfig() + }; + + configs.development.get.withArgs('database.connection.filename', null).returns('./content/data/ghost.db'); + configs.staging.get.withArgs('database.connection.filename', null).returns('/absolute/path/content/data/ghost.db'); + configs.production.get.withArgs('database.connection.filename', null).returns(null); + + const instance = { + getAvailableConfigs: sinon.stub().resolves(configs), + dir: '/test/instance/dir' + }; + + await migrations[1].task({instance}); + + expect(instance.getAvailableConfigs.calledOnce).to.be.true; + expect(configs.development.get.calledOnce).to.be.true; + expect(configs.development.set.calledWithExactly('database.connection.filename', '/test/instance/dir/content/data/ghost.db')).to.be.true; + expect(configs.development.save.calledOnce).to.be.true; + expect(configs.staging.get.calledOnce).to.be.true; + expect(configs.staging.set.called).to.be.false; + expect(configs.staging.save.called).to.be.false; + expect(configs.production.get.calledOnce).to.be.true; + expect(configs.production.set.called).to.be.false; + expect(configs.production.save.called).to.be.false; + }); }); diff --git a/test/unit/tasks/configure/options-spec.js b/test/unit/tasks/configure/options-spec.js index ace8d7f0c..faca2d936 100644 --- a/test/unit/tasks/configure/options-spec.js +++ b/test/unit/tasks/configure/options-spec.js @@ -2,6 +2,7 @@ const {expect} = require('chai'); const sinon = require('sinon'); const proxyquire = require('proxyquire'); const Promise = require('bluebird'); +const path = require('path'); const options = require('../../../../lib/tasks/configure/options'); const urlUtils = require('../../../../lib/utils/url'); @@ -64,8 +65,8 @@ describe('Unit: Tasks: Configure > options', function () { it('dbpath', function () { expect(options.dbpath).to.exist; expect(options.dbpath.defaultValue({get: () => 'mysql'})).to.be.null; - expect(options.dbpath.defaultValue({get: () => 'sqlite3'}, 'development')).to.equal('./content/data/ghost-dev.db'); - expect(options.dbpath.defaultValue({get: () => 'sqlite3'}, 'production')).to.equal('./content/data/ghost.db'); + expect(options.dbpath.defaultValue({get: () => 'sqlite3'}, 'development')).to.equal(path.resolve('./content/data/ghost-dev.db')); + expect(options.dbpath.defaultValue({get: () => 'sqlite3'}, 'production')).to.equal(path.resolve('./content/data/ghost.db')); }); it('mail', function () {