mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Removed method complexity in schedules API controller
refs https://github.com/TryGhost/Team/issues/694 - The controller code is not meant to contain complex business logic.
This commit is contained in:
parent
00460c96f4
commit
7b53a61b73
2 changed files with 105 additions and 57 deletions
|
@ -1,11 +1,6 @@
|
||||||
const _ = require('lodash');
|
|
||||||
const moment = require('moment');
|
|
||||||
const config = require('../../../shared/config');
|
|
||||||
const models = require('../../models');
|
const models = require('../../models');
|
||||||
const urlUtils = require('../../../shared/url-utils');
|
|
||||||
const i18n = require('../../../shared/i18n');
|
const postSchedulingService = require('../../services/posts/post-scheduling-service')('canary');
|
||||||
const errors = require('@tryghost/errors');
|
|
||||||
const api = require('./index');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
docName: 'schedules',
|
docName: 'schedules',
|
||||||
|
@ -32,11 +27,8 @@ module.exports = {
|
||||||
permissions: {
|
permissions: {
|
||||||
docName: 'posts'
|
docName: 'posts'
|
||||||
},
|
},
|
||||||
query(frame) {
|
async query(frame) {
|
||||||
let resource;
|
|
||||||
const resourceType = frame.options.resource;
|
const resourceType = frame.options.resource;
|
||||||
const publishAPostBySchedulerToleranceInMinutes = config.get('times').publishAPostBySchedulerToleranceInMinutes;
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
status: 'scheduled',
|
status: 'scheduled',
|
||||||
id: frame.options.id,
|
id: frame.options.id,
|
||||||
|
@ -45,53 +37,13 @@ module.exports = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return api[resourceType].read({id: frame.options.id}, options)
|
const {scheduledResource, preScheduledResource} = await postSchedulingService.publish(resourceType, frame.options.id, frame.data.force, options);
|
||||||
.then((result) => {
|
const cacheInvalidate = postSchedulingService.handleCacheInvalidation(scheduledResource, preScheduledResource);
|
||||||
resource = result[resourceType][0];
|
this.headers.cacheInvalidate = cacheInvalidate;
|
||||||
const publishedAtMoment = moment(resource.published_at);
|
|
||||||
|
|
||||||
if (publishedAtMoment.diff(moment(), 'minutes') > publishAPostBySchedulerToleranceInMinutes) {
|
const response = {};
|
||||||
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.notFound')}));
|
response[resourceType] = [scheduledResource];
|
||||||
}
|
return response;
|
||||||
|
|
||||||
if (publishedAtMoment.diff(moment(), 'minutes') < publishAPostBySchedulerToleranceInMinutes * -1 && frame.data.force !== true) {
|
|
||||||
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.publishInThePast')}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const editedResource = {};
|
|
||||||
editedResource[resourceType] = [{
|
|
||||||
status: 'published',
|
|
||||||
updated_at: moment(resource.updated_at).toISOString(true)
|
|
||||||
}];
|
|
||||||
|
|
||||||
return api[resourceType].edit(
|
|
||||||
editedResource,
|
|
||||||
_.pick(options, ['context', 'id', 'transacting', 'forUpdate'])
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.then((result) => {
|
|
||||||
const scheduledResource = result[resourceType][0];
|
|
||||||
|
|
||||||
if (
|
|
||||||
(scheduledResource.status === 'published' && resource.status !== 'published') ||
|
|
||||||
(scheduledResource.status === 'draft' && resource.status === 'published')
|
|
||||||
) {
|
|
||||||
this.headers.cacheInvalidate = true;
|
|
||||||
} else if (
|
|
||||||
(scheduledResource.status === 'draft' && resource.status !== 'published') ||
|
|
||||||
(scheduledResource.status === 'scheduled' && resource.status !== 'scheduled')
|
|
||||||
) {
|
|
||||||
this.headers.cacheInvalidate = {
|
|
||||||
value: urlUtils.urlFor({
|
|
||||||
relativeUrl: urlUtils.urlJoin('/p', scheduledResource.uuid, '/')
|
|
||||||
})
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this.headers.cacheInvalidate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
96
core/server/services/posts/post-scheduling-service.js
Normal file
96
core/server/services/posts/post-scheduling-service.js
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
const _ = require('lodash');
|
||||||
|
const errors = require('@tryghost/errors');
|
||||||
|
const moment = require('moment');
|
||||||
|
const config = require('../../../shared/config');
|
||||||
|
const i18n = require('../../../shared/i18n');
|
||||||
|
const urlUtils = require('../../../shared/url-utils');
|
||||||
|
const api = require('../../api');
|
||||||
|
|
||||||
|
class PostSchedulingService {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {String} options.apiVersion - api version
|
||||||
|
*/
|
||||||
|
constructor({apiVersion}) {
|
||||||
|
this.api = api[apiVersion];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes scheduled resource (a post or a page at the moment of writing)
|
||||||
|
*
|
||||||
|
* @param {String} resourceType one of 'post' or 'page' resources
|
||||||
|
* @param {String} id resource id
|
||||||
|
* @param {Boolean} force force publish flag
|
||||||
|
* @param {Object} options api query options
|
||||||
|
* @returns {Promise<Object, Object>}
|
||||||
|
*/
|
||||||
|
async publish(resourceType, id, force, options) {
|
||||||
|
const publishAPostBySchedulerToleranceInMinutes = config.get('times').publishAPostBySchedulerToleranceInMinutes;
|
||||||
|
|
||||||
|
const result = await this.api[resourceType].read({id}, options);
|
||||||
|
const preScheduledResource = result[resourceType][0];
|
||||||
|
|
||||||
|
const publishedAtMoment = moment(preScheduledResource.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 && force !== true) {
|
||||||
|
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.publishInThePast')}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const editedResource = {};
|
||||||
|
editedResource[resourceType] = [{
|
||||||
|
status: 'published',
|
||||||
|
updated_at: moment(preScheduledResource.updated_at).toISOString(true)
|
||||||
|
}];
|
||||||
|
|
||||||
|
const editResult = await this.api[resourceType].edit(
|
||||||
|
editedResource,
|
||||||
|
_.pick(options, ['context', 'id', 'transacting', 'forUpdate'])
|
||||||
|
);
|
||||||
|
const scheduledResource = editResult[resourceType][0];
|
||||||
|
|
||||||
|
return {scheduledResource, preScheduledResource};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} scheduledResource post or page resource object
|
||||||
|
* @param {Object} preScheduledResource post or page resource object in state before publishing
|
||||||
|
* @returns {Boolean|Object}
|
||||||
|
*/
|
||||||
|
handleCacheInvalidation(scheduledResource, preScheduledResource) {
|
||||||
|
if (
|
||||||
|
(scheduledResource.status === 'published' && preScheduledResource.status !== 'published') ||
|
||||||
|
(scheduledResource.status === 'draft' && preScheduledResource.status === 'published')
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
} else if (
|
||||||
|
(scheduledResource.status === 'draft' && preScheduledResource.status !== 'published') ||
|
||||||
|
(scheduledResource.status === 'scheduled' && preScheduledResource.status !== 'scheduled')
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
value: urlUtils.urlFor({
|
||||||
|
relativeUrl: urlUtils.urlJoin('/p', scheduledResource.uuid, '/')
|
||||||
|
})
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} apiVersion - API version to use within the service
|
||||||
|
* @returns {PostSchedulingService} instance of the PostsService
|
||||||
|
*/
|
||||||
|
const getPostSchedulingServiceInstance = (apiVersion) => {
|
||||||
|
return new PostSchedulingService({
|
||||||
|
apiVersion: apiVersion
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = getPostSchedulingServiceInstance;
|
Loading…
Add table
Reference in a new issue