Ghost/core/server/api/schedules.js
Katharina Irrgang d81bc91bd2 Error creation (#7477)
refs #7116, refs #2001

- Changes the way Ghost errors are implemented to benefit from proper inheritance
- Moves all error definitions into a single file
- Changes the error constructor to take an options object, rather than needing the arguments to be passed in the correct order.
- Provides a wrapper so that any errors that haven't already been converted to GhostErrors get converted before they are displayed.

Summary of changes:

* 🐛  set NODE_ENV in config handler
*   add GhostError implementation (core/server/errors.js)
  - register all errors in one file
  - inheritance from GhostError
  - option pattern
* 🔥  remove all error files
*   wrap all errors into GhostError in case of HTTP
* 🎨  adaptions
  - option pattern for errors
  - use GhostError when needed
* 🎨  revert debug deletion and add TODO for error id's
2016-10-06 13:27:35 +01:00

86 lines
3.4 KiB
JavaScript

var _ = require('lodash'),
Promise = require('bluebird'),
moment = require('moment'),
config = require('../config'),
pipeline = require(config.get('paths').corePath + '/server/utils/pipeline'),
dataProvider = require(config.get('paths').corePath + '/server/models'),
i18n = require(config.get('paths').corePath + '/server/i18n'),
errors = require(config.get('paths').corePath + '/server/errors'),
apiPosts = require(config.get('paths').corePath + '/server/api/posts'),
utils = require('./utils');
/**
* publish a scheduled post
*
* object.force: you can force publishing a post in the past (for example if your service was down)
*/
exports.publishPost = function publishPost(object, options) {
if (_.isEmpty(options)) {
options = object || {};
object = {};
}
var post, publishedAtMoment,
publishAPostBySchedulerToleranceInMinutes = config.get('times').publishAPostBySchedulerToleranceInMinutes;
// CASE: only the scheduler client is allowed to publish (hardcoded because of missing client permission system)
if (!options.context || !options.context.client || options.context.client !== 'ghost-scheduler') {
return Promise.reject(new errors.NoPermissionError({message: i18n.t('errors.permissions.noPermissionToAction')}));
}
options.context = {internal: true};
return pipeline([
utils.validate('posts', {opts: utils.idDefaultOptions}),
function (cleanOptions) {
cleanOptions.status = 'scheduled';
return apiPosts.read(cleanOptions)
.then(function (result) {
post = result.posts[0];
publishedAtMoment = moment(post.published_at);
if (publishedAtMoment.diff(moment(), 'minutes') > publishAPostBySchedulerToleranceInMinutes) {
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.notFound')}));
}
if (publishedAtMoment.diff(moment(), 'minutes') < publishAPostBySchedulerToleranceInMinutes * -1 && object.force !== true) {
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.publishInThePast')}));
}
return apiPosts.edit({posts: [{status: 'published'}]}, _.pick(cleanOptions, ['context', 'id']));
});
}
], options);
};
/**
* get all scheduled posts/pages
* permission check not needed, because route is not exposed
*/
exports.getScheduledPosts = function readPosts(options) {
options = options || {};
options.context = {internal: true};
return pipeline([
utils.validate('posts', {opts: ['from', 'to']}),
function (cleanOptions) {
cleanOptions.filter = 'status:scheduled';
cleanOptions.columns = ['id', 'published_at', 'created_at'];
if (cleanOptions.from) {
cleanOptions.filter += '+created_at:>=\'' + moment(cleanOptions.from).format('YYYY-MM-DD HH:mm:ss') + '\'';
}
if (cleanOptions.to) {
cleanOptions.filter += '+created_at:<=\'' + moment(cleanOptions.to).format('YYYY-MM-DD HH:mm:ss') + '\'';
}
return dataProvider.Post.findAll(cleanOptions)
.then(function (result) {
return Promise.resolve({posts: result.models});
});
}
], options);
};