From 02bb2f1c5ae833dc7f2dcb665353489540d1c75c Mon Sep 17 00:00:00 2001 From: June Kelly Date: Wed, 12 Jan 2022 09:53:24 +0000 Subject: [PATCH] Merge pull request #6181 from overleaf/jk-fix-sub-handler-xml-exception [web] Catch XML errors in RecurlyWrapper GitOrigin-RevId: bc20146b67e0ceac76f21b5d28ea2b36e2e97f0d --- .../Features/Subscription/RecurlyWrapper.js | 88 ++++++++++++++++--- .../src/Subscription/RecurlyWrapperTests.js | 31 +++++++ 2 files changed, 107 insertions(+), 12 deletions(-) diff --git a/services/web/app/src/Features/Subscription/RecurlyWrapper.js b/services/web/app/src/Features/Subscription/RecurlyWrapper.js index f5f70334c8..a3c4400b23 100644 --- a/services/web/app/src/Features/Subscription/RecurlyWrapper.js +++ b/services/web/app/src/Features/Subscription/RecurlyWrapper.js @@ -31,7 +31,14 @@ function updateAccountEmailAddress(accountId, newEmail, callback) { const data = { email: newEmail, } - const requestBody = RecurlyWrapper._buildXml('account', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('account', data) + } catch (error) { + return callback( + OError.tag(error, 'error building xml', { accountId, newEmail }) + ) + } RecurlyWrapper.apiRequest( { @@ -123,7 +130,14 @@ const RecurlyWrapper = { last_name: user.last_name, address, } - const requestBody = RecurlyWrapper._buildXml('account', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('account', data) + } catch (error) { + return next( + OError.tag(error, 'error building xml', { user_id: user._id }) + ) + } return RecurlyWrapper.apiRequest( { @@ -171,7 +185,14 @@ const RecurlyWrapper = { return next(new Error('no account code at createBillingInfo stage')) } const data = { token_id: recurlyTokenIds.billing } - const requestBody = RecurlyWrapper._buildXml('billing_info', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('billing_info', data) + } catch (error) { + return next( + OError.tag(error, 'error building xml', { user_id: user._id }) + ) + } return RecurlyWrapper.apiRequest( { url: `accounts/${accountCode}/billing_info`, @@ -233,10 +254,18 @@ const RecurlyWrapper = { } catch (error) { return next(error) } - const requestBody = RecurlyWrapper._buildXml( - 'billing_info', - addressAndCompanyBillingInfo - ) + + let requestBody + try { + requestBody = RecurlyWrapper._buildXml( + 'billing_info', + addressAndCompanyBillingInfo + ) + } catch (error) { + return next( + OError.tag(error, 'error building xml', { user_id: user._id }) + ) + } return RecurlyWrapper.apiRequest( { @@ -288,7 +317,14 @@ const RecurlyWrapper = { if (customFields) { data.custom_fields = customFields } - const requestBody = RecurlyWrapper._buildXml('subscription', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('subscription', data) + } catch (error) { + return next( + OError.tag(error, 'error building xml', { user_id: user._id }) + ) + } return RecurlyWrapper.apiRequest( { @@ -399,7 +435,14 @@ const RecurlyWrapper = { if (customFields) { data.custom_fields = customFields } - const requestBody = RecurlyWrapper._buildXml('subscription', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('subscription', data) + } catch (error) { + return callback( + OError.tag(error, 'error building xml', { user_id: user._id }) + ) + } return RecurlyWrapper.apiRequest( { @@ -701,7 +744,14 @@ const RecurlyWrapper = { plan_code: options.plan_code, timeframe: options.timeframe, } - const requestBody = RecurlyWrapper._buildXml('subscription', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('subscription', data) + } catch (error) { + return callback( + OError.tag(error, 'error building xml', { subscriptionId }) + ) + } return RecurlyWrapper.apiRequest( { @@ -737,7 +787,14 @@ const RecurlyWrapper = { applies_to_all_plans: false, } data.discount_in_cents[currencyCode] = discount_in_cents - const requestBody = RecurlyWrapper._buildXml('coupon', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('coupon', data) + } catch (error) { + return callback( + OError.tag(error, 'error building xml', { coupon_code, name }) + ) + } logger.log({ coupon_code, requestBody }, 'creating coupon') return RecurlyWrapper.apiRequest( @@ -774,7 +831,14 @@ const RecurlyWrapper = { account_code, currency: 'USD', } - const requestBody = RecurlyWrapper._buildXml('redemption', data) + let requestBody + try { + requestBody = RecurlyWrapper._buildXml('redemption', data) + } catch (error) { + return callback( + OError.tag(error, 'error building xml', { account_code, coupon_code }) + ) + } logger.log( { account_code, coupon_code, requestBody }, diff --git a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js index 81e2c7e080..78b4358e75 100644 --- a/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js +++ b/services/web/test/unit/src/Subscription/RecurlyWrapperTests.js @@ -285,6 +285,37 @@ describe('RecurlyWrapper', function () { }) }) + describe('updateAccountEmailAddress, with invalid XML', function () { + beforeEach(function (done) { + this.recurlyAccountId = 'account-id-123' + this.newEmail = '\uD800@example.com' + this.apiRequest = sinon + .stub(this.RecurlyWrapper, 'apiRequest') + .callsFake((options, callback) => { + this.requestOptions = options + callback(null, {}, fixtures['accounts/104']) + }) + done() + }) + + afterEach(function () { + return this.RecurlyWrapper.apiRequest.restore() + }) + + it('should produce an error', function (done) { + this.RecurlyWrapper.updateAccountEmailAddress( + this.recurlyAccountId, + this.newEmail, + (error, recurlyAccount) => { + expect(error).to.exist + expect(error.message.startsWith('Invalid character')).to.equal(true) + expect(this.apiRequest.called).to.equal(false) + done() + } + ) + }) + }) + describe('updateSubscription', function () { beforeEach(function (done) { this.recurlySubscriptionId = 'subscription-id-123'