From 322ace7fca7537c2cb88d5ca2dda570faf5effd1 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 8 Jul 2022 09:20:00 -0400 Subject: [PATCH 1/4] IdV API: Set last GPO code for auto-fill in local development **Why**: So that a developer can complete the GPO proofing flow locally. [skip changelog] --- .../api/verify/password_confirm_controller.rb | 17 ++++++---- app/forms/api/profile_creation_form.rb | 7 ++-- .../password_confirm_controller_spec.rb | 34 ++++++++++++++++--- spec/forms/api/profile_creation_form_spec.rb | 13 +++++++ 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/verify/password_confirm_controller.rb b/app/controllers/api/verify/password_confirm_controller.rb index 0751f43cdc3..424b1e17ff9 100644 --- a/app/controllers/api/verify/password_confirm_controller.rb +++ b/app/controllers/api/verify/password_confirm_controller.rb @@ -4,16 +4,12 @@ class PasswordConfirmController < BaseController self.required_step = 'password_confirm' def create - result, personal_key = Api::ProfileCreationForm.new( - password: verify_params[:password], - jwt: verify_params[:user_bundle_token], - user_session: user_session, - service_provider: current_sp, - ).submit + result, personal_key, gpo_code = form.submit if result.success? user = User.find_by(uuid: result.extra[:user_uuid]) add_proofing_component(user) + session[:last_gpo_confirmation_code] = gpo_code if gpo_code render json: { personal_key: personal_key, completion_url: completion_url(result), @@ -25,6 +21,15 @@ def create private + def form + Api::ProfileCreationForm.new( + password: verify_params[:password], + jwt: verify_params[:user_bundle_token], + user_session: user_session, + service_provider: current_sp, + ) + end + def verify_params params.permit(:password, :user_bundle_token) end diff --git a/app/forms/api/profile_creation_form.rb b/app/forms/api/profile_creation_form.rb index 17406dbaace..602e89d2b4e 100644 --- a/app/forms/api/profile_creation_form.rb +++ b/app/forms/api/profile_creation_form.rb @@ -6,9 +6,7 @@ class ProfileCreationForm validate :valid_user validate :valid_password - attr_reader :password, :user_bundle - attr_reader :user_session, :service_provider - attr_reader :profile + attr_reader :password, :user_bundle, :user_session, :service_provider, :profile, :gpo_code def initialize(password:, jwt:, user_session:, service_provider: nil) @password = password @@ -32,7 +30,7 @@ def submit errors: errors, extra: extra_attributes, ) - [response, personal_key] + [response, personal_key, gpo_code] end private @@ -80,6 +78,7 @@ def create_gpo_entry profile: profile, ) confirmation_maker.perform + @gpo_code = confirmation_maker.otp if FeatureManagement.reveal_gpo_code? end def build_profile_maker diff --git a/spec/controllers/api/verify/password_confirm_controller_spec.rb b/spec/controllers/api/verify/password_confirm_controller_spec.rb index 51e1db863c0..9eb3375b463 100644 --- a/spec/controllers/api/verify/password_confirm_controller_spec.rb +++ b/spec/controllers/api/verify/password_confirm_controller_spec.rb @@ -42,7 +42,7 @@ def stub_idv_session end it 'creates a profile and returns a key and completion url' do - post :create, params: { password: 'iambatman', user_bundle_token: jwt } + post :create, params: { password: password, user_bundle_token: jwt } parsed_body = JSON.parse(response.body) expect(parsed_body).to include( 'personal_key' => kind_of(String), @@ -65,7 +65,7 @@ def stub_idv_session end it 'creates a profile and returns completion url' do - post :create, params: { password: 'iambatman', user_bundle_token: jwt } + post :create, params: { password: password, user_bundle_token: jwt } expect(JSON.parse(response.body)['completion_url']).to eq(sign_up_completed_url) end @@ -75,11 +75,37 @@ def stub_idv_session let(:jwt_metadata) { { vendor_phone_confirmation: false, user_phone_confirmation: false } } it 'creates a profile and returns completion url' do - post :create, params: { password: 'iambatman', user_bundle_token: jwt } + post :create, params: { password: password, user_bundle_token: jwt } expect(JSON.parse(response.body)['completion_url']).to eq(idv_come_back_later_url) end end + + context 'with gpo_code returned from form submission' do + let(:gpo_code) { 'ABC1234' } + + let(:form) do + Api::ProfileCreationForm.new( + password: password, + jwt: jwt_metadata, + user_session: {}, + service_provider: {}, + ) + end + + before do + allow(subject).to receive(:form).and_return(form) + allow(form).to receive(:submit).and_return( + [FormResponse.new(success: true, extra: { user_uuid: user.uuid }), '', gpo_code], + ) + end + + it 'sets code into the session' do + post :create, params: { password: password, user_bundle_token: jwt } + + expect(session[:last_gpo_confirmation_code]).to eq(gpo_code) + end + end end context 'when the idv api is not enabled' do @@ -88,7 +114,7 @@ def stub_idv_session end it 'responds with not found' do - post :create, params: { password: 'iambatman', user_bundle_token: jwt }, as: :json + post :create, params: { password: password, user_bundle_token: jwt }, as: :json expect(response.status).to eq 404 expect(JSON.parse(response.body)['error']). to eq "The page you were looking for doesn't exist" diff --git a/spec/forms/api/profile_creation_form_spec.rb b/spec/forms/api/profile_creation_form_spec.rb index d627b5a059b..547c4dd71b2 100644 --- a/spec/forms/api/profile_creation_form_spec.rb +++ b/spec/forms/api/profile_creation_form_spec.rb @@ -108,6 +108,19 @@ expect(profile.gpo_confirmation_codes.first_with_otp(gpo_otp)).not_to be_nil end + + context 'with reveal_gpo_code? feature enabled' do + before do + allow(FeatureManagement).to receive(:reveal_gpo_code?).and_return(true) + end + + it 'returns code from the submission result the session' do + _response, _personal_key, actual_gpo_code = subject.submit + expected_gpo_code = GpoConfirmation.last.entry[:otp] + + expect(actual_gpo_code).to eq(expected_gpo_code) + end + end end end From 7db7fa21817f32281b52ea7739b0612af6c3278d Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 8 Jul 2022 10:02:41 -0400 Subject: [PATCH 2/4] Add feature guard for GPO code session assignment See: https://github.com/18F/identity-idp/pull/6561#discussion_r916838564 --- app/controllers/api/verify/password_confirm_controller.rb | 6 +++++- .../api/verify/password_confirm_controller_spec.rb | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/verify/password_confirm_controller.rb b/app/controllers/api/verify/password_confirm_controller.rb index 424b1e17ff9..7c2282c1ab5 100644 --- a/app/controllers/api/verify/password_confirm_controller.rb +++ b/app/controllers/api/verify/password_confirm_controller.rb @@ -9,7 +9,7 @@ def create if result.success? user = User.find_by(uuid: result.extra[:user_uuid]) add_proofing_component(user) - session[:last_gpo_confirmation_code] = gpo_code if gpo_code + set_session_last_gpo_code(gpo_code) render json: { personal_key: personal_key, completion_url: completion_url(result), @@ -30,6 +30,10 @@ def form ) end + def set_session_last_gpo_code(code) + session[:last_gpo_confirmation_code] = code if code && FeatureManagement.reveal_gpo_code? + end + def verify_params params.permit(:password, :user_bundle_token) end diff --git a/spec/controllers/api/verify/password_confirm_controller_spec.rb b/spec/controllers/api/verify/password_confirm_controller_spec.rb index 9eb3375b463..fce0e88fd24 100644 --- a/spec/controllers/api/verify/password_confirm_controller_spec.rb +++ b/spec/controllers/api/verify/password_confirm_controller_spec.rb @@ -81,8 +81,8 @@ def stub_idv_session end end - context 'with gpo_code returned from form submission' do - let(:gpo_code) { 'ABC1234' } + context 'with gpo_code returned from form submission and reveal gpo feature enabled' do + let(:gpo_code) { SecureRandom.hex } let(:form) do Api::ProfileCreationForm.new( @@ -94,6 +94,7 @@ def stub_idv_session end before do + allow(FeatureManagement).to receive(:reveal_gpo_code?).and_return(true) allow(subject).to receive(:form).and_return(form) allow(form).to receive(:submit).and_return( [FormResponse.new(success: true, extra: { user_uuid: user.uuid }), '', gpo_code], From cac953fbc3ee6427c5aa4ba628101495b96ae185 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 8 Jul 2022 13:38:28 -0400 Subject: [PATCH 3/4] Assign GPO code from form instance See: https://github.com/18F/identity-idp/pull/6561/files#r916935007 --- app/controllers/api/verify/password_confirm_controller.rb | 6 +++--- app/forms/api/profile_creation_form.rb | 2 +- .../api/verify/password_confirm_controller_spec.rb | 6 ++---- spec/forms/api/profile_creation_form_spec.rb | 8 ++++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/verify/password_confirm_controller.rb b/app/controllers/api/verify/password_confirm_controller.rb index 7c2282c1ab5..3ce9df7252b 100644 --- a/app/controllers/api/verify/password_confirm_controller.rb +++ b/app/controllers/api/verify/password_confirm_controller.rb @@ -4,12 +4,12 @@ class PasswordConfirmController < BaseController self.required_step = 'password_confirm' def create - result, personal_key, gpo_code = form.submit + result, personal_key = form.submit if result.success? user = User.find_by(uuid: result.extra[:user_uuid]) add_proofing_component(user) - set_session_last_gpo_code(gpo_code) + set_session_last_gpo_code(form.gpo_code) render json: { personal_key: personal_key, completion_url: completion_url(result), @@ -22,7 +22,7 @@ def create private def form - Api::ProfileCreationForm.new( + @form ||= Api::ProfileCreationForm.new( password: verify_params[:password], jwt: verify_params[:user_bundle_token], user_session: user_session, diff --git a/app/forms/api/profile_creation_form.rb b/app/forms/api/profile_creation_form.rb index 602e89d2b4e..9a84ceb3dd4 100644 --- a/app/forms/api/profile_creation_form.rb +++ b/app/forms/api/profile_creation_form.rb @@ -30,7 +30,7 @@ def submit errors: errors, extra: extra_attributes, ) - [response, personal_key, gpo_code] + [response, personal_key] end private diff --git a/spec/controllers/api/verify/password_confirm_controller_spec.rb b/spec/controllers/api/verify/password_confirm_controller_spec.rb index fce0e88fd24..3ff27649da1 100644 --- a/spec/controllers/api/verify/password_confirm_controller_spec.rb +++ b/spec/controllers/api/verify/password_confirm_controller_spec.rb @@ -87,7 +87,7 @@ def stub_idv_session let(:form) do Api::ProfileCreationForm.new( password: password, - jwt: jwt_metadata, + jwt: jwt, user_session: {}, service_provider: {}, ) @@ -96,9 +96,7 @@ def stub_idv_session before do allow(FeatureManagement).to receive(:reveal_gpo_code?).and_return(true) allow(subject).to receive(:form).and_return(form) - allow(form).to receive(:submit).and_return( - [FormResponse.new(success: true, extra: { user_uuid: user.uuid }), '', gpo_code], - ) + allow(form).to receive(:gpo_code).and_return(gpo_code) end it 'sets code into the session' do diff --git a/spec/forms/api/profile_creation_form_spec.rb b/spec/forms/api/profile_creation_form_spec.rb index 547c4dd71b2..bc351f67790 100644 --- a/spec/forms/api/profile_creation_form_spec.rb +++ b/spec/forms/api/profile_creation_form_spec.rb @@ -114,11 +114,11 @@ allow(FeatureManagement).to receive(:reveal_gpo_code?).and_return(true) end - it 'returns code from the submission result the session' do - _response, _personal_key, actual_gpo_code = subject.submit - expected_gpo_code = GpoConfirmation.last.entry[:otp] + it 'assigns gpo code' do + subject.submit + gpo_code = GpoConfirmation.last.entry[:otp] - expect(actual_gpo_code).to eq(expected_gpo_code) + expect(subject.gpo_code).to eq(gpo_code) end end end From 346d694afb6eb306b81cb94f3fa6908b24007bbb Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 8 Jul 2022 13:39:04 -0400 Subject: [PATCH 4/4] Rename "set_" to "store_" See: https://github.com/18F/identity-idp/pull/6561/files#r916933401 Co-Authored-By: Zach Margolis --- app/controllers/api/verify/password_confirm_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/verify/password_confirm_controller.rb b/app/controllers/api/verify/password_confirm_controller.rb index 3ce9df7252b..8f1d4a2fef7 100644 --- a/app/controllers/api/verify/password_confirm_controller.rb +++ b/app/controllers/api/verify/password_confirm_controller.rb @@ -9,7 +9,7 @@ def create if result.success? user = User.find_by(uuid: result.extra[:user_uuid]) add_proofing_component(user) - set_session_last_gpo_code(form.gpo_code) + store_session_last_gpo_code(form.gpo_code) render json: { personal_key: personal_key, completion_url: completion_url(result), @@ -30,7 +30,7 @@ def form ) end - def set_session_last_gpo_code(code) + def store_session_last_gpo_code(code) session[:last_gpo_confirmation_code] = code if code && FeatureManagement.reveal_gpo_code? end