From e3aa86deab46bf4ab8d036830a168d6585aca825 Mon Sep 17 00:00:00 2001 From: Braintree Date: Tue, 26 Mar 2024 17:11:29 +0000 Subject: [PATCH] 3.23.0 Co-authored-by: Timothy Martinak Co-authored-by: Sara Vasquez --- CHANGELOG.md | 5 ++ lib/braintree/client_token_gateway.js | 7 +- lib/braintree/validation_error_codes.js | 6 +- package-lock.json | 2 +- package.json | 2 +- .../braintree/client_token_gateway_spec.js | 64 +++++++++++++++++++ .../braintree/client_token_gateway_spec.js | 19 +++++- 7 files changed, 97 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11d8d22..f9c0b26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 3.23.0 + +- Add `domains` parameter support to `ClientToken.generate` +- Refactor key validation in `ClientTokenGateway` + ## 3.22.0 - Add `UnderReview` to `Dispute.Status` diff --git a/lib/braintree/client_token_gateway.js b/lib/braintree/client_token_gateway.js index 3718a53..ca87bf9 100644 --- a/lib/braintree/client_token_gateway.js +++ b/lib/braintree/client_token_gateway.js @@ -24,10 +24,10 @@ class ClientTokenGateway extends Gateway { params.version = DEFAULT_VERSION; } - err = Util.verifyKeys(this._generateSignature(), params); + err = this.validateParams(params); if (!err) { - err = this.validateParams(params); + err = Util.verifyKeys(this._generateSignature(), params); } if (err) { @@ -51,6 +51,8 @@ class ClientTokenGateway extends Gateway { .map((name) => name); if (invalidOptions.length > 0) { + // NEXT_MAJOR_VERSION change UnexpectedError to InvalidKeysError + // InvalidKeysError is more codebase consistent and makes more contextual sense // eslint-disable-next-line consistent-return, new-cap return exceptions.UnexpectedError( `A customer id is required for the following options: ${invalidOptions.join( @@ -91,6 +93,7 @@ class ClientTokenGateway extends Gateway { "options[verifyCard]", "options[failOnDuplicatePaymentMethod]", ], + ignore: ["domains"], }; } } diff --git a/lib/braintree/validation_error_codes.js b/lib/braintree/validation_error_codes.js index d6a8e73..567fe25 100644 --- a/lib/braintree/validation_error_codes.js +++ b/lib/braintree/validation_error_codes.js @@ -72,11 +72,13 @@ class ValidationErrorCodes { this.ClientToken = { CustomerDoesNotExist: "92804", FailOnDuplicatePaymentMethodRequiresCustomerId: "92803", + InvalidDomainFormat: "92011", MakeDefaultRequiresCustomerId: "92801", - ProxyMerchantDoesNotExist: "92805", - VerifyCardRequiresCustomerId: "92802", MerchantAccountDoesNotExist: "92807", + ProxyMerchantDoesNotExist: "92805", + TooManyDomains: "92810", UnsupportedVersion: "92806", + VerifyCardRequiresCustomerId: "92802", }; this.CreditCard = { diff --git a/package-lock.json b/package-lock.json index da2bb2e..72f068b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "braintree", - "version": "3.22.0", + "version": "3.23.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 32701c4..8aa2d17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "braintree", - "version": "3.22.0", + "version": "3.23.0", "description": "A library for server-side integrating with Braintree.", "keywords": [ "braintree", diff --git a/test/integration/braintree/client_token_gateway_spec.js b/test/integration/braintree/client_token_gateway_spec.js index ab15307..874b999 100644 --- a/test/integration/braintree/client_token_gateway_spec.js +++ b/test/integration/braintree/client_token_gateway_spec.js @@ -261,6 +261,70 @@ describe("ClientTokenGateway", function () { ); }); + it("can pass domains", function (done) { + let expectedDomains = ["example.com"]; + let clientTokenParams = { + domains: expectedDomains, + }; + + specHelper.defaultGateway.clientToken.generate( + clientTokenParams, + function (err, result) { + assert.isTrue(result.success); + let clientToken = JSON.parse( + specHelper.decodeClientToken(result.clientToken) + ); + + let authFingerprintPayload = Buffer.from( + clientToken.authorizationFingerprint, + "base64" + ).toString("utf8"); + + expectedDomains.forEach((domain) => { + assert.isTrue(authFingerprintPayload.includes(domain)); + }); + done(); + } + ); + }); + + it("calls callback with an error when an invalid domain is supplied", (done) => + specHelper.defaultGateway.clientToken.generate( + { + domains: ["example"], + }, + function (err, result) { + assert.isFalse(result.success); + assert.equal( + result.message, + "Client token domains must be valid domain names (RFC 1035), e.g. example.com" + ); + done(); + } + )); + + it("calls callback with an error when too many domains are supplied", (done) => + specHelper.defaultGateway.clientToken.generate( + { + domains: [ + "example1.com", + "example2.com", + "example3.com", + "example4.com", + "example5.com", + "example6.com", + ], + }, + function (err, result) { + assert.isFalse(result.success); + assert.equal( + result.message, + "Cannot specify more than 5 client token domains" + ); + done(); + } + )); + it("calls callback with an error when an invalid parameter is supplied", (done) => specHelper.defaultGateway.clientToken.generate( { diff --git a/test/unit/braintree/client_token_gateway_spec.js b/test/unit/braintree/client_token_gateway_spec.js index 97d1b3f..dfce5d5 100644 --- a/test/unit/braintree/client_token_gateway_spec.js +++ b/test/unit/braintree/client_token_gateway_spec.js @@ -3,7 +3,7 @@ let braintree = specHelper.braintree; describe("ClientTokenGateway", () => - describe("generate", () => + describe("generate", () => { it("returns an error when credit card options are supplied without a customer ID", function (done) { specHelper.defaultGateway.clientToken.generate( { @@ -18,4 +18,19 @@ describe("ClientTokenGateway", () => done(); } ); - }))); + }); + + it("does not return an error when the domains option is supplied", function (done) { + specHelper.defaultGateway.clientToken.generate( + { + domains: ["example.com"], + }, + function (err, response) { + assert.equal(err, null); + assert.typeOf(response, "object"); + assert.typeOf(response.clientToken, "string"); + done(); + } + ); + }); + }));