mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-23 11:55:01 +03:00
Improved newsletter limit checking (#14780)
refs https://github.com/TryGhost/Team/issues/1583 - Check limits when unarchiving newsletters - Added tests for more scenarios - When editing/adding newsletters, the limit check happens in the same transaction. - `limit-service` was bumped to add transactions support - Added transaction support for edit in newsletter service
This commit is contained in:
parent
3398e0d07d
commit
3214186f98
@ -112,7 +112,8 @@ class NewslettersService {
|
||||
* @public
|
||||
* @param {object} attrs model properties
|
||||
* @param {Object} [options] options
|
||||
* @param {Object} [options] options.transacting
|
||||
* @param {boolean} [options.opt_in_existing] Opt in existing members
|
||||
* @param {Object} [options.transacting]
|
||||
* @returns {Promise<{object}>} Newsetter Model with verification metadata
|
||||
*/
|
||||
async add(attrs, options = {}) {
|
||||
@ -124,7 +125,9 @@ class NewslettersService {
|
||||
});
|
||||
}
|
||||
|
||||
await this.limitService.errorIfWouldGoOverLimit('newsletters');
|
||||
if (!attrs.status || attrs.status === 'active') {
|
||||
await this.limitService.errorIfWouldGoOverLimit('newsletters', options.transacting ? {transacting: options.transacting} : {});
|
||||
}
|
||||
|
||||
// remove any email properties that are not allowed to be set without verification
|
||||
const {cleanedAttrs, emailsToVerify} = await this.prepAttrsForEmailVerification(attrs);
|
||||
@ -177,14 +180,21 @@ class NewslettersService {
|
||||
* @param {object} attrs model properties
|
||||
* @param {Object} options options
|
||||
* @param {string} options.id Newsletter id to edit
|
||||
* @param {Object} [options.transacting]
|
||||
* @returns {Promise<{object}>} Newsetter Model with verification metadata
|
||||
*/
|
||||
async edit(attrs, options) {
|
||||
const sharedOptions = _.pick(options, 'transacting');
|
||||
|
||||
// fetch newsletter first so we can compare changed emails
|
||||
const originalNewsletter = await this.NewsletterModel.findOne({id: options.id}, {require: true});
|
||||
const originalNewsletter = await this.NewsletterModel.findOne({id: options.id}, {...sharedOptions, require: true});
|
||||
|
||||
const {cleanedAttrs, emailsToVerify} = await this.prepAttrsForEmailVerification(attrs, originalNewsletter);
|
||||
|
||||
if (originalNewsletter.status !== 'active' && cleanedAttrs.status === 'active') {
|
||||
await this.limitService.errorIfWouldGoOverLimit('newsletters', sharedOptions);
|
||||
}
|
||||
|
||||
let updatedNewsletter;
|
||||
|
||||
try {
|
||||
@ -307,7 +317,7 @@ class NewslettersService {
|
||||
|
||||
/**
|
||||
* @typedef {object} ILimitService
|
||||
* @prop {(name: string) => Promise<void>} errorIfWouldGoOverLimit
|
||||
* @prop {(name: string, options?: {transacting?: Object}) => Promise<void>} errorIfWouldGoOverLimit
|
||||
**/
|
||||
|
||||
module.exports = NewslettersService;
|
||||
|
@ -81,7 +81,7 @@
|
||||
"@tryghost/kg-default-cards": "5.16.2",
|
||||
"@tryghost/kg-markdown-html-renderer": "5.1.5",
|
||||
"@tryghost/kg-mobiledoc-html-renderer": "5.3.5",
|
||||
"@tryghost/limit-service": "1.1.2",
|
||||
"@tryghost/limit-service": "1.2.0",
|
||||
"@tryghost/logging": "2.1.8",
|
||||
"@tryghost/magic-link": "1.0.25",
|
||||
"@tryghost/member-events": "0.4.5",
|
||||
|
@ -1062,6 +1062,360 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding a newsletter now doesn't fail 1: [body] 1`] = `
|
||||
Object {
|
||||
"meta": Object {
|
||||
"opted_in_member_count": 6,
|
||||
},
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "sans_serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Naughty newsletter",
|
||||
"sender_email": null,
|
||||
"sender_name": null,
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "naughty-newsletter",
|
||||
"sort_order": 3,
|
||||
"status": "active",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "sans_serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding a newsletter now doesn't fail 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "695",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/newsletters\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding an archived newsletter doesn't fail 1: [body] 1`] = `
|
||||
Object {
|
||||
"meta": Object {
|
||||
"opted_in_member_count": 6,
|
||||
},
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "sans_serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Archived newsletter",
|
||||
"sender_email": null,
|
||||
"sender_name": null,
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "archived-newsletter",
|
||||
"sort_order": 3,
|
||||
"status": "archived",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "sans_serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding an archived newsletter doesn't fail 2: [body] 1`] = `
|
||||
Object {
|
||||
"meta": Object {
|
||||
"opted_in_member_count": 6,
|
||||
},
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "sans_serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Archived newsletter",
|
||||
"sender_email": null,
|
||||
"sender_name": null,
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "archived-newsletter",
|
||||
"sort_order": 3,
|
||||
"status": "archived",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "sans_serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding an archived newsletter doesn't fail 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "699",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/newsletters\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding an archived newsletter doesn't fail 3: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "699",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/newsletters\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding newsletter fails 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"code": null,
|
||||
"context": "Your plan supports up to 3 newsletters. Please upgrade to add more.",
|
||||
"details": Object {
|
||||
"limit": 3,
|
||||
"name": "newsletters",
|
||||
"total": 3,
|
||||
},
|
||||
"ghostErrorCode": null,
|
||||
"help": "https://ghost.org/help/",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"message": "Host Limit error, cannot save newsletter.",
|
||||
"property": null,
|
||||
"type": "HostLimitError",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Adding newsletter fails without transaction 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"code": null,
|
||||
"context": "Your plan supports up to 3 newsletters. Please upgrade to add more.",
|
||||
"details": Object {
|
||||
"limit": 3,
|
||||
"name": "newsletters",
|
||||
"total": 3,
|
||||
},
|
||||
"ghostErrorCode": null,
|
||||
"help": "https://ghost.org/help/",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"message": "Host Limit error, cannot save newsletter.",
|
||||
"property": null,
|
||||
"type": "HostLimitError",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Archiving a newsletter doesn't fail 1: [body] 1`] = `
|
||||
Object {
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "sans_serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Default Newsletter",
|
||||
"sender_email": null,
|
||||
"sender_name": null,
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "default-newsletter",
|
||||
"sort_order": 0,
|
||||
"status": "archived",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "sans_serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Archiving a newsletter doesn't fail 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "662",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Editing an archived newsletter doesn't fail 1: [body] 1`] = `
|
||||
Object {
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Updated archived newsletter name",
|
||||
"sender_email": "jamie@example.com",
|
||||
"sender_name": "Jamie",
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "old-newsletter",
|
||||
"sort_order": 2,
|
||||
"status": "archived",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Editing an archived newsletter doesn't fail 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "680",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Editing an archived newsletter doesn't fails 1: [body] 1`] = `
|
||||
Object {
|
||||
"newsletters": Array [
|
||||
Object {
|
||||
"body_font_category": "serif",
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": null,
|
||||
"footer_content": null,
|
||||
"header_image": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Updated archived newsletter name",
|
||||
"sender_email": "jamie@example.com",
|
||||
"sender_name": "Jamie",
|
||||
"sender_reply_to": "newsletter",
|
||||
"show_badge": true,
|
||||
"show_feature_image": true,
|
||||
"show_header_icon": true,
|
||||
"show_header_name": true,
|
||||
"show_header_title": true,
|
||||
"slug": "old-newsletter",
|
||||
"sort_order": 2,
|
||||
"status": "archived",
|
||||
"subscribe_on_signup": true,
|
||||
"title_alignment": "center",
|
||||
"title_font_category": "serif",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"visibility": "members",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Editing an archived newsletter doesn't fails 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "680",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
"x-cache-invalidate": "/*",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Max limit Unarchiving a newsletter fails 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
Object {
|
||||
"code": null,
|
||||
"context": "Your plan supports up to 3 newsletters. Please upgrade to add more.",
|
||||
"details": Object {
|
||||
"limit": 3,
|
||||
"name": "newsletters",
|
||||
"total": 3,
|
||||
},
|
||||
"ghostErrorCode": null,
|
||||
"help": "https://ghost.org/help/",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
"message": "Host Limit error, cannot edit newsletter.",
|
||||
"property": null,
|
||||
"type": "HostLimitError",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Newsletters API Host Settings: newsletter limits Request fails when newsletter limit is in place 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
|
@ -1,6 +1,7 @@
|
||||
const assert = require('assert');
|
||||
const {agentProvider, mockManager, fixtureManager, configUtils, dbUtils, matchers} = require('../../utils/e2e-framework');
|
||||
const {anyEtag, anyObjectId, anyUuid, anyISODateTime, anyLocationFor, anyNumber} = matchers;
|
||||
const models = require('../../../core/server/models');
|
||||
|
||||
const assertMemberRelationCount = async (newsletterId, expectedCount) => {
|
||||
const relations = await dbUtils.knex('members_newsletters').where({newsletter_id: newsletterId}).pluck('id');
|
||||
@ -358,10 +359,10 @@ describe('Newsletters API', function () {
|
||||
});
|
||||
|
||||
describe('Host Settings: newsletter limits', function () {
|
||||
afterEach(function () {
|
||||
after(function () {
|
||||
configUtils.set('hostSettings:limits', undefined);
|
||||
});
|
||||
|
||||
|
||||
it('Request fails when newsletter limit is in place', async function () {
|
||||
configUtils.set('hostSettings:limits', {
|
||||
newsletters: {
|
||||
@ -388,6 +389,187 @@ describe('Newsletters API', function () {
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
describe('Max limit', function () {
|
||||
before(async function () {
|
||||
configUtils.set('hostSettings:limits', {
|
||||
newsletters: {
|
||||
max: 3,
|
||||
error: 'Your plan supports up to {{max}} newsletters. Please upgrade to add more.'
|
||||
}
|
||||
});
|
||||
|
||||
agent = await agentProvider.getAdminAPIAgent();
|
||||
await fixtureManager.init('newsletters', 'members:newsletters');
|
||||
await agent.loginAsOwner();
|
||||
});
|
||||
|
||||
it('Adding newsletter fails', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const newsletter = {
|
||||
name: 'Naughty newsletter'
|
||||
};
|
||||
|
||||
await agent
|
||||
.post(`newsletters/?opt_in_existing=true`)
|
||||
.body({newsletters: [newsletter]})
|
||||
.expectStatus(403)
|
||||
.matchBodySnapshot({
|
||||
errors: [{
|
||||
id: anyUuid
|
||||
}]
|
||||
})
|
||||
.expect(({body}) => {
|
||||
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
||||
});
|
||||
});
|
||||
|
||||
it('Adding newsletter fails without transaction', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const newsletter = {
|
||||
name: 'Naughty newsletter'
|
||||
};
|
||||
|
||||
// Note that ?opt_in_existing=true will trigger a transaction, so we explicitly test here without a
|
||||
// transaction
|
||||
await agent
|
||||
.post(`newsletters/`)
|
||||
.body({newsletters: [newsletter]})
|
||||
.expectStatus(403)
|
||||
.matchBodySnapshot({
|
||||
errors: [{
|
||||
id: anyUuid
|
||||
}]
|
||||
})
|
||||
.expect(({body}) => {
|
||||
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
||||
});
|
||||
});
|
||||
|
||||
it('Adding an archived newsletter doesn\'t fail', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const newsletter = {
|
||||
name: 'Archived newsletter',
|
||||
status: 'archived'
|
||||
};
|
||||
|
||||
await agent
|
||||
.post(`newsletters/?opt_in_existing=true`)
|
||||
.body({newsletters: [newsletter]})
|
||||
.expectStatus(201)
|
||||
.matchBodySnapshot({
|
||||
newsletters: [newsletterSnapshot]
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag,
|
||||
location: anyLocationFor('newsletters')
|
||||
});
|
||||
});
|
||||
|
||||
it('Editing an archived newsletter doesn\'t fail', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const archivedNewsletter = allNewsletters.find(n => n.get('status') !== 'active');
|
||||
assert.ok(archivedNewsletter, 'This test expects to have an archived newsletter in the test fixtures');
|
||||
|
||||
const id = archivedNewsletter.id;
|
||||
await agent.put(`newsletters/${id}`)
|
||||
.body({
|
||||
newsletters: [{
|
||||
name: 'Updated archived newsletter name'
|
||||
}]
|
||||
})
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
newsletters: [newsletterSnapshot]
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
});
|
||||
});
|
||||
|
||||
it('Unarchiving a newsletter fails', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const archivedNewsletter = allNewsletters.find(n => n.get('status') !== 'active');
|
||||
assert.ok(archivedNewsletter, 'This test expects to have an archived newsletter in the test fixtures');
|
||||
|
||||
const id = archivedNewsletter.id;
|
||||
await agent.put(`newsletters/${id}`)
|
||||
.body({
|
||||
newsletters: [{
|
||||
status: 'active'
|
||||
}]
|
||||
})
|
||||
.expectStatus(403)
|
||||
.matchBodySnapshot({
|
||||
errors: [{
|
||||
id: anyUuid
|
||||
}]
|
||||
})
|
||||
.expect(({body}) => {
|
||||
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
||||
});
|
||||
});
|
||||
|
||||
it('Archiving a newsletter doesn\'t fail', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
||||
|
||||
const activeNewsletter = allNewsletters.find(n => n.get('status') === 'active');
|
||||
|
||||
const id = activeNewsletter.id;
|
||||
await agent.put(`newsletters/${id}`)
|
||||
.body({
|
||||
newsletters: [{
|
||||
status: 'archived'
|
||||
}]
|
||||
})
|
||||
.expectStatus(200)
|
||||
.matchBodySnapshot({
|
||||
newsletters: [newsletterSnapshot]
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag
|
||||
});
|
||||
});
|
||||
|
||||
it('Adding a newsletter now doesn\'t fail', async function () {
|
||||
const allNewsletters = await models.Newsletter.findAll();
|
||||
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
||||
assert.equal(newsletterCount, 2, 'This test expects to have 2 current active newsletters');
|
||||
|
||||
const newsletter = {
|
||||
name: 'Naughty newsletter'
|
||||
};
|
||||
|
||||
await agent
|
||||
.post(`newsletters/?opt_in_existing=true`)
|
||||
.body({newsletters: [newsletter]})
|
||||
.expectStatus(201)
|
||||
.matchBodySnapshot({
|
||||
newsletters: [newsletterSnapshot]
|
||||
})
|
||||
.matchHeaderSnapshot({
|
||||
etag: anyEtag,
|
||||
location: anyLocationFor('newsletters')
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it(`Can't add multiple newsletters with same name`, async function () {
|
||||
|
@ -2106,10 +2106,10 @@
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
"@tryghost/limit-service@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/limit-service/-/limit-service-1.1.2.tgz#248f5b1c5383d302a6e29e8bcd2948ff9eb9ab4f"
|
||||
integrity sha512-aOUVnNvhYDANqtx+2pS0c0RADG39QDQ5tB7CLPjpcz2B6Nsc1fg4dEJeXU8fI1JT0YpMDRSliiNRh0/MMkozbA==
|
||||
"@tryghost/limit-service@1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/limit-service/-/limit-service-1.2.0.tgz#fea838bcb77e30b043f670c73237546bebfa4686"
|
||||
integrity sha512-awO9ZANst25v5+udlkwAcVV3OivisiWEX4OcD4i1YlSqPqcc5ncYr0ozlNjMR3djY0gX+rfN+WUc20ybwWL0Xg==
|
||||
dependencies:
|
||||
"@tryghost/errors" "^1.2.1"
|
||||
lodash "^4.17.21"
|
||||
|
Loading…
Reference in New Issue
Block a user