Ghost/core/server/api/v2/schedules.js

126 lines
4.6 KiB
JavaScript
Raw Normal View History

const _ = require('lodash');
const moment = require('moment');
const config = require('../../../shared/config');
const models = require('../../models');
const urlUtils = require('../../../shared/url-utils');
Refactored `common` lib import to use destructuring (#11835) * refactored `core/frontend/apps` to destructure common imports * refactored `core/frontend/services/{apps, redirects, routing}` to destructure common imports * refactored `core/frontend/services/settings` to destructure common imports * refactored remaining `core/frontend/services` to destructure common imports * refactored `core/server/adapters` to destructure common imports * refactored `core/server/data/{db, exporter, schema, validation}` to destructure common imports * refactored `core/server/data/importer` to destructure common imports * refactored `core/server/models/{base, plugins, relations}` to destructure common imports * refactored remaining `core/server/models` to destructure common imports * refactored `core/server/api/canary/utils/serializers/output` to destructure common imports * refactored remaining `core/server/api/canary/utils` to destructure common imports * refactored remaining `core/server/api/canary` to destructure common imports * refactored `core/server/api/shared` to destructure common imports * refactored `core/server/api/v2/utils` to destructure common imports * refactored remaining `core/server/api/v2` to destructure common imports * refactored `core/frontend/meta` to destructure common imports * fixed some tests referencing `common.errors` instead of `@tryghost/errors` - Not all of them need to be updated; only updating the ones that are causing failures * fixed errors import being shadowed by local scope
2020-05-22 21:22:20 +03:00
const {i18n} = require('../../lib/common');
const errors = require('@tryghost/errors');
const api = require('./index');
module.exports = {
docName: 'schedules',
publish: {
headers: {},
options: [
'id',
'resource'
],
data: [
'force'
],
validation: {
options: {
id: {
required: true
},
resource: {
required: true,
values: ['posts', 'pages']
}
}
},
permissions: {
docName: 'posts'
},
query(frame) {
let resource;
const resourceType = frame.options.resource;
const publishAPostBySchedulerToleranceInMinutes = config.get('times').publishAPostBySchedulerToleranceInMinutes;
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
const options = {
status: 'scheduled',
id: frame.options.id,
context: {
internal: true
}
};
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
return api[resourceType].read({id: frame.options.id}, options)
.then((result) => {
resource = result[resourceType][0];
const publishedAtMoment = moment(resource.published_at);
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
if (publishedAtMoment.diff(moment(), 'minutes') > publishAPostBySchedulerToleranceInMinutes) {
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.notFound')}));
}
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
if (publishedAtMoment.diff(moment(), 'minutes') < publishAPostBySchedulerToleranceInMinutes * -1 && frame.data.force !== true) {
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.publishInThePast')}));
}
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
const editedResource = {};
editedResource[resourceType] = [{
status: 'published',
updated_at: moment(resource.updated_at).toISOString(true)
}];
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
return api[resourceType].edit(
editedResource,
_.pick(options, ['context', 'id', 'transacting', 'forUpdate'])
);
})
.then((result) => {
const scheduledResource = result[resourceType][0];
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
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;
}
🐛 Fixed scheduled post emails pointing at /404/ for the "view online" link no issue When scheduling a post to publish+send the "view online" link was pointing at https://site.com/404/ rather than the published post's url. The problem occurred because the `/schedules/` endpoint wraps it's post read+edit calls in a transaction. Context: - when a post is published with with the "send email" option the email record is immediately generated and added to the API response, as part of the email record generation we render the email content including fetching the url for the "view online" link - urls for all resources are handled by our `url` service, that service updates it's internal cache based upon model events such as the "edited" event triggered when a post is published - if the posts API controller is given a transaction, the email record is also generated inside of that transaction however at this point the `url` service will not have been updated because the post record hasn't been committed meaning it has no available url for the post Fix: - removed the `models.Base.transaction()` wrapper around the post read+update in the `/schedules/` API controllers - we don't need a transaction here. It was added as protection against another write request coming in between the `/schedules/` controller reading a post and publishing a post but we already have protection against that in the form of collision detection - if a write request comes in and commits between the schedules controller reading the post and updating it, the scheduler's update call will fail with a collision error at which point the scheduler itself should retry the request which could then publish the post successfully if everything else is in order
2020-10-08 12:25:27 +03:00
return result;
});
}
},
getScheduled: {
// NOTE: this method is for internal use only by DefaultScheduler
// it is not exposed anywhere!
permissions: false,
validation: {
options: {
resource: {
required: true,
values: ['posts', 'pages']
}
}
},
query(frame) {
const resourceModel = 'Post';
const resourceType = (frame.options.resource === 'post') ? 'post' : 'page';
const cleanOptions = {};
cleanOptions.filter = `status:scheduled+type:${resourceType}`;
cleanOptions.columns = ['id', 'published_at', 'created_at', 'type'];
return models[resourceModel].findAll(cleanOptions)
.then((result) => {
let response = {};
response[resourceType] = result;
return response;
});
}
}
};