mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
no issue - having a `send_email_when_published` property on the Post resource that only has an effect at certain times was confusing and was causing issues with clients that needed to know details of how that toggle worked - makes `post.send_email_when_published` a fully read-only property in the API - adds support for `?send_email_when_published=true` query param that can be passed in POST/PUT requests to the posts endpoint when scheduling or publishing a post - this is the only way to set `post.send_email_when_published` to `true` - adds handling to ensure that `post.send_email_when_published` is always reset to `false` when reverting a post back to a draft _unless_ an email has already been sent
217 lines
6 KiB
JavaScript
217 lines
6 KiB
JavaScript
const models = require('../../models');
|
|
const common = require('../../lib/common');
|
|
const urlUtils = require('../../lib/url-utils');
|
|
const {mega} = require('../../services/mega');
|
|
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email'];
|
|
const unsafeAttrs = ['status', 'authors', 'visibility'];
|
|
|
|
module.exports = {
|
|
docName: 'posts',
|
|
browse: {
|
|
options: [
|
|
'include',
|
|
'filter',
|
|
'fields',
|
|
'formats',
|
|
'limit',
|
|
'order',
|
|
'page',
|
|
'debug',
|
|
'absolute_urls'
|
|
],
|
|
validation: {
|
|
options: {
|
|
include: {
|
|
values: allowedIncludes
|
|
},
|
|
formats: {
|
|
values: models.Post.allowedFormats
|
|
}
|
|
}
|
|
},
|
|
permissions: {
|
|
unsafeAttrs: unsafeAttrs
|
|
},
|
|
query(frame) {
|
|
return models.Post.findPage(frame.options);
|
|
}
|
|
},
|
|
|
|
read: {
|
|
options: [
|
|
'include',
|
|
'fields',
|
|
'formats',
|
|
'debug',
|
|
'absolute_urls',
|
|
// NOTE: only for internal context
|
|
'forUpdate',
|
|
'transacting'
|
|
],
|
|
data: [
|
|
'id',
|
|
'slug',
|
|
'uuid'
|
|
],
|
|
validation: {
|
|
options: {
|
|
include: {
|
|
values: allowedIncludes
|
|
},
|
|
formats: {
|
|
values: models.Post.allowedFormats
|
|
}
|
|
}
|
|
},
|
|
permissions: {
|
|
unsafeAttrs: unsafeAttrs
|
|
},
|
|
query(frame) {
|
|
return models.Post.findOne(frame.data, frame.options)
|
|
.then((model) => {
|
|
if (!model) {
|
|
throw new common.errors.NotFoundError({
|
|
message: common.i18n.t('errors.api.posts.postNotFound')
|
|
});
|
|
}
|
|
|
|
return model;
|
|
});
|
|
}
|
|
},
|
|
|
|
add: {
|
|
statusCode: 201,
|
|
headers: {},
|
|
options: [
|
|
'include',
|
|
'source',
|
|
'send_email_when_published'
|
|
],
|
|
validation: {
|
|
options: {
|
|
include: {
|
|
values: allowedIncludes
|
|
},
|
|
source: {
|
|
values: ['html']
|
|
}
|
|
}
|
|
},
|
|
permissions: {
|
|
unsafeAttrs: unsafeAttrs
|
|
},
|
|
query(frame) {
|
|
return models.Post.add(frame.data.posts[0], frame.options)
|
|
.then((model) => {
|
|
if (model.get('status') !== 'published') {
|
|
this.headers.cacheInvalidate = false;
|
|
} else {
|
|
this.headers.cacheInvalidate = true;
|
|
}
|
|
|
|
return model;
|
|
});
|
|
}
|
|
},
|
|
|
|
edit: {
|
|
headers: {},
|
|
options: [
|
|
'include',
|
|
'id',
|
|
'source',
|
|
'send_email_when_published',
|
|
// NOTE: only for internal context
|
|
'forUpdate',
|
|
'transacting'
|
|
],
|
|
validation: {
|
|
options: {
|
|
include: {
|
|
values: allowedIncludes
|
|
},
|
|
id: {
|
|
required: true
|
|
},
|
|
source: {
|
|
values: ['html']
|
|
}
|
|
}
|
|
},
|
|
permissions: {
|
|
unsafeAttrs: unsafeAttrs
|
|
},
|
|
query(frame) {
|
|
return models.Post.edit(frame.data.posts[0], frame.options)
|
|
.then(async (model) => {
|
|
if (!model.get('send_email_when_published')) {
|
|
return model;
|
|
}
|
|
|
|
if (!model.get('email') && (model.get('status') === 'published') && model.wasChanged()) {
|
|
const email = await mega.addEmail(model.toJSON());
|
|
model.set('email', email);
|
|
}
|
|
|
|
return model;
|
|
})
|
|
.then((model) => {
|
|
if (
|
|
model.get('status') === 'published' && model.wasChanged() ||
|
|
model.get('status') === 'draft' && model.previous('status') === 'published'
|
|
) {
|
|
this.headers.cacheInvalidate = true;
|
|
} else if (
|
|
model.get('status') === 'draft' && model.previous('status') !== 'published' ||
|
|
model.get('status') === 'scheduled' && model.wasChanged()
|
|
) {
|
|
this.headers.cacheInvalidate = {
|
|
value: urlUtils.urlFor({
|
|
relativeUrl: urlUtils.urlJoin('/p', model.get('uuid'), '/')
|
|
})
|
|
};
|
|
} else {
|
|
this.headers.cacheInvalidate = false;
|
|
}
|
|
|
|
return model;
|
|
});
|
|
}
|
|
},
|
|
|
|
destroy: {
|
|
statusCode: 204,
|
|
headers: {
|
|
cacheInvalidate: true
|
|
},
|
|
options: [
|
|
'include',
|
|
'id'
|
|
],
|
|
validation: {
|
|
options: {
|
|
include: {
|
|
values: allowedIncludes
|
|
},
|
|
id: {
|
|
required: true
|
|
}
|
|
}
|
|
},
|
|
permissions: {
|
|
unsafeAttrs: unsafeAttrs
|
|
},
|
|
query(frame) {
|
|
frame.options.require = true;
|
|
|
|
return models.Post.destroy(frame.options)
|
|
.return(null)
|
|
.catch(models.Post.NotFoundError, () => {
|
|
throw new common.errors.NotFoundError({
|
|
message: common.i18n.t('errors.api.posts.postNotFound')
|
|
});
|
|
});
|
|
}
|
|
}
|
|
};
|