From e0ab167b94e39f6febb6deaabcec4c69c05ee00f Mon Sep 17 00:00:00 2001 From: Ronald Langeveld Date: Tue, 15 Aug 2023 06:35:51 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20newsletter=20filters=20n?= =?UTF-8?q?ot=20working=20in=20bulk=20operations=20(#17714)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs https://ghost.slack.com/archives/CTH5NDJMS/p1692021848890629 - Addresses an NQL / API edge case where standalone filters with parentheses doesn't get handled correctly within bulk operations such as member labelling, member unsubscribe and member deletion. - This is currently only affected by newsletter related filters. - This adds a regex functions that checks when those filters are used and removes the parentheses when required. - Ideally we fix the NQL / API issue in the near future and remove this regex hack altogether, but taking all things into consideration, this should mitigate the risk of potential data-loss for Ghost users. --- ghost/admin/app/controllers/members.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ghost/admin/app/controllers/members.js b/ghost/admin/app/controllers/members.js index 3b54f9828e..31a7845dbe 100644 --- a/ghost/admin/app/controllers/members.js +++ b/ghost/admin/app/controllers/members.js @@ -216,9 +216,35 @@ export default class MembersController extends Controller { }); } + refineFilterParam(filterParam) { + // We have some crazy regex below, here's a breakdown of what it does: + // \\( - Matches an opening parenthesis "(" + // [^)]* - Matches zero or more characters that are NOT a closing parenthesis ")" + // [,+\\-]? - Matches an optional comma, plus, or minus sign + // email_disabled - Matches the exact string "email_disabled" + // [^)]* - Matches zero or more characters that are NOT a closing parenthesis ")" + // \\) - Matches a closing parenthesis ")" + // (?! + // [+\\-] - Negative lookahead: Asserts what directly follows is neither a plus "+" nor a minus "-" + // | - OR + // :\\'[^']*\\' - Negative lookahead: Asserts what follows is not a colon ":" followed by a string in single quotes + // | - OR + // :\\"[^"]*\\" - Negative lookahead: Asserts what follows is not a colon ":" followed by a string in double quotes + // ) + const regex = new RegExp(`\\(([^)]*[,+\\-]?email_disabled[^)]*)\\)(?![+\\-]|:\\'[^']*\\'|:\\"[^"]*\\")`, 'g'); + return filterParam.replace(regex, '$1'); + } + getApiQueryObject({params, extraFilters = []} = {}) { let {label, paidParam, searchParam, filterParam} = params ? params : this; + // NOTE: this is a temporary fix to help where the API isn't handling the parentheses correctly + // It's potentially a deeper issue with NQL. This should be removed once the API is fixed. + // refs https://ghost.slack.com/archives/C05EQPTMEP7/p1692025845788769 + if (filterParam) { + filterParam = this.refineFilterParam(filterParam); + } + let filters = []; filters = filters.concat(extraFilters);