0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Backup endpoint improvements (#9365)

closes #9297

- backup endpoint returns JSON
- allows setting of export filename
- DRY up code
- the endpoint is not documented, no breaking change
This commit is contained in:
David Wolfe 2018-01-11 15:03:21 +00:00 committed by Katharina Irrgang
parent b9d3f45402
commit b69b9780a9
4 changed files with 44 additions and 19 deletions

View file

@ -1,17 +1,13 @@
// # DB API // # DB API
// API for DB operations // API for DB operations
var Promise = require('bluebird'), var Promise = require('bluebird'),
path = require('path'),
fs = require('fs-extra'),
pipeline = require('../lib/promise/pipeline'), pipeline = require('../lib/promise/pipeline'),
localUtils = require('./utils'), localUtils = require('./utils'),
exporter = require('../data/export'), exporter = require('../data/export'),
importer = require('../data/importer'), importer = require('../data/importer'),
backupDatabase = require('../data/db/backup'), backupDatabase = require('../data/db/backup'),
models = require('../models'), models = require('../models'),
config = require('../config'),
common = require('../lib/common'), common = require('../lib/common'),
urlService = require('../services/url'),
docName = 'db', docName = 'db',
db; db;
@ -23,26 +19,26 @@ var Promise = require('bluebird'),
db = { db = {
/** /**
* ### Archive Content * ### Archive Content
* Generate the JSON to export - for Moya only * Generate the JSON to export
* *
* @public * @public
* @returns {Promise} Ghost Export JSON format * @returns {Promise} Ghost Export JSON format
*/ */
backupContent: function () { backupContent: function (options) {
var props = { var tasks;
data: exporter.doExport(),
filename: exporter.fileName()
};
return Promise.props(props) options = options || {};
.then(function successMessage(exportResult) {
var filename = path.resolve(urlService.utils.urlJoin(config.get('paths').contentPath, 'data', exportResult.filename));
return fs.writeFile(filename, JSON.stringify(exportResult.data)) function jsonResponse(filename) {
.then(function () { return {db: [{filename: filename}]};
return filename; }
});
}); tasks = [
backupDatabase,
jsonResponse
];
return pipeline(tasks, options);
}, },
/** /**
* ### Export Content * ### Export Content

View file

@ -35,6 +35,7 @@ backup = function backup(options) {
.then(writeExportFile) .then(writeExportFile)
.then(function successMessage(filename) { .then(function successMessage(filename) {
common.logging.info('Database backup written to: ' + filename); common.logging.info('Database backup written to: ' + filename);
return filename;
}); });
}; };

View file

@ -21,6 +21,13 @@ exportFileName = function exportFileName(options) {
var datetime = (new Date()).toJSON().substring(0, 10), var datetime = (new Date()).toJSON().substring(0, 10),
title = ''; title = '';
options = options || {};
// custom filename
if (options.filename) {
return Promise.resolve(options.filename + '.json');
}
return models.Settings.findOne({key: 'title'}, _.merge({}, modelOptions, options)).then(function (result) { return models.Settings.findOne({key: 'title'}, _.merge({}, modelOptions, options)).then(function (result) {
if (result) { if (result) {
title = security.string.safe(result.get('value')) + '.'; title = security.string.safe(result.get('value')) + '.';

View file

@ -116,7 +116,28 @@ describe('DB API', function () {
if (err) { if (err) {
return done(err); return done(err);
} }
res.body.should.match(/data/);
(typeof res.body).should.be.Object;
should.exist(res.body.db[0].filename);
fsStub.calledOnce.should.eql(true);
done();
});
});
it('export can be triggered and named by backup client', function (done) {
backupQuery = '?client_id=' + backupClient.slug + '&client_secret=' + backupClient.secret + '&filename=test';
fsStub = sandbox.stub(fs, 'writeFile').resolves();
request.post(testUtils.API.getApiQuery('db/backup' + backupQuery))
.expect('Content-Type', /json/)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
(typeof res.body).should.be.Object;
res.body.db[0].filename.should.match(/test\.json/);
fsStub.calledOnce.should.eql(true); fsStub.calledOnce.should.eql(true);
done(); done();