diff --git a/core/server/api/canary/newsletters.js b/core/server/api/canary/newsletters.js index e88493e1d6..750754665f 100644 --- a/core/server/api/canary/newsletters.js +++ b/core/server/api/canary/newsletters.js @@ -1,4 +1,10 @@ const models = require('../../models'); +const tpl = require('@tryghost/tpl'); +const errors = require('@tryghost/errors'); + +const messages = { + newsletterNotFound: 'Newsletter not found.' +}; module.exports = { docName: 'newsletters', @@ -17,6 +23,32 @@ module.exports = { } }, + read: { + options: [ + 'fields', + 'debug', + // NOTE: only for internal context + 'forUpdate', + 'transacting' + ], + data: [ + 'id', + 'slug', + 'uuid' + ], + permissions: true, + async query(frame) { + const newsletter = models.Newsletter.findOne(frame.data, frame.options); + + if (!newsletter) { + throw new errors.NotFoundError({ + message: tpl(messages.newsletterNotFound) + }); + } + return newsletter; + } + }, + add: { statusCode: 201, permissions: true, diff --git a/core/server/web/api/canary/admin/routes.js b/core/server/web/api/canary/admin/routes.js index a6549498fe..2fb5c47104 100644 --- a/core/server/web/api/canary/admin/routes.js +++ b/core/server/web/api/canary/admin/routes.js @@ -313,6 +313,7 @@ module.exports = function apiRoutes() { router.put('/custom_theme_settings', mw.authAdminApi, http(api.customThemeSettings.edit)); router.get('/newsletters', mw.authAdminApi, http(api.newsletters.browse)); + router.get('/newsletters/:id', mw.authAdminApi, http(api.newsletters.read)); router.post('/newsletters', mw.authAdminApi, http(api.newsletters.add)); router.put('/newsletters/:id', mw.authAdminApi, http(api.newsletters.edit)); diff --git a/test/e2e-api/admin/__snapshots__/newsletters.test.js.snap b/test/e2e-api/admin/__snapshots__/newsletters.test.js.snap index cfa0e15bf3..947d578af7 100644 --- a/test/e2e-api/admin/__snapshots__/newsletters.test.js.snap +++ b/test/e2e-api/admin/__snapshots__/newsletters.test.js.snap @@ -51,7 +51,7 @@ Object { "page": 1, "pages": 1, "prev": null, - "total": 2, + "total": 4, }, }, "newsletters": Array [ @@ -99,6 +99,50 @@ Object { "title_font_category": "serif", "visibility": "members", }, + Object { + "body_font_category": "serif", + "description": null, + "footer_content": null, + "header_image": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "name": "Daily newsletter", + "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_title": true, + "slug": "daily-newsletter", + "sort_order": 1, + "status": "active", + "subscribe_on_signup": false, + "title_alignment": "center", + "title_font_category": "serif", + "visibility": "members", + }, + Object { + "body_font_category": "serif", + "description": null, + "footer_content": null, + "header_image": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "name": "Weekly newsletter", + "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_title": true, + "slug": "weekly-newsletter", + "sort_order": 2, + "status": "active", + "subscribe_on_signup": true, + "title_alignment": "center", + "title_font_category": "serif", + "visibility": "members", + }, ], } `; @@ -107,7 +151,7 @@ exports[`Newsletters API Can add a newsletter 4: [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": "1097", + "content-length": "2094", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Origin, Accept-Encoding", @@ -124,7 +168,7 @@ Object { "page": 1, "pages": 1, "prev": null, - "total": 2, + "total": 4, }, }, "newsletters": Array [ @@ -172,6 +216,50 @@ Object { "title_font_category": "serif", "visibility": "members", }, + Object { + "body_font_category": "serif", + "description": null, + "footer_content": null, + "header_image": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "name": "Daily newsletter", + "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_title": true, + "slug": "daily-newsletter", + "sort_order": 1, + "status": "active", + "subscribe_on_signup": false, + "title_alignment": "center", + "title_font_category": "serif", + "visibility": "members", + }, + Object { + "body_font_category": "serif", + "description": null, + "footer_content": null, + "header_image": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "name": "Weekly newsletter", + "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_title": true, + "slug": "weekly-newsletter", + "sort_order": 2, + "status": "active", + "subscribe_on_signup": true, + "title_alignment": "center", + "title_font_category": "serif", + "visibility": "members", + }, ], } `; @@ -180,7 +268,7 @@ exports[`Newsletters API Can browse newsletters 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": "1097", + "content-length": "2094", "content-type": "application/json; charset=utf-8", "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, "vary": "Origin, Accept-Encoding", @@ -195,9 +283,9 @@ Object { "limit": 1, "next": 2, "page": 1, - "pages": 2, + "pages": 4, "prev": null, - "total": 2, + "total": 4, }, }, "newsletters": Array [ @@ -280,6 +368,47 @@ Object { } `; +exports[`Newsletters API Can read a newsletter 1: [body] 1`] = ` +Object { + "newsletters": Array [ + Object { + "body_font_category": "serif", + "description": null, + "footer_content": null, + "header_image": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "name": "Daily newsletter", + "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_title": true, + "slug": "daily-newsletter", + "sort_order": 1, + "status": "active", + "subscribe_on_signup": false, + "title_alignment": "center", + "title_font_category": "serif", + "visibility": "members", + }, + ], +} +`; + +exports[`Newsletters API Can read a newsletter 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": "515", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + exports[`Newsletters API Cannot add newsletter with same name 1: [body] 1`] = ` Object { "newsletters": Array [ diff --git a/test/e2e-api/admin/newsletters.test.js b/test/e2e-api/admin/newsletters.test.js index ec1a613687..470abfd47b 100644 --- a/test/e2e-api/admin/newsletters.test.js +++ b/test/e2e-api/admin/newsletters.test.js @@ -1,5 +1,6 @@ const {agentProvider, mockManager, fixtureManager, matchers} = require('../../utils/e2e-framework'); const {anyEtag, anyObjectId, anyString} = matchers; +const testUtils = require('../../utils'); const newsletterSnapshot = { id: anyObjectId @@ -10,7 +11,7 @@ let agent; describe('Newsletters API', function () { before(async function () { agent = await agentProvider.getAdminAPIAgent(); - await fixtureManager.init(); + await fixtureManager.init('newsletters'); await agent.loginAsOwner(); }); @@ -52,7 +53,7 @@ describe('Newsletters API', function () { await agent.get('newsletters/') .expectStatus(200) .matchBodySnapshot({ - newsletters: new Array(2).fill(newsletterSnapshot) + newsletters: new Array(4).fill(newsletterSnapshot) }) .matchHeaderSnapshot({ etag: anyEtag @@ -63,7 +64,19 @@ describe('Newsletters API', function () { await agent.get('newsletters/') .expectStatus(200) .matchBodySnapshot({ - newsletters: new Array(2).fill(newsletterSnapshot) + newsletters: new Array(4).fill(newsletterSnapshot) + }) + .matchHeaderSnapshot({ + etag: anyEtag + }); + }); + + it('Can read a newsletter', async function () { + await agent + .get(`newsletters/${testUtils.DataGenerator.Content.newsletters[0].id}/`) + .expectStatus(200) + .matchBodySnapshot({ + newsletters: new Array(1).fill(newsletterSnapshot) }) .matchHeaderSnapshot({ etag: anyEtag