Ghost/core/server/api/settings.js
Sebastian Gierlinger 61e94a6e8b Use current user in models
closes #2058
- fixed apiContext as suggested in the issue
- added user to options object for models
- added api.users.register() for public registration
- changed models to use options.user for created_by, updated_by,
author_id and published_by
- added override to session model to avoid created_by and updated_by
values
- added user (id: 1) to tests
- added user (id: 1) for registration
- added user (id: 1) for import, fixtures and default settings
- added user (id: 1) for user update
- added user (id: 1) for settings update (dbHash, installedApps, update
check)
- updated bookshelf to version 0.6.8
2014-04-16 18:20:09 +02:00

234 lines
7.9 KiB
JavaScript

var _ = require('lodash'),
dataProvider = require('../models'),
when = require('when'),
errors = require('../errorHandling'),
config = require('../config'),
settings,
settingsObject,
settingsCollection,
settingsFilter,
updateSettingsCache,
readSettingsResult,
filterPaths,
// Holds cached settings
settingsCache = {};
// ### Helpers
// Turn a settings collection into a single object/hashmap
settingsObject = function (settings) {
if (_.isObject(settings)) {
return _.reduce(settings, function (res, item, key) {
if (_.isArray(item)) {
res[key] = item;
} else {
res[key] = item.value;
}
return res;
}, {});
}
return (settings.toJSON ? settings.toJSON() : settings).reduce(function (res, item) {
if (item.toJSON) { item = item.toJSON(); }
if (item.key) { res[item.key] = item.value; }
return res;
}, {});
};
// Turn an object into a collection
settingsCollection = function (settings) {
return _.map(settings, function (value, key) {
return { key: key, value: value };
});
};
// Filters an object based on a given filter object
settingsFilter = function (settings, filter) {
return _.object(_.filter(_.pairs(settings), function (setting) {
if (filter) {
return _.some(filter.split(','), function (f) {
return setting[1].type === f;
});
}
return true;
}));
};
// Maintain the internal cache of the settings object
updateSettingsCache = function (settings) {
settings = settings || {};
if (!_.isEmpty(settings)) {
_.map(settings, function (setting, key) {
settingsCache[key].value = setting.value;
});
} else {
return when(dataProvider.Settings.findAll()).then(function (result) {
return when(readSettingsResult(result)).then(function (s) {
settingsCache = s;
});
});
}
};
readSettingsResult = function (result) {
var settings = {};
return when(_.map(result.models, function (member) {
if (!settings.hasOwnProperty(member.attributes.key)) {
var val = {};
val.value = member.attributes.value;
val.type = member.attributes.type;
settings[member.attributes.key] = val;
}
})).then(function () {
return when(config().paths.availableThemes).then(function (themes) {
var res = filterPaths(themes, settings.activeTheme.value);
settings.availableThemes = {
value: res,
type: 'theme'
};
return settings;
});
}).then(function () {
return when(config().paths.availableApps).then(function (apps) {
var res = filterPaths(apps, JSON.parse(settings.activeApps.value));
settings.availableApps = {
value: res,
type: 'app'
};
return settings;
});
});
};
/**
* Normalizes paths read by require-tree so that the apps and themes modules can use them.
* Creates an empty array (res), and populates it with useful info about the read packages
* like name, whether they're active (comparison with the second argument), and if they
* have a package.json, that, otherwise false
* @param object paths as returned by require-tree()
* @param array/string active as read from the settings object
* @return array of objects with useful info about
* apps / themes
*/
filterPaths = function (paths, active) {
var pathKeys = Object.keys(paths),
res = [],
item;
// turn active into an array (so themes and apps can be checked the same)
if (!Array.isArray(active)) {
active = [active];
}
_.each(pathKeys, function (key) {
//do not include hidden files or _messages
if (key.indexOf('.') !== 0
&& key !== '_messages'
&& key !== 'README.md'
) {
item = {
name: key
};
if (paths[key].hasOwnProperty('package.json')) {
item.package = paths[key]['package.json'];
} else {
item.package = false;
}
if (_.indexOf(active, key) !== -1) {
item.active = true;
}
res.push(item);
}
});
return res;
};
settings = {
// #### Browse
// **takes:** options object
browse: function browse(options) {
// **returns:** a promise for a settings json object
if (settingsCache) {
return when(settingsCache).then(function (settings) {
//TODO: omit where type==core
return settingsObject(settingsFilter(settings, options.type));
}, errors.logAndThrowError);
}
},
// #### Read
// **takes:** either a json object containing a key, or a single key string
read: function read(options) {
if (_.isString(options)) {
options = { key: options };
}
if (settingsCache) {
return when(settingsCache[options.key]).then(function (setting) {
if (!setting) {
return when.reject({code: 404, message: 'Unable to find setting: ' + options.key});
}
var res = {};
res.key = options.key;
res.value = setting.value;
return res;
}, errors.logAndThrowError);
}
},
// #### Edit
// **takes:** either a json object representing a collection of settings, or a key and value pair
edit: function edit(key, value) {
var self = this,
type;
// Check for passing a collection of settings first
if (_.isObject(key)) {
//clean data
type = key.type;
delete key.type;
delete key.availableThemes;
delete key.availableApps;
key = settingsCollection(key);
return dataProvider.Settings.edit(key, {user: self.user}).then(function (result) {
result.models = result;
return when(readSettingsResult(result)).then(function (settings) {
updateSettingsCache(settings);
}).then(function () {
return config.theme.update(settings, config().url).then(function () {
return settingsObject(settingsFilter(settingsCache, type));
});
});
}).otherwise(function (error) {
return dataProvider.Settings.read(key.key).then(function (result) {
if (!result) {
return when.reject({code: 404, message: 'Unable to find setting: ' + key});
}
return when.reject({message: error.message});
});
});
}
return dataProvider.Settings.read(key).then(function (setting) {
if (!setting) {
return when.reject({code: 404, message: 'Unable to find setting: ' + key});
}
if (!_.isString(value)) {
value = JSON.stringify(value);
}
setting.set('value', value);
return dataProvider.Settings.edit(setting, {user: self.user}).then(function (result) {
settingsCache[_.first(result).attributes.key].value = _.first(result).attributes.value;
}).then(function () {
return config.theme.update(settings, config().url).then(function () {
return settingsObject(settingsCache);
});
}).otherwise(errors.logAndThrowError);
});
}
};
module.exports = settings;
module.exports.updateSettingsCache = updateSettingsCache;