From a393ab40d14098dc0030ca8fddd778871832d400 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 5 Dec 2024 12:03:20 +0000 Subject: [PATCH 1/3] can extract full name from OL JWT --- app/models/one_login/core_identity_validator.rb | 4 ++++ .../one_login/core_identity_validator_spec.rb | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/app/models/one_login/core_identity_validator.rb b/app/models/one_login/core_identity_validator.rb index 6adcae864c..4fbec78fbf 100644 --- a/app/models/one_login/core_identity_validator.rb +++ b/app/models/one_login/core_identity_validator.rb @@ -21,6 +21,10 @@ def date_of_birth Date.parse(decoded_jwt[0]["vc"]["credentialSubject"]["birthDate"][0]["value"]) end + def full_name + name_parts.map { |hash| hash["value"] }.join(" ") + end + private def name_parts diff --git a/spec/models/one_login/core_identity_validator_spec.rb b/spec/models/one_login/core_identity_validator_spec.rb index 189c3bd725..c6ba813db4 100644 --- a/spec/models/one_login/core_identity_validator_spec.rb +++ b/spec/models/one_login/core_identity_validator_spec.rb @@ -79,6 +79,20 @@ end end + describe "#full_name" do + before do + stub_normal_did + + travel_to(Time.at(1723548751)) do + subject.call + end + end + + it "returns whole name" do + expect(subject.full_name).to eql("KENNETH DECERQUEIRA") + end + end + let(:stub_normal_did) do return_headers = { "Cache-Control" => "max-age=3600, private" From 0bcadd3eeccab53876848ab2b88759d9e6fda098 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 5 Dec 2024 13:13:03 +0000 Subject: [PATCH 2/3] store full name from OL --- app/controllers/omniauth_callbacks_controller.rb | 7 +++++-- app/models/claim.rb | 7 ++----- app/models/journeys/session_answers.rb | 1 + config/analytics_blocklist.yml | 1 + .../20241205121421_add_ol_full_name_to_claims.rb | 15 +++++++++++++++ db/schema.rb | 3 ++- spec/factories/claims.rb | 1 + .../further_education_payments/happy_path_spec.rb | 1 + .../claim_submission_form_spec.rb | 3 +++ .../claim_verifiers/identity_spec.rb | 3 ++- spec/models/claim_spec.rb | 1 + .../omniauth_callbacks_controller_spec.rb | 1 + 12 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 db/migrate/20241205121421_add_ol_full_name_to_claims.rb diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index d9066c84d4..c61674cf22 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -92,13 +92,14 @@ def process_one_login_identity_verification_callback(core_identity_jwt) return redirect_to "/auth/failure?strategy=onelogin&message=access_denied&origin=#{origin}" end - first_name, last_name, date_of_birth = extract_data_from_jwt(core_identity_jwt) + first_name, last_name, full_name, date_of_birth = extract_data_from_jwt(core_identity_jwt) journey_session.answers.assign_attributes( identity_confirmed_with_onelogin: true, onelogin_idv_at: Time.now, onelogin_idv_first_name: first_name, onelogin_idv_last_name: last_name, + onelogin_idv_full_name: full_name, onelogin_idv_date_of_birth: date_of_birth ) journey_session.answers.first_name ||= first_name @@ -124,16 +125,18 @@ def extract_data_from_jwt(jwt) if OneLoginSignIn.bypass? first_name = ONE_LOGIN_TEST_USER[:first_name] last_name = ONE_LOGIN_TEST_USER[:last_name] + full_name = "#{first_name} #{last_name}" date_of_birth = ONE_LOGIN_TEST_USER[:date_of_birth] else validator = OneLogin::CoreIdentityValidator.new(jwt:) validator.call first_name = validator.first_name last_name = validator.last_name + full_name = validator.full_name date_of_birth = validator.date_of_birth end - [first_name, last_name, date_of_birth] + [first_name, last_name, full_name, date_of_birth] end def test_user_auth_hash diff --git a/app/models/claim.rb b/app/models/claim.rb index bb0491bc35..a5772505a2 100644 --- a/app/models/claim.rb +++ b/app/models/claim.rb @@ -93,7 +93,8 @@ class Claim < ApplicationRecord practitioner_email_address: true, provider_contact_name: true, started_at: false, - verified_at: false + verified_at: false, + onelogin_idv_full_name: true }.freeze DECISION_DEADLINE = 12.weeks DECISION_DEADLINE_WARNING_POINT = 2.weeks @@ -247,10 +248,6 @@ class Claim < ApplicationRecord by_policies(Policies.all.select { |p| p.require_in_progress_update_emails? }) } - def onelogin_idv_full_name - "#{onelogin_idv_first_name} #{onelogin_idv_last_name}" - end - def hold!(reason:, user:) if holdable? && !held? self.class.transaction do diff --git a/app/models/journeys/session_answers.rb b/app/models/journeys/session_answers.rb index c1d973c93d..c72d2d8ec5 100644 --- a/app/models/journeys/session_answers.rb +++ b/app/models/journeys/session_answers.rb @@ -44,6 +44,7 @@ class SessionAnswers attribute :onelogin_idv_first_name, :string attribute :onelogin_idv_last_name, :string + attribute :onelogin_idv_full_name, :string attribute :onelogin_idv_date_of_birth, :date attribute :onelogin_auth_at, :datetime diff --git a/config/analytics_blocklist.yml b/config/analytics_blocklist.yml index d05bf8bfb7..5651091c09 100644 --- a/config/analytics_blocklist.yml +++ b/config/analytics_blocklist.yml @@ -34,6 +34,7 @@ - onelogin_uid - onelogin_idv_first_name - onelogin_idv_last_name + - onelogin_idv_full_name - onelogin_idv_date_of_birth :claim_decisions: - trn diff --git a/db/migrate/20241205121421_add_ol_full_name_to_claims.rb b/db/migrate/20241205121421_add_ol_full_name_to_claims.rb new file mode 100644 index 0000000000..8b63414b2e --- /dev/null +++ b/db/migrate/20241205121421_add_ol_full_name_to_claims.rb @@ -0,0 +1,15 @@ +class AddOlFullNameToClaims < ActiveRecord::Migration[8.0] + def up + add_column :claims, :onelogin_idv_full_name, :text + + execute <<-SQL + UPDATE claims + SET onelogin_idv_full_name = CONCAT(claims.onelogin_idv_first_name, ' ', claims.onelogin_idv_last_name) + WHERE claims.onelogin_idv_full_name IS NULL + SQL + end + + def down + remove_column :claims, :onelogin_idv_full_name + end +end diff --git a/db/schema.rb b/db/schema.rb index ff5c7e9cb2..d82cd6d019 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[8.0].define(version: 2024_11_26_105650) do +ActiveRecord::Schema[8.0].define(version: 2024_12_05_121421) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "pg_catalog.plpgsql" @@ -113,6 +113,7 @@ t.date "onelogin_idv_date_of_birth" t.datetime "started_at", precision: nil, null: false t.datetime "verified_at" + t.text "onelogin_idv_full_name" t.index ["academic_year"], name: "index_claims_on_academic_year" t.index ["created_at"], name: "index_claims_on_created_at" t.index ["eligibility_type", "eligibility_id"], name: "index_claims_on_eligibility_type_and_eligibility_id" diff --git a/spec/factories/claims.rb b/spec/factories/claims.rb index 6a4cfc9fb7..4a42e660f2 100644 --- a/spec/factories/claims.rb +++ b/spec/factories/claims.rb @@ -57,6 +57,7 @@ onelogin_idv_at { (onelogin_auth_at + 1.hour) } onelogin_idv_first_name { first_name } onelogin_idv_last_name { surname } + onelogin_idv_full_name { [first_name, surname].join(" ") } onelogin_idv_date_of_birth { date_of_birth } end diff --git a/spec/features/further_education_payments/happy_path_spec.rb b/spec/features/further_education_payments/happy_path_spec.rb index 1bf2995557..3b74d01462 100644 --- a/spec/features/further_education_payments/happy_path_spec.rb +++ b/spec/features/further_education_payments/happy_path_spec.rb @@ -180,6 +180,7 @@ expect(claim.first_name).to eql("John") expect(claim.surname).to eql("Doe") + expect(claim.onelogin_idv_full_name).to eql("TEST USER") expect(claim.student_loan_plan).to eq "plan_1" eligibility = Policies::FurtherEducationPayments::Eligibility.last diff --git a/spec/forms/journeys/further_education_payments/claim_submission_form_spec.rb b/spec/forms/journeys/further_education_payments/claim_submission_form_spec.rb index bae162eeed..b1a3696647 100644 --- a/spec/forms/journeys/further_education_payments/claim_submission_form_spec.rb +++ b/spec/forms/journeys/further_education_payments/claim_submission_form_spec.rb @@ -18,6 +18,7 @@ logged_in_with_onelogin: true, onelogin_idv_first_name: "John", onelogin_idv_last_name: "Doe", + onelogin_idv_full_name: "John Doe", onelogin_idv_date_of_birth: Date.new(1970, 1, 1), first_name: "John", surname: "Doe", @@ -47,6 +48,7 @@ expect(claim.onelogin_idv_at).to eql(answers.onelogin_idv_at) expect(claim.onelogin_idv_first_name).to eql(answers.onelogin_idv_first_name) expect(claim.onelogin_idv_last_name).to eql(answers.onelogin_idv_last_name) + expect(claim.onelogin_idv_full_name).to eql(answers.onelogin_idv_full_name) expect(claim.onelogin_idv_date_of_birth).to eql(answers.onelogin_idv_date_of_birth) expect(eligibility.award_amount).to eq(answers.award_amount) @@ -141,6 +143,7 @@ logged_in_with_onelogin: true, onelogin_idv_first_name: "John", onelogin_idv_last_name: "Doe", + onelogin_idv_full_name: "John Doe", onelogin_idv_date_of_birth: Date.new(1970, 1, 1), first_name: "Jack", surname: "Doe", diff --git a/spec/models/automated_checks/claim_verifiers/identity_spec.rb b/spec/models/automated_checks/claim_verifiers/identity_spec.rb index 516be27b4a..3091cce2eb 100644 --- a/spec/models/automated_checks/claim_verifiers/identity_spec.rb +++ b/spec/models/automated_checks/claim_verifiers/identity_spec.rb @@ -90,7 +90,8 @@ module ClaimVerifiers first_name: "John", surname: "Doe", onelogin_idv_first_name: "Tom", - onelogin_idv_last_name: "Jones" + onelogin_idv_last_name: "Jones", + onelogin_idv_full_name: "Tom Jones" ) end diff --git a/spec/models/claim_spec.rb b/spec/models/claim_spec.rb index 1196df1bff..d50966b4cf 100644 --- a/spec/models/claim_spec.rb +++ b/spec/models/claim_spec.rb @@ -653,6 +653,7 @@ :onelogin_uid, :onelogin_idv_first_name, :onelogin_idv_last_name, + :onelogin_idv_full_name, :onelogin_idv_date_of_birth, :paye_reference, :practitioner_email_address, diff --git a/spec/requests/omniauth_callbacks_controller_spec.rb b/spec/requests/omniauth_callbacks_controller_spec.rb index a0d93d0a68..f00b541e30 100644 --- a/spec/requests/omniauth_callbacks_controller_spec.rb +++ b/spec/requests/omniauth_callbacks_controller_spec.rb @@ -226,6 +226,7 @@ def set_mock_auth(trn) call: nil, first_name: "John", last_name: "Doe", + full_name: "John Doe", date_of_birth: Date.new(1970, 12, 13) ) From 429c5b3123e3eda3756316399973b41d7d40c022 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 5 Dec 2024 13:47:18 +0000 Subject: [PATCH 3/3] OL name matches via regexp --- app/models/claim.rb | 11 ++++----- spec/models/claim_spec.rb | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/app/models/claim.rb b/app/models/claim.rb index a5772505a2..063a3da5b7 100644 --- a/app/models/claim.rb +++ b/app/models/claim.rb @@ -475,14 +475,14 @@ def same_claimant?(other_claim) end end - def one_login_idv_mismatch? - !one_login_idv_name_match? || !one_login_idv_dob_match? - end - def one_login_idv_match? one_login_idv_name_match? && one_login_idv_dob_match? end + def one_login_idv_mismatch? + !one_login_idv_match? + end + def awaiting_provider_verification? return false unless has_further_education_policy? @@ -500,7 +500,8 @@ def attributes_flagged_by_risk_indicator private def one_login_idv_name_match? - onelogin_idv_full_name.downcase == "#{first_name.downcase} #{surname.downcase}" + /\A#{first_name.strip.downcase} /.match?(onelogin_idv_full_name.strip.downcase) && + / #{surname.strip.downcase}\z/.match?(onelogin_idv_full_name.strip.downcase) end def one_login_idv_dob_match? diff --git a/spec/models/claim_spec.rb b/spec/models/claim_spec.rb index d50966b4cf..47a605654a 100644 --- a/spec/models/claim_spec.rb +++ b/spec/models/claim_spec.rb @@ -1478,4 +1478,51 @@ expect(policy).to have_received(:decision_deadline_date).with(claim) end end + + describe "#one_login_idv_match?" do + context "space in first name" do + before do + subject.onelogin_idv_full_name = "A B C" + subject.first_name = "A B" + subject.surname = "C" + + subject.onelogin_idv_date_of_birth = Date.today + subject.date_of_birth = Date.today + end + + it "matches" do + expect(subject).to be_one_login_idv_match + end + end + + context "close match" do + before do + subject.onelogin_idv_full_name = "A B C" + subject.first_name = "AA B" + subject.surname = "C" + + subject.onelogin_idv_date_of_birth = Date.today + subject.date_of_birth = Date.today + end + + it "does not match" do + expect(subject).not_to be_one_login_idv_match + end + end + + context "not a match" do + before do + subject.onelogin_idv_full_name = "A B" + subject.first_name = "Z" + subject.surname = "B" + + subject.onelogin_idv_date_of_birth = Date.today + subject.date_of_birth = Date.today + end + + it "does not match" do + expect(subject).not_to be_one_login_idv_match + end + end + end end