Ghost/core/server/api/db.js
Jacob Gable 298077582b ACL and strict rules for Settings API
Ref #2061

- Add canThis permission checks to settings api calls
- Add strict rules about accessing core settings without internal: true
- Omit core settings in browse() call unless internal: true
- Update unit tests to call api.settings with contexts
- Add a couple unit tests for new scenarios
- Update all api.settings calls in the app to call with internal context
- Re-arrange permissions.init in server startup so config.theme.update
can access settings without permissions error
2014-05-07 10:56:03 -05:00

121 lines
5.1 KiB
JavaScript

var dataExport = require('../data/export'),
dataImport = require('../data/import'),
dataProvider = require('../models'),
fs = require('fs-extra'),
when = require('when'),
nodefn = require('when/node/function'),
_ = require('lodash'),
validation = require('../data/validation'),
errors = require('../../server/errorHandling'),
canThis = require('../permissions').canThis,
api = {},
db;
api.notifications = require('./notifications');
api.settings = require('./settings');
db = {
'exportContent': function () {
var self = this;
// Export data, otherwise send error 500
return canThis(self.user).exportContent.db().then(function () {
return dataExport().otherwise(function (error) {
return when.reject({type: 'InternalServerError', message: error.message || error});
});
}, function () {
return when.reject({type: 'NoPermission', message: 'You do not have permission to export data. (no rights)'});
});
},
'importContent': function (options) {
var databaseVersion,
self = this;
return canThis(self.user).importContent.db().then(function () {
if (!options.importfile || !options.importfile.path || options.importfile.name.indexOf('json') === -1) {
/**
* Notify of an error if it occurs
*
* - If there's no file (although if you don't select anything, the input is still submitted, so
* !req.files.importfile will always be false)
* - If there is no path
* - If the name doesn't have json in it
*/
return when.reject({type: 'InternalServerError', message: 'Please select a .json file to import.'});
}
return api.settings.read.call({ internal: true }, { key: 'databaseVersion' }).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, options.importfile.path);
}).then(function (fileContents) {
var importData,
error = '';
// Parse the json data
try {
importData = JSON.parse(fileContents);
} catch (e) {
errors.logError(e, "API DB import content", "check that the import file is valid JSON.");
return when.reject(new Error("Failed to parse the import JSON file"));
}
if (!importData.meta || !importData.meta.version) {
return when.reject(new Error("Import data does not specify version"));
}
_.each(_.keys(importData.data), function (tableName) {
_.each(importData.data[tableName], function (importValues) {
try {
validation.validateSchema(tableName, importValues);
} catch (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({message: 'Posts, tags and other data successfully imported'});
}).otherwise(function importFailure(error) {
return when.reject({type: 'InternalServerError', message: error.message || error});
}).finally(function () {
// Unlink the file after import
return nodefn.call(fs.unlink, options.importfile.path);
});
}, function () {
return when.reject({type: 'NoPermission', message: 'You do not have permission to export data. (no rights)'});
});
},
'deleteAllContent': function () {
var self = this;
return canThis(self.user).deleteAllContent.db().then(function () {
return when(dataProvider.deleteAllContent())
.then(function () {
return when.resolve({message: 'Successfully deleted all content from your blog.'});
}, function (error) {
return when.reject({message: error.message || error});
});
}, function () {
return when.reject({type: 'NoPermission', message: 'You do not have permission to export data. (no rights)'});
});
}
};
module.exports = db;