Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
// # Settings API
|
2014-06-03 17:05:25 +04:00
|
|
|
// RESTful API for the Setting resource
|
2018-09-18 16:59:56 +03:00
|
|
|
const Promise = require('bluebird'),
|
2017-09-12 18:31:14 +03:00
|
|
|
_ = require('lodash'),
|
2018-07-12 14:40:37 +03:00
|
|
|
moment = require('moment-timezone'),
|
|
|
|
fs = require('fs-extra'),
|
|
|
|
path = require('path'),
|
2018-09-27 17:06:57 +03:00
|
|
|
config = require('../../config'),
|
|
|
|
models = require('../../models'),
|
|
|
|
canThis = require('../../services/permissions').canThis,
|
2017-12-14 00:14:19 +03:00
|
|
|
localUtils = require('./utils'),
|
2018-09-27 17:06:57 +03:00
|
|
|
urlService = require('../../services/url'),
|
|
|
|
common = require('../../lib/common'),
|
|
|
|
settingsCache = require('../../services/settings/cache'),
|
2018-09-18 16:59:56 +03:00
|
|
|
docName = 'settings';
|
|
|
|
|
|
|
|
let settings,
|
2017-11-01 16:44:54 +03:00
|
|
|
settingsFilter,
|
2014-04-28 03:28:50 +04:00
|
|
|
settingsResult,
|
2017-11-01 16:44:54 +03:00
|
|
|
canEditAllSettings;
|
2013-12-06 12:51:35 +04:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
// ## Helpers
|
2014-04-28 03:28:50 +04:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* ### Settings Filter
|
|
|
|
* Filters an object based on a given filter object
|
|
|
|
* @private
|
2014-09-10 08:06:24 +04:00
|
|
|
* @param {Object} settings
|
|
|
|
* @param {String} filter
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
settingsFilter = (settings, filter) => {
|
2019-01-02 22:18:19 +03:00
|
|
|
let filteredTypes = filter ? filter.split(',') : false;
|
|
|
|
return _.filter(settings, (setting) => {
|
|
|
|
if (filteredTypes) {
|
|
|
|
return _.includes(filteredTypes, setting.type);
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
}
|
2019-01-02 22:18:19 +03:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
return true;
|
2019-01-02 22:18:19 +03:00
|
|
|
});
|
2014-02-23 16:32:35 +04:00
|
|
|
};
|
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
2017-03-03 01:00:01 +03:00
|
|
|
* ### Settings Result
|
2017-03-02 19:53:48 +03:00
|
|
|
*
|
2017-03-03 01:00:01 +03:00
|
|
|
* Takes a keyed JSON object
|
2017-03-02 19:53:48 +03:00
|
|
|
* E.g.
|
2017-04-24 20:41:00 +03:00
|
|
|
* db_hash: {
|
2017-03-02 19:53:48 +03:00
|
|
|
* id: '123abc',
|
|
|
|
* key: 'dbash',
|
|
|
|
* value: 'xxxx',
|
|
|
|
* type: 'core',
|
|
|
|
* timestamps
|
|
|
|
* }
|
|
|
|
*
|
2017-03-03 01:00:01 +03:00
|
|
|
* Performs a filter, based on the `type`
|
|
|
|
* And converts the remaining items to our API format by adding a `setting` and `meta` keys.
|
|
|
|
*
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @private
|
2017-03-03 01:00:01 +03:00
|
|
|
* @param {Object} settings - a keyed JSON object
|
2014-09-10 08:06:24 +04:00
|
|
|
* @param {String} type
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @returns {{settings: *}}
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
settingsResult = (settings, type) => {
|
|
|
|
let filteredSettings = _.values(settingsFilter(settings, type)),
|
2014-04-28 03:28:50 +04:00
|
|
|
result = {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
settings: filteredSettings,
|
|
|
|
meta: {}
|
2014-04-28 03:28:50 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (type) {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
result.meta.filters = {
|
|
|
|
type: type
|
2014-04-28 03:28:50 +04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* ### Can Edit All Settings
|
|
|
|
* Check that this edit request is allowed for all settings requested to be updated
|
|
|
|
* @private
|
2014-09-10 08:06:24 +04:00
|
|
|
* @param {Object} settingsInfo
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
canEditAllSettings = (settingsInfo, options) => {
|
|
|
|
let checkSettingPermissions = (setting) => {
|
2014-06-17 19:36:47 +04:00
|
|
|
if (setting.type === 'core' && !(options.context && options.context.internal)) {
|
2014-08-17 10:17:23 +04:00
|
|
|
return Promise.reject(
|
2017-12-12 00:47:46 +03:00
|
|
|
new common.errors.NoPermissionError({message: common.i18n.t('errors.api.settings.accessCoreSettingFromExtReq')})
|
2014-06-17 19:36:47 +04:00
|
|
|
);
|
|
|
|
}
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
return canThis(options.context).edit.setting(setting.key).catch(() => {
|
2017-12-12 00:47:46 +03:00
|
|
|
return Promise.reject(new common.errors.NoPermissionError({message: common.i18n.t('errors.api.settings.noPermissionToEditSettings')}));
|
2014-07-30 05:25:53 +04:00
|
|
|
});
|
2014-06-17 19:36:47 +04:00
|
|
|
},
|
2018-09-18 16:59:56 +03:00
|
|
|
checks = settingsInfo.map((settingInfo) => {
|
|
|
|
let setting = settingsCache.get(settingInfo.key, {resolve: false});
|
2014-06-17 19:36:47 +04:00
|
|
|
|
|
|
|
if (!setting) {
|
2017-12-12 00:47:46 +03:00
|
|
|
return Promise.reject(new common.errors.NotFoundError(
|
|
|
|
{message: common.i18n.t('errors.api.settings.problemFindingSetting', {key: settingInfo.key})}
|
2017-02-27 18:53:04 +03:00
|
|
|
));
|
2014-06-17 19:36:47 +04:00
|
|
|
}
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
|
2017-04-24 20:41:00 +03:00
|
|
|
if (setting.key === 'active_theme') {
|
2017-03-13 14:44:44 +03:00
|
|
|
return Promise.reject(
|
2017-12-12 00:47:46 +03:00
|
|
|
new common.errors.BadRequestError({
|
|
|
|
message: common.i18n.t('errors.api.settings.activeThemeSetViaAPI.error'),
|
|
|
|
help: common.i18n.t('errors.api.settings.activeThemeSetViaAPI.help')
|
2017-03-13 14:44:44 +03:00
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-06-17 19:36:47 +04:00
|
|
|
return checkSettingPermissions(setting);
|
|
|
|
});
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
|
2014-08-17 10:17:23 +04:00
|
|
|
return Promise.all(checks);
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
};
|
|
|
|
|
2014-06-03 17:05:25 +04:00
|
|
|
/**
|
|
|
|
* ## Settings API Methods
|
|
|
|
*
|
2017-12-14 16:13:40 +03:00
|
|
|
* **See:** [API Methods](constants.js.html#api%20methods)
|
2014-06-03 17:05:25 +04:00
|
|
|
*/
|
2013-12-06 12:51:35 +04:00
|
|
|
settings = {
|
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* ### Browse
|
2014-09-10 08:06:24 +04:00
|
|
|
* @param {Object} options
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
browse(options) {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
options = options || {};
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
let result = settingsResult(settingsCache.getAll(), options.type);
|
2014-05-07 04:49:25 +04:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
// If there is no context, return only blog settings
|
|
|
|
if (!options.context) {
|
2018-09-18 16:59:56 +03:00
|
|
|
return Promise.resolve(result.settings.filter((setting) => {
|
2017-12-12 00:47:46 +03:00
|
|
|
return setting.type === 'blog';
|
|
|
|
}));
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
}
|
2014-05-07 04:49:25 +04:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
// Otherwise return whatever this context is allowed to browse
|
2018-09-18 16:59:56 +03:00
|
|
|
return canThis(options.context).browse.setting().then(() => {
|
2014-05-07 04:49:25 +04:00
|
|
|
// Omit core settings unless internal request
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
if (!options.context.internal) {
|
2018-09-18 16:59:56 +03:00
|
|
|
result.settings = result.settings.filter((setting) => {
|
2018-08-06 18:18:59 +03:00
|
|
|
return setting.type !== 'core' && setting.key !== 'permalinks';
|
2017-12-12 00:47:46 +03:00
|
|
|
});
|
2014-05-07 04:49:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
});
|
2013-12-06 12:51:35 +04:00
|
|
|
},
|
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* ### Read
|
2014-09-10 08:06:24 +04:00
|
|
|
* @param {Object} options
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @returns {*}
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
read(options) {
|
2013-12-06 12:51:35 +04:00
|
|
|
if (_.isString(options)) {
|
2014-09-10 08:06:24 +04:00
|
|
|
options = {key: options};
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
let setting = settingsCache.get(options.key, {resolve: false}),
|
2017-02-27 18:53:04 +03:00
|
|
|
result = {};
|
2014-05-07 04:49:25 +04:00
|
|
|
|
2017-02-27 18:53:04 +03:00
|
|
|
if (!setting) {
|
2017-12-12 00:47:46 +03:00
|
|
|
return Promise.reject(new common.errors.NotFoundError(
|
|
|
|
{message: common.i18n.t('errors.api.settings.problemFindingSetting', {key: options.key})}
|
2017-02-27 18:53:04 +03:00
|
|
|
));
|
|
|
|
}
|
2014-05-07 04:49:25 +04:00
|
|
|
|
2017-02-27 18:53:04 +03:00
|
|
|
result[options.key] = setting;
|
2014-06-17 19:36:47 +04:00
|
|
|
|
2017-02-27 18:53:04 +03:00
|
|
|
if (setting.type === 'core' && !(options.context && options.context.internal)) {
|
|
|
|
return Promise.reject(
|
2017-12-12 00:47:46 +03:00
|
|
|
new common.errors.NoPermissionError({message: common.i18n.t('errors.api.settings.accessCoreSettingFromExtReq')})
|
2017-02-27 18:53:04 +03:00
|
|
|
);
|
|
|
|
}
|
Consistency in model method naming
- The API has the BREAD naming for methods
- The model now has findAll, findOne, findPage (where needed), edit, add and destroy, meaning it is similar but with a bit more flexibility
- browse, read, update, create, and delete, which were effectively just aliases, have all been removed.
- added jsDoc for the model methods
2014-05-05 19:18:38 +04:00
|
|
|
|
2018-08-06 18:18:59 +03:00
|
|
|
if (setting.key === 'permalinks') {
|
|
|
|
return Promise.reject(new common.errors.NotFoundError({
|
|
|
|
message: common.i18n.t('errors.errors.resourceNotFound')
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2017-02-27 18:53:04 +03:00
|
|
|
if (setting.type === 'blog') {
|
|
|
|
return Promise.resolve(settingsResult(result));
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
}
|
2014-04-28 03:28:50 +04:00
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
return canThis(options.context).read.setting(options.key).then(() => {
|
2017-02-27 18:53:04 +03:00
|
|
|
return settingsResult(result);
|
2018-09-18 16:59:56 +03:00
|
|
|
}, () => {
|
2017-12-12 00:47:46 +03:00
|
|
|
return Promise.reject(new common.errors.NoPermissionError({message: common.i18n.t('errors.api.settings.noPermissionToReadSettings')}));
|
2017-02-27 18:53:04 +03:00
|
|
|
});
|
2013-12-06 12:51:35 +04:00
|
|
|
},
|
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
/**
|
|
|
|
* ### Edit
|
2015-12-02 10:28:36 +03:00
|
|
|
* Update properties of a setting
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
* @param {{settings: }} object Setting or a single string name
|
|
|
|
* @param {{id (required), include,...}} options (optional) or a single string value
|
|
|
|
* @return {Promise(Setting)} Edited Setting
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
edit(object, options) {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
options = options || {};
|
2018-09-18 16:59:56 +03:00
|
|
|
let type;
|
2014-04-03 17:03:09 +04:00
|
|
|
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
// Allow shorthand syntax where a single key and value are passed to edit instead of object and options
|
|
|
|
if (_.isString(object)) {
|
2014-09-10 08:06:24 +04:00
|
|
|
object = {settings: [{key: object, value: options}]};
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
2014-04-28 03:28:50 +04:00
|
|
|
|
2014-09-10 08:06:24 +04:00
|
|
|
// clean data
|
2018-09-18 16:59:56 +03:00
|
|
|
object.settings.forEach((setting) => {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
if (!_.isString(setting.value)) {
|
|
|
|
setting.value = JSON.stringify(setting.value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
type = object.settings.find((setting) => {
|
2017-12-12 00:47:46 +03:00
|
|
|
return setting.key === 'type';
|
|
|
|
});
|
2018-08-06 18:18:59 +03:00
|
|
|
|
2014-05-06 22:52:11 +04:00
|
|
|
if (_.isObject(type)) {
|
|
|
|
type = type.value;
|
|
|
|
}
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
object.settings = _.reject(object.settings, (setting) => {
|
2017-03-02 19:53:48 +03:00
|
|
|
return setting.key === 'type';
|
2014-05-06 22:52:11 +04:00
|
|
|
});
|
|
|
|
|
2018-08-06 18:18:59 +03:00
|
|
|
if (object.settings[0].key === 'permalinks') {
|
|
|
|
return Promise.reject(new common.errors.NotFoundError({
|
|
|
|
message: common.i18n.t('errors.errors.resourceNotFound')
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
return canEditAllSettings(object.settings, options).then(() => {
|
|
|
|
return localUtils.checkObject(object, docName).then((checkedData) => {
|
2017-09-12 18:31:14 +03:00
|
|
|
return models.Settings.edit(checkedData.settings, options);
|
2018-09-18 16:59:56 +03:00
|
|
|
}).then((settingsModelsArray) => {
|
2017-03-03 01:00:01 +03:00
|
|
|
// Instead of a standard bookshelf collection, Settings.edit returns an array of Settings Models.
|
|
|
|
// We convert this to JSON, by calling toJSON on each Model (using invokeMap for ease)
|
|
|
|
// We use keyBy to create an object that uses the 'key' as a key for each setting.
|
2018-09-18 16:59:56 +03:00
|
|
|
let settingsKeyedJSON = _.keyBy(_.invokeMap(settingsModelsArray, 'toJSON'), 'key');
|
2017-03-03 01:00:01 +03:00
|
|
|
return settingsResult(settingsKeyedJSON, type);
|
2014-05-06 22:52:11 +04:00
|
|
|
});
|
2013-12-06 12:51:35 +04:00
|
|
|
});
|
2018-07-12 14:40:37 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The `routes.yaml` file offers a way to configure your Ghost blog. It's currently a setting feature
|
|
|
|
* we have added. That's why the `routes.yaml` file is treated as a "setting" right now.
|
|
|
|
* If we want to add single permissions for this file (e.g. upload/download routes.yaml), we can add later.
|
|
|
|
*
|
|
|
|
* How does it work?
|
|
|
|
*
|
|
|
|
* - we first reset all url generators (each url generator belongs to one express router)
|
|
|
|
* - we don't destroy the resources, we only release them (this avoids reloading all resources from the db again)
|
|
|
|
* - then we reload the whole site app, which will reset all routers and re-create the url generators
|
|
|
|
*/
|
2018-09-18 16:59:56 +03:00
|
|
|
upload(options) {
|
2018-07-12 14:40:37 +03:00
|
|
|
const backupRoutesPath = path.join(config.getContentPath('settings'), `routes-${moment().format('YYYY-MM-DD-HH-mm-ss')}.yaml`);
|
|
|
|
|
|
|
|
return localUtils.handlePermissions('settings', 'edit')(options)
|
|
|
|
.then(() => {
|
2018-09-18 16:59:56 +03:00
|
|
|
return fs.copy(`${config.getContentPath('settings')}/routes.yaml`, backupRoutesPath);
|
2018-07-12 14:40:37 +03:00
|
|
|
})
|
|
|
|
.then(() => {
|
2018-09-18 16:59:56 +03:00
|
|
|
return fs.copy(options.path, `${config.getContentPath('settings')}/routes.yaml`);
|
2018-07-12 14:40:37 +03:00
|
|
|
})
|
|
|
|
.then(() => {
|
|
|
|
urlService.resetGenerators({releaseResourcesOnly: true});
|
|
|
|
})
|
|
|
|
.then(() => {
|
2018-09-27 17:06:57 +03:00
|
|
|
const siteApp = require('../../web/site/app');
|
2018-07-12 14:40:37 +03:00
|
|
|
|
|
|
|
try {
|
|
|
|
return siteApp.reload();
|
|
|
|
} catch (err) {
|
|
|
|
// bring back backup, otherwise your Ghost blog is broken
|
2018-09-18 16:59:56 +03:00
|
|
|
return fs.copy(backupRoutesPath, `${config.getContentPath('settings')}/routes.yaml`)
|
2018-07-12 14:40:37 +03:00
|
|
|
.then(() => {
|
|
|
|
return siteApp.reload();
|
|
|
|
})
|
|
|
|
.then(() => {
|
|
|
|
throw err;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2018-09-18 16:59:56 +03:00
|
|
|
download(options) {
|
2018-07-12 14:40:37 +03:00
|
|
|
const routesPath = path.join(config.getContentPath('settings'), 'routes.yaml');
|
|
|
|
|
|
|
|
return localUtils.handlePermissions('settings', 'browse')(options)
|
|
|
|
.then(() => {
|
|
|
|
return fs.readFile(routesPath, 'utf-8');
|
|
|
|
})
|
2018-09-18 16:59:56 +03:00
|
|
|
.catch((err) => {
|
2018-07-12 14:40:37 +03:00
|
|
|
if (err.code === 'ENOENT') {
|
|
|
|
return Promise.resolve([]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (common.errors.utils.isIgnitionError(err)) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new common.errors.NotFoundError({
|
|
|
|
err: err
|
|
|
|
});
|
|
|
|
});
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = settings;
|