mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-24 06:35:49 +03:00
Merge pull request #728 from skattyadz/default-settings-validations
Conflicts: Gruntfile.js core/server.js core/server/data/default-settings.json core/test/unit/admin_spec.js
This commit is contained in:
commit
3fab1f708a
@ -144,6 +144,9 @@ Ghost.prototype.init = function () {
|
||||
instance.mail.init(self)
|
||||
).then(function () {
|
||||
return models.Settings.populateDefaults();
|
||||
}).then(function () {
|
||||
// Initialize plugins
|
||||
return self.initPlugins();
|
||||
}).then(function () {
|
||||
// Initialize the settings cache
|
||||
return self.updateSettingsCache();
|
||||
|
@ -1,62 +1,59 @@
|
||||
[
|
||||
{
|
||||
"key": "title",
|
||||
"value": "Ghost",
|
||||
"type": "blog"
|
||||
{
|
||||
"blog": {
|
||||
"title": {
|
||||
"default": "Ghost"
|
||||
},
|
||||
"description": {
|
||||
"default": "Just a blogging platform."
|
||||
},
|
||||
"logo": {
|
||||
"default": ""
|
||||
},
|
||||
"cover": {
|
||||
"default": ""
|
||||
},
|
||||
"defaultLang": {
|
||||
"default": "en",
|
||||
"validations": {
|
||||
"notNull": true
|
||||
}
|
||||
},
|
||||
"postsPerPage": {
|
||||
"default": "6",
|
||||
"validations": {
|
||||
"notNull": true,
|
||||
"isNumeric": true
|
||||
}
|
||||
},
|
||||
"forceI18n": {
|
||||
"default": "true",
|
||||
"validations": {
|
||||
"notNull": true,
|
||||
"isIn": ["true", "false"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "description",
|
||||
"value": "Just a blogging platform.",
|
||||
"type": "blog"
|
||||
"general": {
|
||||
"email": {
|
||||
"default": "ghost@example.com",
|
||||
"validations": {
|
||||
"notNull": true,
|
||||
"isEmail": true
|
||||
}
|
||||
},
|
||||
"activePlugins": {
|
||||
"default": ""
|
||||
},
|
||||
"activeTheme": {
|
||||
"default": "casper"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "email",
|
||||
"value": "ghost@example.com",
|
||||
"type": "general"
|
||||
},
|
||||
{
|
||||
"key": "activePlugins",
|
||||
"value": "",
|
||||
"type": "general"
|
||||
},
|
||||
{
|
||||
"key": "activeTheme",
|
||||
"value": "casper",
|
||||
"type": "general"
|
||||
},
|
||||
{
|
||||
"key": "currentVersion",
|
||||
"value": "002",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"key": "installedPlugins",
|
||||
"value": "[]",
|
||||
"type": "core"
|
||||
},
|
||||
{
|
||||
"key": "logo",
|
||||
"value": "",
|
||||
"type": "blog"
|
||||
},
|
||||
{
|
||||
"key": "cover",
|
||||
"value": "",
|
||||
"type": "blog"
|
||||
},
|
||||
{
|
||||
"key": "defaultLang",
|
||||
"value": "en",
|
||||
"type": "blog"
|
||||
},
|
||||
{
|
||||
"key": "forceI18n",
|
||||
"value": true,
|
||||
"type": "blog"
|
||||
},
|
||||
{
|
||||
"key": "postsPerPage",
|
||||
"value": "6",
|
||||
"type": "blog"
|
||||
"core": {
|
||||
"currentVersion": {
|
||||
"default": "000"
|
||||
},
|
||||
"installedPlugins": {
|
||||
"default": "[]"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,10 +1,31 @@
|
||||
var Settings,
|
||||
GhostBookshelf = require('./base'),
|
||||
validator = GhostBookshelf.validator,
|
||||
uuid = require('node-uuid'),
|
||||
_ = require('underscore'),
|
||||
errors = require('../errorHandling'),
|
||||
when = require('when'),
|
||||
defaultSettings = require('../data/default-settings.json');
|
||||
defaultSettings;
|
||||
|
||||
// For neatness, the defaults file is split into categories.
|
||||
// It's much easier for us to work with it as a single level
|
||||
// instead of iterating those categories every time
|
||||
function parseDefaultSettings() {
|
||||
var defaultSettingsInCategories = require('../data/default-settings.json'),
|
||||
defaultSettingsFlattened = {};
|
||||
|
||||
|
||||
_.each(defaultSettingsInCategories, function (settings, categoryName) {
|
||||
_.each(settings, function (setting, settingName) {
|
||||
setting.type = categoryName;
|
||||
setting.key = settingName;
|
||||
defaultSettingsFlattened[settingName] = setting;
|
||||
});
|
||||
});
|
||||
|
||||
return defaultSettingsFlattened;
|
||||
}
|
||||
defaultSettings = parseDefaultSettings();
|
||||
|
||||
// Each setting is saved as a separate row in the database,
|
||||
// but the overlying API treats them as a single key:value mapping
|
||||
@ -28,10 +49,36 @@ Settings = GhostBookshelf.Model.extend({
|
||||
this.on('saving', this.validate, this);
|
||||
},
|
||||
|
||||
// Validate default settings using the validator module.
|
||||
// Each validation's key is a name and its value is an array of options
|
||||
// Use true (boolean) if options aren't applicable
|
||||
//
|
||||
// eg:
|
||||
// validations: { isUrl: true, len: [20, 40] }
|
||||
//
|
||||
// will validate that a setting's length is a URL between 20 and 40 chars,
|
||||
// available validators: https://github.com/chriso/node-validator#list-of-validation-methods
|
||||
validate: function () {
|
||||
// TODO: validate value, check type is one of the allowed values etc
|
||||
GhostBookshelf.validator.check(this.get('key'), "Setting key cannot be blank").notEmpty();
|
||||
GhostBookshelf.validator.check(this.get('type'), "Setting type cannot be blank").notEmpty();
|
||||
validator.check(this.get('key'), "Setting key cannot be blank").notEmpty();
|
||||
validator.check(this.get('type'), "Setting type cannot be blank").notEmpty();
|
||||
|
||||
var matchingDefault = defaultSettings[this.get('key')];
|
||||
|
||||
if (matchingDefault && matchingDefault.validations) {
|
||||
_.each(matchingDefault.validations, function (validationOptions, validationName) {
|
||||
var validation = validator.check(this.get('value'));
|
||||
|
||||
if (validationOptions === true) {
|
||||
validationOptions = null;
|
||||
}
|
||||
if (typeof validationOptions !== 'array') {
|
||||
validationOptions = [validationOptions];
|
||||
}
|
||||
|
||||
// equivalent of validation.isSomething(option1, option2)
|
||||
validation[validationName].apply(validation, validationOptions);
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
saving: function () {
|
||||
@ -72,9 +119,10 @@ Settings = GhostBookshelf.Model.extend({
|
||||
var usedKeys = allSettings.models.map(function (setting) { return setting.get('key'); }),
|
||||
insertOperations = [];
|
||||
|
||||
defaultSettings.forEach(function (defaultSetting) {
|
||||
var isMissingFromDB = usedKeys.indexOf(defaultSetting.key) === -1;
|
||||
_.each(defaultSettings, function (defaultSetting, defaultSettingKey) {
|
||||
var isMissingFromDB = usedKeys.indexOf(defaultSettingKey) === -1;
|
||||
if (isMissingFromDB) {
|
||||
defaultSetting.value = defaultSetting.default;
|
||||
insertOperations.push(Settings.forge(defaultSetting).save());
|
||||
}
|
||||
});
|
||||
|
@ -38,6 +38,7 @@ describe('Admin Controller', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('valid file', function() {
|
||||
|
||||
var clock;
|
||||
|
@ -83,4 +83,4 @@ testUtils = {
|
||||
|
||||
};
|
||||
|
||||
module.exports = testUtils;
|
||||
module.exports = testUtils;
|
||||
|
Loading…
Reference in New Issue
Block a user