Handled email unsubscribe with multiple newsletters (#14560)

refs https://github.com/TryGhost/Team/issues/1495

- removes subscription from all newsletters for a member on click of unsubscribe link in email
- allows the new multiple newsletter system to work with existing unsubscribe flow
This commit is contained in:
Rishabh Garg 2022-04-22 19:37:24 +05:30 committed by Matt Hanley
parent 2d27c9d42a
commit a330165e4f
2 changed files with 47 additions and 2 deletions

View File

@ -15,6 +15,7 @@ const jobsService = require('../jobs');
const db = require('../../data/db'); const db = require('../../data/db');
const models = require('../../models'); const models = require('../../models');
const postEmailSerializer = require('./post-email-serializer'); const postEmailSerializer = require('./post-email-serializer');
const labs = require('../../../shared/labs');
const {getSegmentsFromHtml} = require('./segment-parser'); const {getSegmentsFromHtml} = require('./segment-parser');
// Used to listen to email.added and email.edited model events originally, I think to offload this - ideally would just use jobs now if possible // Used to listen to email.added and email.edited model events originally, I think to offload this - ideally would just use jobs now if possible
@ -273,7 +274,11 @@ async function handleUnsubscribeRequest(req) {
} }
try { try {
const memberModel = await membersService.api.members.update({subscribed: false}, {id: member.id}); let memberData = {subscribed: false};
if (labs.isSet('multipleNewsletters')) {
memberData.newsletters = [];
}
const memberModel = await membersService.api.members.update(memberData, {id: member.id});
return memberModel.toJSON(); return memberModel.toJSON();
} catch (err) { } catch (err) {
throw new errors.InternalServerError({ throw new errors.InternalServerError({

View File

@ -2,7 +2,9 @@ const should = require('should');
const sinon = require('sinon'); const sinon = require('sinon');
const errors = require('@tryghost/errors'); const errors = require('@tryghost/errors');
const {addEmail, _partitionMembersBySegment, _getEmailMemberRows, _transformEmailRecipientFilter} = require('../../../../../core/server/services/mega/mega'); const {addEmail, _partitionMembersBySegment, _getEmailMemberRows, _transformEmailRecipientFilter, handleUnsubscribeRequest} = require('../../../../../core/server/services/mega/mega');
const membersService = require('../../../../../core/server/services/members');
const labs = require('../../../../../core/shared/labs');
describe('MEGA', function () { describe('MEGA', function () {
describe('addEmail', function () { describe('addEmail', function () {
@ -44,6 +46,44 @@ describe('MEGA', function () {
}); });
}); });
describe('handleUnsubscribeRequest', function () {
const updateStub = sinon.stub();
beforeEach(function () {
updateStub.returns({
toJSON: () => {
return {};
}
});
sinon.stub(membersService, 'api').get(() => {
return {
members: {
get: () => {
return {
id: 'id-1',
name: 'Jamie'
};
},
update: updateStub
}
};
});
});
it('unsubscribes from all newsletters', async function () {
sinon.stub(labs, 'isSet').withArgs('multipleNewsletters').returns(true);
const req = {
url: 'https://example.com?uuid=abc'
};
await handleUnsubscribeRequest(req);
updateStub.calledWith({
subscribed: false,
newsletters: []
}, {
id: 'id-1'
}).should.be.true();
});
});
describe('getEmailMemberRows', function () { describe('getEmailMemberRows', function () {
it('addEmail throws when "free" or "paid" strings are used as a recipient_filter', async function () { it('addEmail throws when "free" or "paid" strings are used as a recipient_filter', async function () {
const emailModel = { const emailModel = {