mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-26 20:34:02 +03:00
Added member endpoints for managing newsletter subscriptions (#14624)
refs TryGhost/Team#1495 With multiple newsletters, members are allowed to manage their newsletter pref via email unsubscribe link with member uuid. Since Portal needs to manage member's newsletter pref via their UUID, we need new endpoints on members that allow fetch/update of newsletter subscriptions via only uuid. The endpoints return only limited data for a member that are needed for the UI. - adds endpoint to fetch newsletter subscriptions for member via uuid - adds endpoint to update newsletter subscriptions for member via uuid
This commit is contained in:
parent
a332e42476
commit
c7b247a079
@ -69,6 +69,65 @@ const getOfferData = async function (req, res) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getMemberNewsletters = async function (req, res) {
|
||||||
|
try {
|
||||||
|
const memberUuid = req.query.uuid;
|
||||||
|
|
||||||
|
if (!memberUuid) {
|
||||||
|
res.writeHead(400);
|
||||||
|
return res.end('Invalid member uuid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberData = await membersService.api.members.get({
|
||||||
|
uuid: memberUuid
|
||||||
|
}, {
|
||||||
|
withRelated: ['newsletters']
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!memberData) {
|
||||||
|
res.writeHead(404);
|
||||||
|
return res.end('Email address not found.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = _.pick(memberData.toJSON(), 'uuid', 'email', 'name', 'newsletters', 'status');
|
||||||
|
return res.json(data);
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end('Failed to unsubscribe this email address');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateMemberNewsletters = async function (req, res) {
|
||||||
|
try {
|
||||||
|
const memberUuid = req.query.uuid;
|
||||||
|
if (!memberUuid) {
|
||||||
|
res.writeHead(400);
|
||||||
|
return res.end('Invalid member uuid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = _.pick(req.body, 'newsletters');
|
||||||
|
const memberData = await membersService.api.members.get({
|
||||||
|
uuid: memberUuid
|
||||||
|
});
|
||||||
|
if (!memberData) {
|
||||||
|
res.writeHead(404);
|
||||||
|
return res.end('Email address not found.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
id: memberData.get('id'),
|
||||||
|
withRelated: ['newsletters']
|
||||||
|
};
|
||||||
|
|
||||||
|
const updatedMember = await membersService.api.members.update(data, options);
|
||||||
|
const updatedMemberData = _.pick(updatedMember.toJSON(), ['uuid', 'email', 'name', 'newsletters', 'status']);
|
||||||
|
res.json(updatedMemberData);
|
||||||
|
} catch (err) {
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end('Failed to update newsletters');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const updateMemberData = async function (req, res) {
|
const updateMemberData = async function (req, res) {
|
||||||
try {
|
try {
|
||||||
const data = _.pick(req.body, 'name', 'subscribed', 'newsletters');
|
const data = _.pick(req.body, 'name', 'subscribed', 'newsletters');
|
||||||
@ -270,9 +329,11 @@ module.exports = {
|
|||||||
loadMemberSession,
|
loadMemberSession,
|
||||||
createSessionFromMagicLink,
|
createSessionFromMagicLink,
|
||||||
getIdentityToken,
|
getIdentityToken,
|
||||||
|
getMemberNewsletters,
|
||||||
getMemberData,
|
getMemberData,
|
||||||
getOfferData,
|
getOfferData,
|
||||||
updateMemberData,
|
updateMemberData,
|
||||||
|
updateMemberNewsletters,
|
||||||
getMemberSiteData,
|
getMemberSiteData,
|
||||||
deleteSession
|
deleteSession
|
||||||
};
|
};
|
||||||
|
@ -33,6 +33,11 @@ module.exports = function setupMembersApp() {
|
|||||||
|
|
||||||
// Initializes members specific routes as well as assigns members specific data to the req/res objects
|
// Initializes members specific routes as well as assigns members specific data to the req/res objects
|
||||||
// We don't want to add global bodyParser middleware as that interfers with stripe webhook requests on - `/webhooks`.
|
// We don't want to add global bodyParser middleware as that interfers with stripe webhook requests on - `/webhooks`.
|
||||||
|
|
||||||
|
// Manage newsletter subscription via unsubscribe link
|
||||||
|
membersApp.get('/api/member/newsletters', middleware.getMemberNewsletters);
|
||||||
|
membersApp.put('/api/member/newsletters', bodyParser.json({limit: '1mb'}), middleware.updateMemberNewsletters);
|
||||||
|
|
||||||
membersApp.get('/api/member', middleware.getMemberData);
|
membersApp.get('/api/member', middleware.getMemberData);
|
||||||
membersApp.put('/api/member', bodyParser.json({limit: '1mb'}), middleware.updateMemberData);
|
membersApp.put('/api/member', bodyParser.json({limit: '1mb'}), middleware.updateMemberData);
|
||||||
membersApp.post('/api/member/email', bodyParser.json({limit: '1mb'}), (req, res) => membersService.api.middleware.updateEmailAddress(req, res));
|
membersApp.post('/api/member/email', bodyParser.json({limit: '1mb'}), (req, res) => membersService.api.middleware.updateEmailAddress(req, res));
|
||||||
|
@ -10,6 +10,7 @@ const DomainEvents = require('@tryghost/domain-events');
|
|||||||
const {MemberPageViewEvent} = require('@tryghost/member-events');
|
const {MemberPageViewEvent} = require('@tryghost/member-events');
|
||||||
const models = require('../../core/server/models');
|
const models = require('../../core/server/models');
|
||||||
const {mockManager} = require('../utils/e2e-framework');
|
const {mockManager} = require('../utils/e2e-framework');
|
||||||
|
const DataGenerator = require('../utils/fixtures/data-generator');
|
||||||
|
|
||||||
function assertContentIsPresent(res) {
|
function assertContentIsPresent(res) {
|
||||||
res.text.should.containEql('<h2 id="markdown">markdown</h2>');
|
res.text.should.containEql('<h2 id="markdown">markdown</h2>');
|
||||||
@ -57,7 +58,8 @@ describe('Front-end members behaviour', function () {
|
|||||||
return originalSettingsCacheGetFn(key, options);
|
return originalSettingsCacheGetFn(key, options);
|
||||||
});
|
});
|
||||||
await testUtils.startGhost();
|
await testUtils.startGhost();
|
||||||
await testUtils.initFixtures('members');
|
await testUtils.initFixtures('newsletters', 'members:newsletters');
|
||||||
|
|
||||||
request = supertest.agent(configUtils.config.get('url'));
|
request = supertest.agent(configUtils.config.get('url'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,6 +119,53 @@ describe('Front-end members behaviour', function () {
|
|||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should error for fetching member newsletters with missing uuid', async function () {
|
||||||
|
await request.get('/members/api/member/newsletters')
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error for fetching member newsletters with invalid uuid', async function () {
|
||||||
|
await request.get('/members/api/member/newsletters?uuid=abc')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error for updating member newsletters with missing uuid', async function () {
|
||||||
|
await request.put('/members/api/member/newsletters')
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error for updating member newsletters with invalid uuid', async function () {
|
||||||
|
await request.put('/members/api/member/newsletters?uuid=abc')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch and update member newsletters with valid uuid', async function () {
|
||||||
|
const memberUUID = DataGenerator.Content.members[0].uuid;
|
||||||
|
|
||||||
|
// Can fetch newsletter subscriptions
|
||||||
|
const getRes = await request.get(`/members/api/member/newsletters?uuid=${memberUUID}`)
|
||||||
|
.expect(200);
|
||||||
|
const getJsonResponse = getRes.body;
|
||||||
|
|
||||||
|
should.exist(getJsonResponse);
|
||||||
|
getJsonResponse.should.have.properties(['email', 'uuid', 'status', 'name', 'newsletters']);
|
||||||
|
getJsonResponse.should.not.have.property('id');
|
||||||
|
getJsonResponse.newsletters.should.have.length(1);
|
||||||
|
|
||||||
|
// Can update newsletter subscription
|
||||||
|
const res = await request.put(`/members/api/member/newsletters?uuid=${memberUUID}`)
|
||||||
|
.send({
|
||||||
|
newsletters: []
|
||||||
|
})
|
||||||
|
.expect(200);
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
|
||||||
|
should.exist(jsonResponse);
|
||||||
|
jsonResponse.should.have.properties(['email', 'uuid', 'status', 'name', 'newsletters']);
|
||||||
|
jsonResponse.should.not.have.property('id');
|
||||||
|
jsonResponse.newsletters.should.have.length(0);
|
||||||
|
});
|
||||||
|
|
||||||
it('should serve theme 404 on members endpoint', async function () {
|
it('should serve theme 404 on members endpoint', async function () {
|
||||||
await request.get('/members/')
|
await request.get('/members/')
|
||||||
.expect(404)
|
.expect(404)
|
||||||
|
Loading…
Reference in New Issue
Block a user