From 87ba37dcfd5833da9a595478760ec5b4dd7071f9 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Mon, 18 Dec 2023 18:44:49 +0000 Subject: [PATCH 1/3] Replaces Stripe stubs with the account and customer IDs Adds STRIPE_ACCOUNT as sensitive data to VCR setup Rubocop fixes and re-recording of cassettes Adds bogus client_id to local test file - for CI to run --- .env.test | 2 + ...stroys_the_record_and_notifies_Bugsnag.yml | 125 ++++++++++++++++++ .../destroys_the_record.yml | 125 ++++++++++++++++++ spec/models/stripe_account_spec.rb | 25 ++-- spec/support/vcr_setup.rb | 1 + 5 files changed, 262 insertions(+), 16 deletions(-) create mode 100644 spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml create mode 100644 spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml diff --git a/.env.test b/.env.test index e1d7d47cc2..afa4e58c1d 100644 --- a/.env.test +++ b/.env.test @@ -4,6 +4,8 @@ SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" STRIPE_SECRET_TEST_API_KEY="bogus_key" STRIPE_CUSTOMER="bogus_customer" +STRIPE_ACCOUNT="bogus_account" +STRIPE_CLIENT_ID="bogus_client_id" SITE_URL="test.host" diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml new file mode 100644 index 0000000000..4808014362 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml @@ -0,0 +1,125 @@ +--- +http_interactions: +- request: + method: post + uri: https://connect.stripe.com/oauth/deauthorize + body: + encoding: UTF-8 + string: stripe_user_id=&client_id=bogus_client_id + headers: + User-Agent: + - Stripe/v1 RubyBindings/10.3.0 + Authorization: + - Bearer + Content-Type: + - application/x-www-form-urlencoded + Stripe-Version: + - '2023-10-16' + X-Stripe-Client-User-Agent: + - '{"bindings_version":"10.3.0","lang":"ruby","lang_version":"3.1.4 p223 (2023-03-30)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 6.2.0-39-generic (buildd@lcy02-amd64-045) (x86_64-linux-gnu-gcc-11 + (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) + #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2","hostname":"ff-LAT"}' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 401 + message: Unauthorized + headers: + Server: + - nginx + Date: + - Tue, 19 Dec 2023 12:55:29 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '96' + Connection: + - keep-alive + Cache-Control: + - max-age=0, no-cache, no-store, must-revalidate + Content-Security-Policy: + - report-uri /csp-report?p=%2Foauth%2Fdeauthorize;block-all-mixed-content;default-src + 'none' 'report-sample';base-uri 'none';form-action 'none';style-src 'unsafe-inline';frame-ancestors + 'self';connect-src 'self';img-src 'self' https://b.stripecdn.com + Cross-Origin-Opener-Policy-Report-Only: + - same-origin; report-to=https://q.stripe.com/coop-report + Expires: + - '0' + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Request-Id: + - req_1v8IG0ihHAhDnR + Set-Cookie: + - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; + secure; SameSite=None + - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + HttpOnly; SameSite=Lax + - machine_identifier=nsadMhesm4x1GYVPmQcxGxkwOEHT0uGESxaoxop6tgOLhu%2BvkqpSkkKcxxRvqqlpa%2BQ%3D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + HttpOnly; SameSite=Lax + - private_machine_identifier=5MctxMzB3oEJsWQPiwovzvt6vy1pHt5g4lYzkFr0hY3jCZZPQz%2F6jU71Ye8gqtUCUkE%3D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + HttpOnly; SameSite=None + - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 + 00:00:00 GMT; secure + - stripe.csrf=ivC9DH1gR7jYwuuHUpqqkApanZ79wswQZMBVKfzfaLr1n5rf_HwKb4sv66YdBNDs03Zq1H_JeHyOjBZ1rENh4jw-AYTZVJxQjKfvlBDZNhjvEvPk5QdyiiBil-k2Op8FixB9Mw4lkg%3D%3D; + domain=stripe.com; path=/; secure; HttpOnly; SameSite=None + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + - max-age=63072000; includeSubDomains; preload + Stripe-Kill-Route: + - "[]" + Stripe-Parent-Id: + - '0000000000000000' + Stripe-Span-Id: + - 1317edffcd8f0941 + Www-Authenticate: + - Bearer realm="Stripe" + X-Apiori-Intentional-Latency: + - 0s + X-Apiori-Reqid: + - dub2DISD22ogqObCRqkyYRE + X-Apiori-Server-Duration-Ms: + - '126' + X-Apiori-Upstream-Duration: + - 126.447763ms + X-Apiori-Upstream-Name: + - manage-srv + X-Apiori-Upstream-Region: + - northwest + X-Content-Type-Options: + - nosniff + X-Envoy-Attempt-Count: + - '1' + X-Envoy-Upstream-Service-Time: + - '248' + X-Robots-Tag: + - none + X-Stripe-Bg-Intended-Route-Color: + - green + X-Stripe-C-Cost: + - '2' + X-Stripe-Client-Envoy-Start-Time-Us: + - '1702990529582694' + X-Stripe-Rpc-C-Cost-Report: + - Cg0IARIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= + X-Stripe-Server-Envoy-Start-Time-Us: + - '1702990529583695' + X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: + - '123' + body: + encoding: UTF-8 + string: |- + { + "error": "invalid_client", + "error_description": "No such application: 'bogus_client_id'" + } + recorded_at: Tue, 19 Dec 2023 12:55:29 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml new file mode 100644 index 0000000000..0c8489a0f3 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml @@ -0,0 +1,125 @@ +--- +http_interactions: +- request: + method: post + uri: https://connect.stripe.com/oauth/deauthorize + body: + encoding: UTF-8 + string: stripe_user_id=&client_id=ca_MzG1xs6tZFDztUlak7uFxoUM36G6307W + headers: + User-Agent: + - Stripe/v1 RubyBindings/10.3.0 + Authorization: + - Bearer + Content-Type: + - application/x-www-form-urlencoded + Stripe-Version: + - '2023-10-16' + X-Stripe-Client-User-Agent: + - '{"bindings_version":"10.3.0","lang":"ruby","lang_version":"3.1.4 p223 (2023-03-30)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 6.2.0-39-generic (buildd@lcy02-amd64-045) (x86_64-linux-gnu-gcc-11 + (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) + #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2","hostname":"ff-LAT"}' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 401 + message: Unauthorized + headers: + Server: + - nginx + Date: + - Tue, 19 Dec 2023 12:55:30 GMT + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '164' + Connection: + - keep-alive + Cache-Control: + - max-age=0, no-cache, no-store, must-revalidate + Content-Security-Policy: + - report-uri /csp-report?p=%2Foauth%2Fdeauthorize;block-all-mixed-content;default-src + 'none' 'report-sample';base-uri 'none';form-action 'none';style-src 'unsafe-inline';frame-ancestors + 'self';connect-src 'self';img-src 'self' https://b.stripecdn.com + Cross-Origin-Opener-Policy-Report-Only: + - same-origin; report-to=https://q.stripe.com/coop-report + Expires: + - '0' + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Request-Id: + - req_pGBBuPOXb6xMly + Set-Cookie: + - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; + secure; SameSite=None + - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + HttpOnly; SameSite=Lax + - machine_identifier=JJUOdPN1UTC9yKxG3Cief9mNanXTKM9y3VmUcEzfmFXEB%2FViV5jXpnxq0kFsEjoKyyg%3D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + HttpOnly; SameSite=Lax + - private_machine_identifier=qnLLWHsR2kIkVnuEZbUabBmPGOMmgoa%2B2t%2Bt82Sn41uVMChBI%2FF%2FmVlhmFtmb9%2Fnd70%3D; + domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + HttpOnly; SameSite=None + - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 + 00:00:00 GMT; secure + - stripe.csrf=aIL_e_YV7LaxFPnsyZHeK9DsuQ7sm4bYeawhyIBlivow1bC0KAoKCaoR0E-WklLxlvDMXwX1_tY7Aa5l_gJ-zzw-AYTZVJwtl69iWowmC5Gcjqp-_ni03g1Mcx1Hbz6xqEXSGCKfKg%3D%3D; + domain=stripe.com; path=/; secure; HttpOnly; SameSite=None + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + - max-age=63072000; includeSubDomains; preload + Stripe-Kill-Route: + - "[]" + Stripe-Parent-Id: + - '0000000000000000' + Stripe-Span-Id: + - abaf119f94aa71c4 + Www-Authenticate: + - Bearer realm="Stripe" + X-Apiori-Intentional-Latency: + - 0s + X-Apiori-Reqid: + - dub1DISD299L0WxB0Akf1uq + X-Apiori-Server-Duration-Ms: + - '138' + X-Apiori-Upstream-Duration: + - 137.918128ms + X-Apiori-Upstream-Name: + - manage-srv + X-Apiori-Upstream-Region: + - northwest + X-Content-Type-Options: + - nosniff + X-Envoy-Attempt-Count: + - '1' + X-Envoy-Upstream-Service-Time: + - '257' + X-Robots-Tag: + - none + X-Stripe-Bg-Intended-Route-Color: + - green + X-Stripe-C-Cost: + - '4' + X-Stripe-Client-Envoy-Start-Time-Us: + - '1702990530466139' + X-Stripe-Rpc-C-Cost-Report: + - Cg0IAxIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= + X-Stripe-Server-Envoy-Start-Time-Us: + - '1702990530466931' + X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: + - '135' + body: + encoding: UTF-8 + string: |- + { + "error": "invalid_client", + "error_description": "This application is not connected to stripe account , or that account does not exist." + } + recorded_at: Tue, 19 Dec 2023 12:55:30 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/models/stripe_account_spec.rb b/spec/models/stripe_account_spec.rb index f798cbc56a..4aae9c5a9e 100644 --- a/spec/models/stripe_account_spec.rb +++ b/spec/models/stripe_account_spec.rb @@ -4,27 +4,24 @@ require 'spec_helper' require 'stripe/oauth' describe StripeAccount do - describe "deauthorize_and_destroy" do + describe "deauthorize_and_destroy", :vcr, :stripe_version do let!(:enterprise) { create(:enterprise) } let!(:enterprise2) { create(:enterprise) } - let(:client_id) { 'ca_abc123' } - let(:stripe_user_id) { 'acct_abc123' } + let(:client_id) { ENV.fetch('STRIPE_CLIENT_ID', nil) } + let(:stripe_user_id) { ENV.fetch('STRIPE_ACCOUNT', nil) } + let!(:stripe_account) { create(:stripe_account, enterprise:, stripe_user_id:) } + let(:secret) { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } + before do - Stripe.api_key = "sk_test_12345" - Stripe.client_id = client_id + Stripe.api_key = secret end context "when the Stripe API disconnect fails" do - before do - stub_request(:post, "https://connect.stripe.com/oauth/deauthorize"). - with(body: { "client_id" => client_id, "stripe_user_id" => stripe_user_id }). - to_return(status: 400, body: JSON.generate(error: 'invalid_grant', - error_description: "Some Message")) - end + before { Stripe.client_id = "bogus_client_id" } it "destroys the record and notifies Bugsnag" do expect(Bugsnag).to receive(:notify) @@ -34,11 +31,7 @@ describe StripeAccount do end context "when the Stripe API disconnect succeeds" do - before do - stub_request(:post, "https://connect.stripe.com/oauth/deauthorize"). - with(body: { "client_id" => client_id, "stripe_user_id" => stripe_user_id }). - to_return(status: 200, body: JSON.generate(stripe_user_id:)) - end + before { Stripe.client_id = client_id } it "destroys the record" do stripe_account.deauthorize_and_destroy diff --git a/spec/support/vcr_setup.rb b/spec/support/vcr_setup.rb index 7cb9d1b63d..2f944fb235 100644 --- a/spec/support/vcr_setup.rb +++ b/spec/support/vcr_setup.rb @@ -9,5 +9,6 @@ VCR.configure do |config| config.configure_rspec_metadata! config.filter_sensitive_data('') { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } config.filter_sensitive_data('') { ENV.fetch('STRIPE_CUSTOMER', nil) } + config.filter_sensitive_data('') { ENV.fetch('STRIPE_ACCOUNT', nil) } config.ignore_hosts('localhost', '127.0.0.1', '0.0.0.0', 'api.knapsackpro.com') end From beb916d24d7a285aea147e0412d2a41d8f686676 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Tue, 19 Dec 2023 16:17:56 +0000 Subject: [PATCH 2/3] Improves assertions around disconnect-failure and -success test cases --- spec/models/stripe_account_spec.rb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/spec/models/stripe_account_spec.rb b/spec/models/stripe_account_spec.rb index 4aae9c5a9e..374f7ee640 100644 --- a/spec/models/stripe_account_spec.rb +++ b/spec/models/stripe_account_spec.rb @@ -24,9 +24,13 @@ describe StripeAccount do before { Stripe.client_id = "bogus_client_id" } it "destroys the record and notifies Bugsnag" do + # returns status 401 expect(Bugsnag).to receive(:notify) - stripe_account.deauthorize_and_destroy - expect(StripeAccount.all).to_not include(stripe_account) + expect { + stripe_account.deauthorize_and_destroy + }.to change( + StripeAccount.where(stripe_user_id:), :count + ).from(1).to(0) end end @@ -34,8 +38,14 @@ describe StripeAccount do before { Stripe.client_id = client_id } it "destroys the record" do + # returns status 200 + expect(Bugsnag).to_not receive(:notify) stripe_account.deauthorize_and_destroy - expect(StripeAccount.all).not_to include(stripe_account) + expect { + stripe_account.deauthorize_and_destroy + }.to change( + StripeAccount.where(stripe_user_id:), :count + ).from(1).to(0) end end From d8d874f7eab5ea97a923e86b1e6cde05df070c68 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Thu, 21 Dec 2023 10:47:24 +0000 Subject: [PATCH 3/3] Creates a connected account and tests OFN code for disconnecting it Re-records cassettes Creates a bogus publishable key We need to feed some value to the ENV variables which are picked up from the local test environment, for the build to run. We could also store them all as environment secrets on our repo, but I don'r think this is necessary, as we only run recorderd API/VCR calls on our build, and never real API calls. --- .env.test | 1 + ...stroys_the_record_and_notifies_Bugsnag.yml | 36 +-- .../destroys_the_record.yml | 261 ++++++++++++++++-- spec/models/stripe_account_spec.rb | 24 +- 4 files changed, 267 insertions(+), 55 deletions(-) diff --git a/.env.test b/.env.test index afa4e58c1d..a52a6b10b4 100644 --- a/.env.test +++ b/.env.test @@ -6,6 +6,7 @@ STRIPE_SECRET_TEST_API_KEY="bogus_key" STRIPE_CUSTOMER="bogus_customer" STRIPE_ACCOUNT="bogus_account" STRIPE_CLIENT_ID="bogus_client_id" +STRIPE_PUBLIC_TEST_API_KEY="bogus_stripe_publishable_key" SITE_URL="test.host" diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml index 4808014362..49aef67136 100644 --- a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml @@ -32,7 +32,7 @@ http_interactions: Server: - nginx Date: - - Tue, 19 Dec 2023 12:55:29 GMT + - Thu, 21 Dec 2023 10:45:56 GMT Content-Type: - application/json; charset=utf-8 Content-Length: @@ -54,22 +54,22 @@ http_interactions: Referrer-Policy: - strict-origin-when-cross-origin Request-Id: - - req_1v8IG0ihHAhDnR + - req_5I7fo8ZIT4iiOD Set-Cookie: - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure; SameSite=None - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=Lax - - machine_identifier=nsadMhesm4x1GYVPmQcxGxkwOEHT0uGESxaoxop6tgOLhu%2BvkqpSkkKcxxRvqqlpa%2BQ%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + - machine_identifier=QgNDMZHR38PElyy9q592gsCebE6wwZpG2yGY42Pr9eBKa8VgTy3D6hYV68qrQ22Ss6M%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=Lax - - private_machine_identifier=5MctxMzB3oEJsWQPiwovzvt6vy1pHt5g4lYzkFr0hY3jCZZPQz%2F6jU71Ye8gqtUCUkE%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + - private_machine_identifier=I5FD6ty3P%2Fu3NcPXx%2FQWf0rlSSmmseIhF3Jjh1k0VDaE0r9pST2zC0QF5zOrj9mL8xU%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=None - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure - - stripe.csrf=ivC9DH1gR7jYwuuHUpqqkApanZ79wswQZMBVKfzfaLr1n5rf_HwKb4sv66YdBNDs03Zq1H_JeHyOjBZ1rENh4jw-AYTZVJxQjKfvlBDZNhjvEvPk5QdyiiBil-k2Op8FixB9Mw4lkg%3D%3D; + - stripe.csrf=3pBovX-WeRInaYekIenxBP4HZPJUKPIapUKWzkq61RZGXY_L4XNwm0d3kPOaWycuCWRVZPILZHIl0E1ajDrp9jw-AYTZVJw3W5vZuecF9T6yl15939IAMLnS4TPsJz7sL-g2uJ-hMA%3D%3D; domain=stripe.com; path=/; secure; HttpOnly; SameSite=None Strict-Transport-Security: - max-age=63072000; includeSubDomains; preload @@ -79,17 +79,17 @@ http_interactions: Stripe-Parent-Id: - '0000000000000000' Stripe-Span-Id: - - 1317edffcd8f0941 + - c9754f0ed47ef010 Www-Authenticate: - Bearer realm="Stripe" X-Apiori-Intentional-Latency: - 0s X-Apiori-Reqid: - - dub2DISD22ogqObCRqkyYRE + - dub1DIXA8nWJL2tSW8r7Vtw X-Apiori-Server-Duration-Ms: - - '126' + - '118' X-Apiori-Upstream-Duration: - - 126.447763ms + - 118.447951ms X-Apiori-Upstream-Name: - manage-srv X-Apiori-Upstream-Region: @@ -99,21 +99,21 @@ http_interactions: X-Envoy-Attempt-Count: - '1' X-Envoy-Upstream-Service-Time: - - '248' + - '235' X-Robots-Tag: - none X-Stripe-Bg-Intended-Route-Color: - - green + - blue X-Stripe-C-Cost: - '2' X-Stripe-Client-Envoy-Start-Time-Us: - - '1702990529582694' + - '1703155556322583' X-Stripe-Rpc-C-Cost-Report: - Cg0IARIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= X-Stripe-Server-Envoy-Start-Time-Us: - - '1702990529583695' + - '1703155556323654' X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: - - '123' + - '115' body: encoding: UTF-8 string: |- @@ -121,5 +121,5 @@ http_interactions: "error": "invalid_client", "error_description": "No such application: 'bogus_client_id'" } - recorded_at: Tue, 19 Dec 2023 12:55:29 GMT + recorded_at: Thu, 21 Dec 2023 10:45:56 GMT recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml index 0c8489a0f3..03de8ad4e2 100644 --- a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml @@ -2,10 +2,10 @@ http_interactions: - request: method: post - uri: https://connect.stripe.com/oauth/deauthorize + uri: https://api.stripe.com/v1/accounts body: encoding: UTF-8 - string: stripe_user_id=&client_id=ca_MzG1xs6tZFDztUlak7uFxoUM36G6307W + string: type=standard&country=AU&email=jumping.jack%40example.com headers: User-Agent: - Stripe/v1 RubyBindings/10.3.0 @@ -26,17 +26,219 @@ http_interactions: - "*/*" response: status: - code: 401 - message: Unauthorized + code: 200 + message: OK headers: Server: - nginx Date: - - Tue, 19 Dec 2023 12:55:30 GMT + - Thu, 21 Dec 2023 10:45:58 GMT Content-Type: - - application/json; charset=utf-8 + - application/json Content-Length: - - '164' + - '2916' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET,HEAD,PUT,PATCH,POST,DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Expose-Headers: + - Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, + X-Stripe-Privileged-Session-Required + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Content-Security-Policy: + - report-uri https://q.stripe.com/csp-report?p=v1%2Faccounts; block-all-mixed-content; + default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; + img-src 'self'; script-src 'self' 'report-sample'; style-src 'self' + Idempotency-Key: + - 4faf7619-9abc-418c-82ab-d4c1b0b2f5ca + Original-Request: + - req_akFJPnmmxbaXxd + Request-Id: + - req_akFJPnmmxbaXxd + Stripe-Should-Retry: + - 'false' + Stripe-Version: + - '2023-10-16' + Vary: + - Origin + X-Stripe-Routing-Context-Priority-Tier: + - api-testmode + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + body: + encoding: UTF-8 + string: |- + { + "id": "acct_1OPjlJQKtA57Vnxb", + "object": "account", + "business_profile": { + "mcc": null, + "name": null, + "product_description": null, + "support_address": null, + "support_email": null, + "support_phone": null, + "support_url": null, + "url": null + }, + "business_type": null, + "capabilities": {}, + "charges_enabled": false, + "controller": { + "is_controller": true, + "type": "application" + }, + "country": "AU", + "created": 1703155558, + "default_currency": "aud", + "details_submitted": false, + "email": "jumping.jack@example.com", + "external_accounts": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/accounts/acct_1OPjlJQKtA57Vnxb/external_accounts" + }, + "future_requirements": { + "alternatives": [], + "current_deadline": null, + "currently_due": [], + "disabled_reason": null, + "errors": [], + "eventually_due": [], + "past_due": [], + "pending_verification": [] + }, + "metadata": {}, + "payouts_enabled": false, + "requirements": { + "alternatives": [], + "current_deadline": null, + "currently_due": [ + "business_profile.product_description", + "business_profile.support_phone", + "business_profile.url", + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "disabled_reason": "requirements.past_due", + "errors": [], + "eventually_due": [ + "business_profile.product_description", + "business_profile.support_phone", + "business_profile.url", + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "past_due": [ + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "pending_verification": [] + }, + "settings": { + "bacs_debit_payments": { + "display_name": null, + "service_user_number": null + }, + "branding": { + "icon": null, + "logo": null, + "primary_color": null, + "secondary_color": null + }, + "card_issuing": { + "tos_acceptance": { + "date": null, + "ip": null + } + }, + "card_payments": { + "decline_on": { + "avs_failure": false, + "cvc_failure": false + }, + "statement_descriptor_prefix": null, + "statement_descriptor_prefix_kana": null, + "statement_descriptor_prefix_kanji": null + }, + "dashboard": { + "display_name": null, + "timezone": "Etc/UTC" + }, + "payments": { + "statement_descriptor": null, + "statement_descriptor_kana": null, + "statement_descriptor_kanji": null + }, + "payouts": { + "debit_negative_balances": true, + "schedule": { + "delay_days": 2, + "interval": "daily" + }, + "statement_descriptor": null + }, + "sepa_debit_payments": {} + }, + "tos_acceptance": { + "date": null, + "ip": null, + "user_agent": null + }, + "type": "standard" + } + recorded_at: Thu, 21 Dec 2023 10:45:58 GMT +- request: + method: post + uri: https://connect.stripe.com/oauth/deauthorize + body: + encoding: UTF-8 + string: stripe_user_id=acct_1OPjlJQKtA57Vnxb&client_id=ca_MzG1xs6tZFDztUlak7uFxoUM36G6307W + headers: + User-Agent: + - Stripe/v1 RubyBindings/10.3.0 + Authorization: + - Bearer + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-Telemetry: + - '{"last_request_metrics":{"request_id":"req_akFJPnmmxbaXxd","request_duration_ms":1906}}' + Stripe-Version: + - '2023-10-16' + X-Stripe-Client-User-Agent: + - '{"bindings_version":"10.3.0","lang":"ruby","lang_version":"3.1.4 p223 (2023-03-30)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 6.2.0-39-generic (buildd@lcy02-amd64-045) (x86_64-linux-gnu-gcc-11 + (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) + #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2","hostname":"ff-LAT"}' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 21 Dec 2023 10:45:59 GMT + Content-Type: + - application/json + Content-Length: + - '47' Connection: - keep-alive Cache-Control: @@ -54,22 +256,22 @@ http_interactions: Referrer-Policy: - strict-origin-when-cross-origin Request-Id: - - req_pGBBuPOXb6xMly + - req_GI4KuC138PCJAi Set-Cookie: - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure; SameSite=None - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=Lax - - machine_identifier=JJUOdPN1UTC9yKxG3Cief9mNanXTKM9y3VmUcEzfmFXEB%2FViV5jXpnxq0kFsEjoKyyg%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + - machine_identifier=HKDeDB5hKqj4clQzAFDSsv1CYfwTn24qrrs%2BEPZII8GCVRJ%2FXlImUJxiAZyJEtIZ%2Fmw%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=Lax - - private_machine_identifier=qnLLWHsR2kIkVnuEZbUabBmPGOMmgoa%2B2t%2Bt82Sn41uVMChBI%2FF%2FmVlhmFtmb9%2Fnd70%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + - private_machine_identifier=MtWBDVmUQlK99LHORT57Q4I%2BFQVz1NgOm8YwuEQ1hcLBZg%2B0065RWGEpjtHqd73XO9g%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=None - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure - - stripe.csrf=aIL_e_YV7LaxFPnsyZHeK9DsuQ7sm4bYeawhyIBlivow1bC0KAoKCaoR0E-WklLxlvDMXwX1_tY7Aa5l_gJ-zzw-AYTZVJwtl69iWowmC5Gcjqp-_ni03g1Mcx1Hbz6xqEXSGCKfKg%3D%3D; + - stripe.csrf=2JHhBnTu9M9rT2X5ddKYKiGrldjy1_TlDZkBH0QYBxLbuX5pF9u2LvZHkuwLr3S96XXp0ZHdgqJRzdhyPTMYmDw-AYTZVJziZaudEZeavUdznjQfqSpNTprhJdapun0wOEWmMxs7zQ%3D%3D; domain=stripe.com; path=/; secure; HttpOnly; SameSite=None Strict-Transport-Security: - max-age=63072000; includeSubDomains; preload @@ -79,17 +281,15 @@ http_interactions: Stripe-Parent-Id: - '0000000000000000' Stripe-Span-Id: - - abaf119f94aa71c4 - Www-Authenticate: - - Bearer realm="Stripe" + - 7c70338af8eb59d9 X-Apiori-Intentional-Latency: - 0s X-Apiori-Reqid: - - dub1DISD299L0WxB0Akf1uq + - dub1DIXA981iCMFaeUWou2O X-Apiori-Server-Duration-Ms: - - '138' + - '226' X-Apiori-Upstream-Duration: - - 137.918128ms + - 225.729973ms X-Apiori-Upstream-Name: - manage-srv X-Apiori-Upstream-Region: @@ -99,27 +299,28 @@ http_interactions: X-Envoy-Attempt-Count: - '1' X-Envoy-Upstream-Service-Time: - - '257' + - '347' X-Robots-Tag: - none X-Stripe-Bg-Intended-Route-Color: - - green + - blue X-Stripe-C-Cost: - - '4' + - '22' X-Stripe-Client-Envoy-Start-Time-Us: - - '1702990530466139' + - '1703155559193296' X-Stripe-Rpc-C-Cost-Report: - - Cg0IAxIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= + - Cg0IFBIJY2VsbF8wMDA3Cg8IAhILZ2xvYmFsX2NlbGw= X-Stripe-Server-Envoy-Start-Time-Us: - - '1702990530466931' + - '1703155559194276' X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: - - '135' + - '223' + Stripe-Action-Id: + - dub1DIXA981iCMFaeUWou2O body: encoding: UTF-8 string: |- { - "error": "invalid_client", - "error_description": "This application is not connected to stripe account , or that account does not exist." + "stripe_user_id": "acct_1OPjlJQKtA57Vnxb" } - recorded_at: Tue, 19 Dec 2023 12:55:30 GMT + recorded_at: Thu, 21 Dec 2023 10:45:59 GMT recorded_with: VCR 6.2.0 diff --git a/spec/models/stripe_account_spec.rb b/spec/models/stripe_account_spec.rb index 374f7ee640..d890152bb7 100644 --- a/spec/models/stripe_account_spec.rb +++ b/spec/models/stripe_account_spec.rb @@ -9,13 +9,13 @@ describe StripeAccount do let!(:enterprise2) { create(:enterprise) } let(:client_id) { ENV.fetch('STRIPE_CLIENT_ID', nil) } let(:stripe_user_id) { ENV.fetch('STRIPE_ACCOUNT', nil) } + let(:stripe_publishable_key) { ENV.fetch('STRIPE_PUBLIC_TEST_API_KEY', nil) } + let(:secret) { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } let!(:stripe_account) { create(:stripe_account, enterprise:, stripe_user_id:) } - let(:secret) { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } - before do Stripe.api_key = secret end @@ -25,7 +25,7 @@ describe StripeAccount do it "destroys the record and notifies Bugsnag" do # returns status 401 - expect(Bugsnag).to receive(:notify) + expect(Bugsnag).to receive(:notify) # and receives Bugsnag notification expect { stripe_account.deauthorize_and_destroy }.to change( @@ -35,16 +35,26 @@ describe StripeAccount do end context "when the Stripe API disconnect succeeds" do - before { Stripe.client_id = client_id } + let!(:connected_account) do + Stripe::Account.create({ + type: 'standard', + country: 'AU', + email: 'jumping.jack@example.com' + }) + end + + before do + Stripe.client_id = client_id + stripe_account.update!(stripe_publishable_key:, stripe_user_id: connected_account.id) + end it "destroys the record" do # returns status 200 - expect(Bugsnag).to_not receive(:notify) - stripe_account.deauthorize_and_destroy + expect(Bugsnag).to_not receive(:notify) # and does not receive Bugsnag notification expect { stripe_account.deauthorize_and_destroy }.to change( - StripeAccount.where(stripe_user_id:), :count + StripeAccount.where(stripe_user_id: connected_account.id), :count ).from(1).to(0) end end