Files
sure/test/controllers/wise_items_controller_test.rb
Blaž Dular 7b0f98b1d6 fix(wise): redirect after token submission instead of rendering inline (#2730)
* fix(wise): redirect after token submission instead of rendering inline

The success path in create rendered select_profiles directly (200 OK),
which Turbo rejects for standard form submissions ('Form responses must
redirect to another location'). Now it redirects, carrying the encrypted
token through the session. Session-expired fallbacks now point at
settings_providers_path instead of new_wise_item_path, which has no view.

* test(wise): update controller specs for redirect-based create flow

* fix(wise): read pending token from session, not client params

link_profiles decrypted params[:encrypted_pending_token], even though create
already stores the encrypted token server-side in the session. The client
round-trip was unnecessary and untrusted; now link_profiles reads directly
from session[:wise_pending_encrypted_token].
2026-07-21 01:28:53 +02:00

97 lines
3.8 KiB
Ruby

# frozen_string_literal: true
require "test_helper"
class WiseItemsControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in users(:family_admin)
SyncJob.stubs(:perform_later)
@family = families(:dylan_family)
@wise_item = wise_items(:one)
@valid_profiles = [
{ "id" => "99999999", "type" => "personal", "details" => { "firstName" => "Jane", "lastName" => "Doe" } }
]
end
# create redirects to select_profiles (Turbo requires a redirect from a standard
# form submission) — the encrypted token travels via the session, not the response body.
test "create redirects to select_profiles and keeps raw token out of the session" do
Provider::Wise.any_instance.stubs(:get_profiles).returns(@valid_profiles)
post wise_items_url, params: { wise_item: { token: "live_token_abc" } }
assert_redirected_to select_profiles_wise_items_path
assert_nil session[:wise_pending_token], "raw API token must not be stored in the session"
assert session[:wise_pending_encrypted_token].present?
follow_redirect!
assert_select "input[name='encrypted_pending_token']"
end
test "create stores an encrypted token that round-trips to the original value" do
Provider::Wise.any_instance.stubs(:get_profiles).returns(@valid_profiles)
post wise_items_url, params: { wise_item: { token: "live_token_abc" } }
follow_redirect!
encrypted = css_select("input[name='encrypted_pending_token']").first["value"]
assert encrypted.present?, "hidden encrypted_pending_token field must be present"
key = Rails.application.key_generator.generate_key("wise_pending_token", 32)
decrypted = ActiveSupport::MessageEncryptor.new(key).decrypt_and_verify(encrypted)
assert_equal "live_token_abc", decrypted
end
test "create redirects to providers on blank token" do
post wise_items_url, params: { wise_item: { token: "" } }
assert_redirected_to settings_providers_path
assert_nil session[:wise_pending_token]
end
test "create redirects to providers when Wise API rejects the token" do
Provider::Wise.any_instance.stubs(:get_profiles).raises(
Provider::Wise::WiseError.new("unauthorized", :unauthorized)
)
post wise_items_url, params: { wise_item: { token: "bad_token" } }
assert_redirected_to settings_providers_path
assert_nil session[:wise_pending_token]
end
# link_profiles reads the encrypted token from the session (set by create) —
# the client no longer needs to (and cannot) supply or tamper with it via params.
test "link_profiles creates WiseItems using the session-held encrypted token" do
Provider::Wise.any_instance.stubs(:get_profiles).returns(@valid_profiles)
post wise_items_url, params: { wise_item: { token: "live_token_abc" } }
assert_difference "WiseItem.count", 1 do
post link_profiles_wise_items_url, params: { profile_ids: [ "99999999" ] }
end
assert_redirected_to settings_providers_path
assert_equal "live_token_abc", @family.wise_items.find_by!(profile_id: "99999999").token
assert_nil session[:wise_pending_profiles]
assert_nil session[:wise_pending_encrypted_token]
end
test "link_profiles redirects to providers when there is no pending session" do
post link_profiles_wise_items_url, params: { profile_ids: [ "99999999" ] }
assert_redirected_to settings_providers_path
end
test "link_profiles redirects to providers when the session token cannot be decrypted" do
Provider::Wise.any_instance.stubs(:get_profiles).returns(@valid_profiles)
post wise_items_url, params: { wise_item: { token: "live_token_abc" } }
session[:wise_pending_encrypted_token] = "corrupted_garbage_value"
post link_profiles_wise_items_url, params: { profile_ids: [ "99999999" ] }
assert_redirected_to settings_providers_path
end
end