0
Fork 0
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:
Naz 2021-09-03 21:53:33 +04:00 committed by naz
parent 00460c96f4
commit 7b53a61b73
2 changed files with 105 additions and 57 deletions

View file

@ -1,11 +1,6 @@
const _ = require('lodash');
const moment = require('moment');
const config = require('../../../shared/config');
const models = require('../../models');
const urlUtils = require('../../../shared/url-utils');
const i18n = require('../../../shared/i18n');
const errors = require('@tryghost/errors');
const api = require('./index');
const postSchedulingService = require('../../services/posts/post-scheduling-service')('canary');
module.exports = {
docName: 'schedules',
@ -32,11 +27,8 @@ module.exports = {
permissions: {
docName: 'posts'
},
query(frame) {
let resource;
async query(frame) {
const resourceType = frame.options.resource;
const publishAPostBySchedulerToleranceInMinutes = config.get('times').publishAPostBySchedulerToleranceInMinutes;
const options = {
status: 'scheduled',
id: frame.options.id,
@ -45,53 +37,13 @@ module.exports = {
}
};
return api[resourceType].read({id: frame.options.id}, options)
.then((result) => {
resource = result[resourceType][0];
const publishedAtMoment = moment(resource.published_at);
const {scheduledResource, preScheduledResource} = await postSchedulingService.publish(resourceType, frame.options.id, frame.data.force, options);
const cacheInvalidate = postSchedulingService.handleCacheInvalidation(scheduledResource, preScheduledResource);
this.headers.cacheInvalidate = cacheInvalidate;
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 && 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;
});
const response = {};
response[resourceType] = [scheduledResource];
return response;
}
},

View 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;