🐛 Fixed unsubscribe button requiring manual action + wrong confirmation

fixes https://github.com/TryGhost/Product/issues/4118

The newsletter uuids were not passed when fetching all the members current newsletters. Therefore, Portals logic broke to remove all newsletters that matched the uuid that was passed to the unsubscribe link. No newsletters were removed, still the notification toast said that the member was unsubscribed from the newsletter.
This commit is contained in:
Simon Backx 2023-11-08 12:32:12 +01:00 committed by Simon Backx
parent 85979df33d
commit 986296cac9
5 changed files with 40 additions and 14 deletions

View File

@ -1,6 +1,12 @@
function formatNewsletterResponse(newsletters) {
return newsletters.map(({id, name, description, sort_order: sortOrder}) => {
return {id, name, description, sort_order: sortOrder};
return newsletters.map(({id, uuid, name, description, sort_order: sortOrder}) => {
return {
id,
uuid,
name,
description,
sort_order: sortOrder
};
});
}

View File

@ -19,12 +19,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"paid": false,
@ -38,7 +40,7 @@ exports[`Comments API when authenticated can get member data 2: [headers] 1`] =
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "529",
"content-length": "621",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -144,12 +146,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"paid": false,
@ -163,7 +167,7 @@ exports[`Comments API when authenticated can update comment notifications 2: [he
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "541",
"content-length": "633",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -182,12 +186,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"status": "free",
@ -199,7 +205,7 @@ exports[`Comments API when authenticated can update comment notifications 4: [he
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "354",
"content-length": "446",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -226,12 +232,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"paid": false,
@ -245,7 +253,7 @@ exports[`Comments API when authenticated can update member expertise 2: [headers
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "542",
"content-length": "634",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -272,12 +280,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"paid": false,
@ -291,7 +301,7 @@ exports[`Comments API when authenticated can update name 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "540",
"content-length": "632",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -318,12 +328,14 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Default Newsletter",
"sort_order": 0,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
Object {
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Weekly newsletter",
"sort_order": 2,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"paid": false,
@ -337,7 +349,7 @@ exports[`Comments API when authenticated trims whitespace from expertise 2: [hea
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "531",
"content-length": "623",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",
@ -356,6 +368,7 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"name": "Daily newsletter",
"sort_order": 1,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
},
],
"status": "free",
@ -367,7 +380,7 @@ exports[`Comments API when not authenticated but enabled can update comment noti
Object {
"access-control-allow-origin": "*",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "253",
"content-length": "299",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Encoding",

View File

@ -12,7 +12,8 @@ const memberMatcher = (newslettersCount) => {
created_at: anyISODateTime,
newsletters: new Array(newslettersCount).fill(
{
id: anyObjectId
id: anyObjectId,
uuid: anyUuid
}
)
};
@ -23,7 +24,8 @@ const buildMemberMatcher = (newslettersCount) => {
uuid: anyUuid,
newsletters: new Array(newslettersCount).fill(
{
id: anyObjectId
id: anyObjectId,
uuid: anyUuid
}
)
};

View File

@ -194,9 +194,10 @@ describe('Front-end members behavior', function () {
getJsonResponse.newsletters.should.have.length(1);
// NOTE: these should be snapshots not code
Object.keys(getJsonResponse.newsletters[0]).should.have.length(4);
Object.keys(getJsonResponse.newsletters[0]).should.have.length(5);
getJsonResponse.newsletters[0].should.have.properties([
'id',
'uuid',
'name',
'description',
'sort_order'
@ -231,9 +232,10 @@ describe('Front-end members behavior', function () {
restoreJsonResponse.should.not.have.property('id');
restoreJsonResponse.newsletters.should.have.length(1);
// @NOTE: this seems like too much exposed information, needs a review
Object.keys(restoreJsonResponse.newsletters[0]).should.have.length(4);
Object.keys(restoreJsonResponse.newsletters[0]).should.have.length(5);
restoreJsonResponse.newsletters[0].should.have.properties([
'id',
'uuid',
'name',
'description',
'sort_order'
@ -663,9 +665,10 @@ describe('Front-end members behavior', function () {
memberData.newsletters.should.have.length(1);
// @NOTE: this should be a snapshot test not code
Object.keys(memberData.newsletters[0]).should.have.length(4);
Object.keys(memberData.newsletters[0]).should.have.length(5);
memberData.newsletters[0].should.have.properties([
'id',
'uuid',
'name',
'description',
'sort_order'

View File

@ -61,6 +61,7 @@ describe('Members Service - utils', function () {
extra: 'property',
newsletters: [{
id: 'newsletter-1',
uuid: 'uuid-1',
name: 'Daily brief',
description: 'One email daily',
sender_name: 'Jamie',
@ -82,6 +83,7 @@ describe('Members Service - utils', function () {
paid: true,
newsletters: [{
id: 'newsletter-1',
uuid: 'uuid-1',
name: 'Daily brief',
description: 'One email daily',
sort_order: 0