2957b0175e
closes #3252 - added `/ghost/api/v0.1/uploads/` endpoint - removed upload method from `controller/admin.js` - moved removal of temporary files from storage to endpoint (needed to account for failed uploads) - changed and moved tests - Oversight: I think that we use `.otherwise()` and `.catch()` a bit too extensive and mask the real error objects. We probably need an error handling strategy at some point in the future.
167 lines
6.1 KiB
JavaScript
167 lines
6.1 KiB
JavaScript
// # DB API
|
|
// API for DB operations
|
|
var dataExport = require('../data/export'),
|
|
dataImport = require('../data/import'),
|
|
dataProvider = require('../models'),
|
|
fs = require('fs-extra'),
|
|
when = require('when'),
|
|
nodefn = require('when/node'),
|
|
_ = require('lodash'),
|
|
path = require('path'),
|
|
validation = require('../data/validation'),
|
|
errors = require('../../server/errors'),
|
|
canThis = require('../permissions').canThis,
|
|
api = {},
|
|
db;
|
|
|
|
api.settings = require('./settings');
|
|
|
|
|
|
function isValidFile(type, ext) {
|
|
if (type === 'application/json' && ext === '.json') {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* ## DB API Methods
|
|
*
|
|
* **See:** [API Methods](index.js.html#api%20methods)
|
|
*/
|
|
db = {
|
|
/**
|
|
* ### Export Content
|
|
* Generate the JSON to export
|
|
*
|
|
* @public
|
|
* @param {{context}} options
|
|
* @returns {Promise} Ghost Export JSON format
|
|
*/
|
|
'exportContent': function (options) {
|
|
options = options || {};
|
|
|
|
// Export data, otherwise send error 500
|
|
return canThis(options.context).exportContent.db().then(function () {
|
|
return dataExport().then(function (exportedData) {
|
|
return when.resolve({ db: [exportedData] });
|
|
}).otherwise(function (error) {
|
|
return when.reject(new errors.InternalServerError(error.message || error));
|
|
});
|
|
}, function () {
|
|
return when.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
|
|
});
|
|
},
|
|
/**
|
|
* ### Import Content
|
|
* Import posts, tags etc from a JSON blob
|
|
*
|
|
* @public
|
|
* @param {{context}} options
|
|
* @returns {Promise} Success
|
|
*/
|
|
'importContent': function (options) {
|
|
options = options || {};
|
|
var databaseVersion,
|
|
type,
|
|
ext,
|
|
filepath;
|
|
|
|
return canThis(options.context).importContent.db().then(function () {
|
|
if (!options.importfile || !options.importfile.type || !options.importfile.path) {
|
|
return when.reject(new errors.NoPermissionError('Please select a file to import.'));
|
|
}
|
|
|
|
type = options.importfile.type;
|
|
ext = path.extname(options.importfile.name).toLowerCase();
|
|
filepath = options.importfile.path;
|
|
|
|
return when(isValidFile(options.importfile)).then(function (result) {
|
|
if (!result) {
|
|
return when.reject(new errors.UnsupportedMediaTypeError('Please select a .json file to import.'));
|
|
}
|
|
}).then(function () {
|
|
return api.settings.read({key: 'databaseVersion', context: { internal: true }}).then(function (response) {
|
|
var setting = response.settings[0];
|
|
|
|
return when(setting.value);
|
|
}, function () {
|
|
return when('002');
|
|
});
|
|
}).then(function (version) {
|
|
databaseVersion = version;
|
|
// Read the file contents
|
|
return nodefn.call(fs.readFile, filepath);
|
|
}).then(function (fileContents) {
|
|
var importData,
|
|
error = '';
|
|
|
|
// Parse the json data
|
|
try {
|
|
importData = JSON.parse(fileContents);
|
|
|
|
// if importData follows JSON-API format `{ db: [exportedData] }`
|
|
if (_.keys(importData).length === 1 && Array.isArray(importData.db)) {
|
|
importData = importData.db[0];
|
|
}
|
|
} catch (e) {
|
|
errors.logError(e, "API DB import content", "check that the import file is valid JSON.");
|
|
return when.reject(new errors.BadRequest("Failed to parse the import JSON file"));
|
|
}
|
|
|
|
if (!importData.meta || !importData.meta.version) {
|
|
return when.reject(new errors.ValidationError("Import data does not specify version", 'meta.version'));
|
|
}
|
|
|
|
_.each(_.keys(importData.data), function (tableName) {
|
|
_.each(importData.data[tableName], function (importValues) {
|
|
validation.validateSchema(tableName, importValues).catch(function (err) {
|
|
error += error !== '' ? '<br>' : '';
|
|
error += err.message;
|
|
});
|
|
});
|
|
});
|
|
|
|
if (error !== '') {
|
|
return when.reject(new Error(error));
|
|
}
|
|
// Import for the current version
|
|
return dataImport(databaseVersion, importData);
|
|
|
|
}).then(function importSuccess() {
|
|
return api.settings.updateSettingsCache();
|
|
}).then(function () {
|
|
return when.resolve({ db: [] });
|
|
}).finally(function () {
|
|
// Unlink the file after import
|
|
return nodefn.call(fs.unlink, filepath);
|
|
});
|
|
}, function () {
|
|
return when.reject(new errors.NoPermissionError('You do not have permission to import data. (no rights)'));
|
|
});
|
|
},
|
|
/**
|
|
* ### Delete All Content
|
|
* Remove all posts and tags
|
|
*
|
|
* @public
|
|
* @param {{context}} options
|
|
* @returns {Promise} Success
|
|
*/
|
|
'deleteAllContent': function (options) {
|
|
options = options || {};
|
|
|
|
return canThis(options.context).deleteAllContent.db().then(function () {
|
|
return when(dataProvider.deleteAllContent())
|
|
.then(function () {
|
|
return when.resolve({ db: [] });
|
|
}, function (error) {
|
|
return when.reject(new errors.InternalServerError(error.message || error));
|
|
});
|
|
}, function () {
|
|
return when.reject(new errors.NoPermissionError('You do not have permission to export data. (no rights)'));
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = db;
|