From 1550724800e9fd970d1022ee27a54d3712cab65f Mon Sep 17 00:00:00 2001 From: George Byers Date: Tue, 7 May 2024 11:10:57 -0400 Subject: [PATCH] Feature/ffs 675 (#16) * added new migration for connected_argyle_accounts * added ConnectedArgyleAccount model * added ability to query payroll-data from argyle for connected account. added webhook logic to persist connected accounts into the database * uncommented signature check * Passing test for Argyle payroll * fixed test assertions and stubs * updated test descriptions and made them look pretty * updates per PR feedback * moved test setup logic to before block --- .github/actions/setup-project/action.yml | 1 + .gitignore | 2 +- Gemfile.lock | 3 ++ .../webhooks/argyle/events_controller.rb | 20 ++++++-- app/models/connected_argyle_account.rb | 4 ++ app/services/argyle_service.rb | 10 +++- config/credentials/development.yml.enc | 2 +- config/database.yml | 4 ++ ...195250_create_connected_argyle_accounts.rb | 10 ++++ db/schema.rb | 9 +++- doc/compliance/rendered/apps/data.logical.pdf | Bin 22481 -> 29392 bytes spec/services/argyle_service_spec.rb | 44 ++++++++++++++++-- .../support/account_connected_webhook_stub.rb | 44 ++++++++++++++++++ .../payroll_documents_response_stub.rb | 36 ++++++++++++++ spec/support/webhook_x_argyle_signature.rb | 3 ++ 15 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 app/models/connected_argyle_account.rb create mode 100644 db/migrate/20240502195250_create_connected_argyle_accounts.rb create mode 100644 spec/support/account_connected_webhook_stub.rb create mode 100644 spec/support/payroll_documents_response_stub.rb create mode 100644 spec/support/webhook_x_argyle_signature.rb diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml index 2d31237f7..87e281d0f 100644 --- a/.github/actions/setup-project/action.yml +++ b/.github/actions/setup-project/action.yml @@ -11,6 +11,7 @@ inputs: default: postgres://cidbuser:postgres@localhost:5432/iv_cbv_payroll_test outputs: database_url: + description: The database URL that was set value: ${{ inputs.database_url }} runs: using: composite diff --git a/.gitignore b/.gitignore index 17e204928..c7f763919 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,7 @@ Brewfile.lock.json # Ignore local dotenv overrides .env*.local - +.env.test # Ignore OWASP files /zap_report.html /zap.yaml diff --git a/Gemfile.lock b/Gemfile.lock index 62e9e0706..f35aed20c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -160,6 +160,8 @@ GEM net-protocol newrelic_rpm (8.16.0) nio4r (2.7.1) + nokogiri (1.16.4-aarch64-linux) + racc (~> 1.4) nokogiri (1.16.4-arm64-darwin) racc (~> 1.4) nokogiri (1.16.4-x86_64-darwin) @@ -337,6 +339,7 @@ GEM zeitwerk (2.6.13) PLATFORMS + aarch64-linux arm64-darwin-23 x86_64-darwin-20 x86_64-linux diff --git a/app/controllers/webhooks/argyle/events_controller.rb b/app/controllers/webhooks/argyle/events_controller.rb index f9e95c052..8968a1268 100644 --- a/app/controllers/webhooks/argyle/events_controller.rb +++ b/app/controllers/webhooks/argyle/events_controller.rb @@ -2,19 +2,29 @@ class Webhooks::Argyle::EventsController < ApplicationController skip_before_action :verify_authenticity_token def create - signature = OpenSSL::HMAC.hexdigest('SHA512', ENV['ARGYLE_WEBHOOK_SECRET'], request.raw_post) + signature = OpenSSL::HMAC.hexdigest("SHA512", ENV["ARGYLE_WEBHOOK_SECRET"], request.raw_post) unless request.headers["X-Argyle-Signature"] == signature - return render json: { error: 'Invalid signature' }, status: :unauthorized + return render json: { error: "Invalid signature" }, status: :unauthorized end - if params['event'] == 'paystubs.fully_synced' || params['event'] == 'paystubs.partially_synced' - @cbv_flow = CbvFlow.find_by_argyle_user_id(params['data']['user']) + if params["event"] == "paystubs.fully_synced" || params["event"] == "paystubs.partially_synced" + @cbv_flow = CbvFlow.find_by_argyle_user_id(params["data"]["user"]) if @cbv_flow - @cbv_flow.update(payroll_data_available_from: params['data']['available_from']) + @cbv_flow.update(payroll_data_available_from: params["data"]["available_from"]) ArgylePaystubsChannel.broadcast_to(@cbv_flow, params) end end + + if params["event"] == "accounts.connected" + rep = ConnectedArgyleAccount.create!( + user_id: params["data"]["user"], + account_id: params["data"]["account"] + ) + Rails.logger.info "ConnectedArgyleAccount created: #{rep}" + render json: { message: "ConnectedArgyleAccount created", data: rep }, status: :created + end + end end diff --git a/app/models/connected_argyle_account.rb b/app/models/connected_argyle_account.rb new file mode 100644 index 000000000..229534aa2 --- /dev/null +++ b/app/models/connected_argyle_account.rb @@ -0,0 +1,4 @@ +class ConnectedArgyleAccount < ApplicationRecord + validates :user_id, presence: true + validates :account_id, presence: true +end diff --git a/app/services/argyle_service.rb b/app/services/argyle_service.rb index 67f6536f3..60835da90 100644 --- a/app/services/argyle_service.rb +++ b/app/services/argyle_service.rb @@ -5,6 +5,7 @@ class ArgyleService def initialize @api_key = Rails.application.credentials.argyle[:api_key] base_url = ENV["ARGYLE_API_URL"] || "https://api-sandbox.argyle.com/v2" + client_options = { request: { open_timeout: 5, @@ -21,8 +22,15 @@ def initialize # Fetch all Argyle items def items(query = nil) - # get "items" and pass the query as the q parameter for the Faraday instance response = @http.get("items", { q: query }) JSON.parse(response.body) end + + def payroll_documents(account_id, user_id) + account_exists = ConnectedArgyleAccount.exists?(user_id: user_id, account_id: account_id) + raise "Argyle error: Account not connected" unless account_exists + response = @http.get("payroll-documents", { account: account_id, user: user_id }) + JSON.parse(response.body) + end + end diff --git a/config/credentials/development.yml.enc b/config/credentials/development.yml.enc index 8e0c56934..a37074995 100644 --- a/config/credentials/development.yml.enc +++ b/config/credentials/development.yml.enc @@ -1 +1 @@ -Btn0OVg1L730VpNEbQ+H15cFKg1y3q/z6IwIaDc9c4iExboCtzTUsYU/NO4sXKVZ0m0ShItWOKR4IxwCqw7GrIRKckilMnNhJKKMZJ9clj6CieYC9efIb8WeUe3c11AA--KLu1KB+ynGorNBrB--+jEPdTuPzExEtrlSeJzR9g== \ No newline at end of file +pWx+QNd/gK0RyL9jUoME8AVCKEPpGVXDzQrBov/o5dQNXhb3AF8ZLVEFErUXesZPt+ZFjO0kOWfgwHALtRtwkWHZpt6mF7odr9fG4W6pQkorMPHdwaVVJoSTCHbQ5a357qF0EcuDXXmHCGqqr0sG0ly+8NNLSmOM4zdV0Rq1Rwi0hnQjo4RPSZ6hIiYTR3VqwAxbAaWqLwC01Q/wbt/bxNHKq0f6k/Q9yQQ=--MpaWHAhpoYnJd8WO--pz1XxYcKma6dhIuVugJv8w== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml index 1d103fa8c..135f2d408 100644 --- a/config/database.yml +++ b/config/database.yml @@ -61,6 +61,10 @@ development: test: <<: *default database: iv_cbv_payroll_test + host: <%= ENV.fetch("DB_HOST") { "localhost" } %> + username: <%= ENV.fetch("DB_USERNAME") { nil } %> + # The password associated with the postgres role (username). + password: <%= ENV.fetch("DB_PASSWORD") { nil } %> # As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is diff --git a/db/migrate/20240502195250_create_connected_argyle_accounts.rb b/db/migrate/20240502195250_create_connected_argyle_accounts.rb new file mode 100644 index 000000000..63b63eab6 --- /dev/null +++ b/db/migrate/20240502195250_create_connected_argyle_accounts.rb @@ -0,0 +1,10 @@ +class CreateConnectedArgyleAccounts < ActiveRecord::Migration[7.0] + def change + create_table :connected_argyle_accounts do |t| + t.uuid :user_id, null: false + t.uuid :account_id, null: false + t.timestamps null: false + t.index [ :user_id, :account_id ], unique: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 7b9743eeb..ae447aed5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2024_05_01_192504) do +ActiveRecord::Schema[7.0].define(version: 2024_05_02_195250) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -27,4 +27,11 @@ t.date "payroll_data_available_from" end + create_table "connected_argyle_accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "user_id", null: false + t.uuid "account_id", null: false + t.datetime "created_at", default: -> { "CURRENT_TIMESTAMP" }, null: false + t.index ["user_id", "account_id"], name: "index_connected_argyle_accounts_on_user_id_and_account_id", unique: true + end + end diff --git a/doc/compliance/rendered/apps/data.logical.pdf b/doc/compliance/rendered/apps/data.logical.pdf index 5edc91406b6d773a530b0fe9ab96449400713b3d..0b07fc5358a234814e471b1c1985720e744d1bca 100644 GIT binary patch literal 29392 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 oagqMjcF7zPpn+a literal 22481 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 SI~&9husAUd4O1J6*na@mNA3>* diff --git a/spec/services/argyle_service_spec.rb b/spec/services/argyle_service_spec.rb index bcda50cbc..6f5ca8b45 100644 --- a/spec/services/argyle_service_spec.rb +++ b/spec/services/argyle_service_spec.rb @@ -1,6 +1,13 @@ require 'rails_helper' +require 'support/account_connected_webhook_stub' +require 'support/payroll_documents_response_stub' RSpec.describe ArgyleService, type: :service do + let(:service) { ArgyleService.new } + let(:account_id) { 'account_id' } + let(:user_id) { 'user_id' } + let(:fake_response) { instance_double(Faraday::Response, body: payroll_documents_response_stub) } + describe 'Initialization' do it 'has a default API endpoint pointing to the sandbox' do service = ArgyleService.new @@ -11,15 +18,46 @@ end describe '#items' do - it 'returns a non-empty response' do - service = ArgyleService.new + before do # Stub the HTTP call to return a non-empty JSON response fake_response = instance_double(Faraday::Response, body: '[{"id": "12345"}]') allow_any_instance_of(Faraday::Connection).to receive(:get).with("items", { q: nil }).and_return(fake_response) - + end + it 'returns a non-empty response' do + service = ArgyleService.new response = service.items expect(response).not_to be_empty expect(response.first['id']).to eq("12345") end end + + describe '#payroll_documents' do + context 'when ConnectedArgyleAccount exists' do + before do + # simulate that fetching the payroll documents returns a non-empty JSON response resembling payroll data + allow_any_instance_of(Faraday::Connection).to receive(:get).with("payroll-documents", { account: account_id, user: user_id }).and_return(fake_response) + end + + it 'invokes the ArguleApiService and returns payroll documents' do + # simulate that we have a ConnectedArgyleAccount record + allow(ConnectedArgyleAccount).to receive(:exists?).with(user_id: user_id, account_id: account_id).and_return(true) + response = service.payroll_documents(account_id, user_id) + + # expect that user_id, account_id stored in the ConnectedArgyleAccount record match the id and acount in the response + expect(response).not_to be_empty + expect(response['data'][0]['id']).to eq(JSON.parse(fake_response.body)['data'][0]['id']) + expect(response['data'][0]['account']).to eq(JSON.parse(fake_response.body)['data'][0]['account']) + end + end + + context 'when ConnectedArgyleAccount does not exist' do + before do + allow(ConnectedArgyleAccount).to receive(:exists?).with(user_id: user_id, account_id: account_id).and_return(false) + end + + it 'raises an error' do + expect { service.payroll_documents(account_id, user_id) }.to raise_error("Argyle error: Account not connected") + end + end + end end diff --git a/spec/support/account_connected_webhook_stub.rb b/spec/support/account_connected_webhook_stub.rb new file mode 100644 index 000000000..203d25818 --- /dev/null +++ b/spec/support/account_connected_webhook_stub.rb @@ -0,0 +1,44 @@ +def account_connected_webhook_stub + '{ + "event": "accounts.connected", + "name": "Account Connected", + "data": { + "account": "018f3fb8-47b7-7a9f-b95a-530117e8522e", + "user": "018f110a-39c1-3a5f-826f-a004eb7ed0b5", + "resource": { + "id": "018f3fb8-47b7-7a9f-b95a-530117e8522e", + "user": "018f110a-39c1-3a5f-826f-a004eb7ed0b5", + "employers": [], + "item": "item_000012375", + "source": "argyle_sandbox", + "created_at": "2024-05-03T18:29:52.780604Z", + "updated_at": "2024-05-03T18:30:09.761659Z", + "connection": { + "status": "connected", + "error_code": null, + "error_message": null, + "updated_at": "2024-05-03T18:30:09.137853Z" + }, + "direct_deposit_switch": { + "status": "idle", + "error_code": null, + "error_message": null, + "updated_at": "2024-05-03T18:29:53.219572Z" + }, + "availability": { + "gigs": null, + "paystubs": null, + "payroll_documents": null, + "identities": null, + "ratings": null, + "vehicles": null, + "deposit_destinations": null, + "user_forms": null + }, + "ongoing_refresh": { + "status": "idle" + } + } + } + }' +end diff --git a/spec/support/payroll_documents_response_stub.rb b/spec/support/payroll_documents_response_stub.rb new file mode 100644 index 000000000..75c5d1f1b --- /dev/null +++ b/spec/support/payroll_documents_response_stub.rb @@ -0,0 +1,36 @@ +def payroll_documents_response_stub + '{ + "data": [ + { + "id": "018f110a-39c1-3a5f-826f-a004eb7ed0b5", + "account": "018f3fb8-47b7-7a9f-b95a-530117e8522e", + "document_number": null, + "available_date": "2020-05-13T17:25:59Z", + "expiration_date": null, + "employer": "Whole Goods", + "document_type": "payout-statement", + "document_type_description": null, + "file_url": "api.argyle.com/v2/payroll-documents/{id}/file", + "created_at": "2023-03-13T17:27:01.501Z", + "updated_at": "2023-03-13T17:27:01.501Z", + "ocr_data": {}, + "metadata": {} + }, + { + "id": "018f110a-39c1-3a5f-826f-a004eb7ed0b5", + "account": "018f3fb8-47b7-7a9f-b95a-530117e8522e", + "document_number": "ced46eb3-7586-3cd7-2418-8eb9482bc3ec", + "available_date": "2019-03-14T17:46:25Z", + "expiration_date": "2027-03-12T17:46:25Z", + "employer": "GigAndGo", + "document_type": "drivers-licence", + "document_type_description": "Driver\'s license", + "file_url": "api.argyle.com/v2/payroll-documents/{id}/file", + "created_at": "2023-03-13T17:46:28.240Z", + "updated_at": "2023-03-13T17:46:28.240Z", + "ocr_data": {}, + "metadata": {} + } + ] + }' +end diff --git a/spec/support/webhook_x_argyle_signature.rb b/spec/support/webhook_x_argyle_signature.rb new file mode 100644 index 000000000..d4daecd4b --- /dev/null +++ b/spec/support/webhook_x_argyle_signature.rb @@ -0,0 +1,3 @@ +def webhook_x_argyle_signature + 'X-Argyle-Signature: cbc0045ca9ba037086d7396966516349bc7a0c9f48b0eaf1e2d0a5002d77dc7202b48e88bfb0ad3a8973e56998a6ad519f98801cee9527be4297f53223d3f8bf' +end