From 30dd34b4fd5433a2461da66d392b21397c6f6577 Mon Sep 17 00:00:00 2001 From: jey Date: Fri, 27 Dec 2024 12:01:54 -0800 Subject: [PATCH 01/42] i don't know why i had to do this --- app/models/intake.rb | 2 ++ app/models/intake/ctc_intake.rb | 2 ++ app/models/intake/gyr_intake.rb | 2 ++ spec/models/intake/gyr_intake_spec.rb | 2 ++ spec/models/intake_spec.rb | 2 ++ 5 files changed, 10 insertions(+) diff --git a/app/models/intake.rb b/app/models/intake.rb index 9263fea383..a43da723da 100644 --- a/app/models/intake.rb +++ b/app/models/intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # diff --git a/app/models/intake/ctc_intake.rb b/app/models/intake/ctc_intake.rb index dd8d7f07d8..6508bc0ea8 100644 --- a/app/models/intake/ctc_intake.rb +++ b/app/models/intake/ctc_intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::CtcIntake < Intake diff --git a/app/models/intake/gyr_intake.rb b/app/models/intake/gyr_intake.rb index a897d0084e..db753f432f 100644 --- a/app/models/intake/gyr_intake.rb +++ b/app/models/intake/gyr_intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::GyrIntake < Intake diff --git a/spec/models/intake/gyr_intake_spec.rb b/spec/models/intake/gyr_intake_spec.rb index ff99754925..861e555dba 100644 --- a/spec/models/intake/gyr_intake_spec.rb +++ b/spec/models/intake/gyr_intake_spec.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # require "rails_helper" diff --git a/spec/models/intake_spec.rb b/spec/models/intake_spec.rb index 7402905340..8cf0af8a39 100644 --- a/spec/models/intake_spec.rb +++ b/spec/models/intake_spec.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # From 2d1f3f1a77d536c5cbbbac5b8b2f4527808fe262 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 26 Dec 2024 16:17:31 -0800 Subject: [PATCH 02/42] can navigate to email address page --- ...mpleted_return_email_address_controller.rb | 6 +++ ...mpleted_return_email_address_controller.rb | 5 +++ .../completed_tax_return_navigation.rb | 12 ++++++ app/models/intake.rb | 2 + app/models/intake/ctc_intake.rb | 2 + app/models/intake/gyr_intake.rb | 2 + .../edit.html.erb | 3 ++ .../state_file_pages/about_page.html.erb | 9 ++++- config/locales/en.yml | 2 + config/locales/es.yml | 1 + config/routes.rb | 2 + ...dd_address_to_completed_2023_tax_return.rb | 39 +++++++++++++++++++ db/schema.rb | 6 ++- 13 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 app/controllers/state_file/questions/completed_return_email_address_controller.rb create mode 100644 app/forms/state_file/completed_return_email_address_controller.rb create mode 100644 app/lib/navigation/completed_tax_return_navigation.rb create mode 100644 app/views/state_file/questions/completed_return_email_address/edit.html.erb create mode 100644 db/data/20241226211010_add_address_to_completed_2023_tax_return.rb diff --git a/app/controllers/state_file/questions/completed_return_email_address_controller.rb b/app/controllers/state_file/questions/completed_return_email_address_controller.rb new file mode 100644 index 0000000000..5a00418e8c --- /dev/null +++ b/app/controllers/state_file/questions/completed_return_email_address_controller.rb @@ -0,0 +1,6 @@ +module StateFile + module Questions + class CompletedReturnEmailAddressController < QuestionsController + end + end +end \ No newline at end of file diff --git a/app/forms/state_file/completed_return_email_address_controller.rb b/app/forms/state_file/completed_return_email_address_controller.rb new file mode 100644 index 0000000000..58d31df079 --- /dev/null +++ b/app/forms/state_file/completed_return_email_address_controller.rb @@ -0,0 +1,5 @@ +module StateFile + class CompletedReturnEmailAddressForm < QuestionsForm + + end +end \ No newline at end of file diff --git a/app/lib/navigation/completed_tax_return_navigation.rb b/app/lib/navigation/completed_tax_return_navigation.rb new file mode 100644 index 0000000000..05bb57f4c8 --- /dev/null +++ b/app/lib/navigation/completed_tax_return_navigation.rb @@ -0,0 +1,12 @@ +module Navigation + class CompletedTaxReturnNavigation < Navigation::StateFileBaseQuestionNavigation + include ControllerNavigation + + SECTIONS = [ + Navigation::NavigationSection.new("state_file.navigation.section_1", [ + Navigation::NavigationStep.new(StateFile::Questions::CompletedReturnEmailAddressController), + ]), + ].freeze + FLOW = SECTIONS.map(&:controllers).flatten.freeze + end +end diff --git a/app/models/intake.rb b/app/models/intake.rb index 9263fea383..a43da723da 100644 --- a/app/models/intake.rb +++ b/app/models/intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # diff --git a/app/models/intake/ctc_intake.rb b/app/models/intake/ctc_intake.rb index dd8d7f07d8..6508bc0ea8 100644 --- a/app/models/intake/ctc_intake.rb +++ b/app/models/intake/ctc_intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::CtcIntake < Intake diff --git a/app/models/intake/gyr_intake.rb b/app/models/intake/gyr_intake.rb index a897d0084e..db753f432f 100644 --- a/app/models/intake/gyr_intake.rb +++ b/app/models/intake/gyr_intake.rb @@ -306,6 +306,8 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) +# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) +# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::GyrIntake < Intake diff --git a/app/views/state_file/questions/completed_return_email_address/edit.html.erb b/app/views/state_file/questions/completed_return_email_address/edit.html.erb new file mode 100644 index 0000000000..dfdfc7b303 --- /dev/null +++ b/app/views/state_file/questions/completed_return_email_address/edit.html.erb @@ -0,0 +1,3 @@ + +<% title = "butt" %> +<% content_for :page_title, title %> \ No newline at end of file diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index 7f60c9e235..eb1a6c10b0 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -42,4 +42,11 @@ <% end %> -<% end %> \ No newline at end of file +<% end %> + +
+ <%= t(".looking_for_return_html")%> +
+ <%= link_to t(".tax_return_link") %> +
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index f7b49ba628..964b737695 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3794,6 +3794,8 @@ en: We're closed for the tax season. Unfortunately you can no longer file your state return with us this year.

Already filed your state taxes with us? You can download a copy of your state return until December 31, 2024

header: A free state filing service for taxpayers using IRS Direct File + looking_for_return_html: Looking for your 2023 Arizona or New York State Tax Return? + tax_return_link: Click here to access your tax return section1_html: | How does it work?
    diff --git a/config/locales/es.yml b/config/locales/es.yml index 98c5145903..edc8ce7912 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -3768,6 +3768,7 @@ es: Estamos cerrados por la temporada de impuestos. Desafortunadamente, no puede presentar tu declaración estatal con nosotros este año.

    ¿Ya presentó tus impuestos estatales con nosotros? Puedes descargar una copia de tu declaración estatal hasta el 31 de diciembre de 2024

    header: Una herramienta sin costo para presentar impuestos estatales para los contribuyentes utilizando IRS Direct File + looking_for_return_html: ¿Está buscando su declaración de impuestos del estado de Arizona o Nueva York de 2023? section1_html: | ¿Cómo funciona?
      diff --git a/config/routes.rb b/config/routes.rb index 6d167bb0ce..db2d21897b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -592,6 +592,8 @@ def scoped_navigation_routes(context, navigation) navigation_class = StateFile::StateInformationService.navigation_class(code) scoped_navigation_routes(:questions, navigation_class) end + scoped_navigation_routes(:questions, Navigation::CompletedTaxReturnNavigation) + match("/code-verified", action: :edit, controller: "state_file/questions/code_verified", via: :get) match("/code-verified", action: :update, controller: "state_file/questions/code_verified", via: :put) diff --git a/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb b/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb new file mode 100644 index 0000000000..dc4e05e3e5 --- /dev/null +++ b/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +class AddAddressToCompleted2023TaxReturn < ActiveRecord::Migration[7.1] + def up + puts "Migrating Arizona details" + StateFileAzIntake.all.each do |intake| + completed_return = Completed2023TaxReturn.new + completed_return.mailing_street = intake.direct_file_data.mailing_street + completed_return.mailing_apartment = intake.direct_file_data.mailing_apartment + completed_return.mailing_city = intake.direct_file_data.mailing_city + completed_return.mailing_state = intake.direct_file_data.mailing_state + completed_return.mailing_zip = intake.direct_file_data.mailing_zip + completed_return.email_address = intake.email_address + completed_return.state_code = 'az' + completed_return.hashed_ssn = intake.hashed_ssn + completed_return_pdf = Completed2023TaxReturnPdf.new + + end + + puts "Migrating New York details" + StateFileNyIntake.all.each do |intake| + completed_return = Completed2023TaxReturn.new + completed_return.mailing_street = intake.direct_file_data.mailing_street + completed_return.mailing_apartment = intake.direct_file_data.mailing_apartment + completed_return.mailing_city = intake.direct_file_data.mailing_city + completed_return.mailing_state = intake.direct_file_data.mailing_state + completed_return.mailing_zip = intake.direct_file_data.mailing_zip + completed_return.email_address = intake.email_address + completed_return.state_code = 'ny' + completed_return.hashed_ssn = intake.hashed_ssn + completed_return_pdf = Completed2023TaxReturnPdf.new + + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index 2a6edf3bd3..5a05161530 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_12_20_195915) do +ActiveRecord::Schema[7.1].define(version: 2024_12_26_203341) do + create_schema "analytics" + # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" @@ -2775,6 +2777,8 @@ add_foreign_key "incoming_text_messages", "clients" add_foreign_key "intake_archives", "intakes", column: "id" add_foreign_key "intakes", "clients" + add_foreign_key "intakes", "drivers_licenses", column: "primary_drivers_license_id" + add_foreign_key "intakes", "drivers_licenses", column: "spouse_drivers_license_id" add_foreign_key "intakes", "intakes", column: "matching_previous_year_intake_id" add_foreign_key "intakes", "vita_partners" add_foreign_key "notes", "clients" From 36a8be464e59ccc4e719333a1e70d2aaad4a5e4c Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 27 Dec 2024 12:41:04 -0800 Subject: [PATCH 03/42] rename files and add link --- .../questions/archived_intake_email_address_controller.rb | 6 ++++++ .../questions/completed_return_email_address_controller.rb | 6 ------ ...x_return_navigation.rb => archived_intake_navigation.rb} | 4 ++-- .../edit.html.erb | 2 +- app/views/state_file/state_file_pages/about_page.html.erb | 2 +- config/routes.rb | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 app/controllers/state_file/questions/archived_intake_email_address_controller.rb delete mode 100644 app/controllers/state_file/questions/completed_return_email_address_controller.rb rename app/lib/navigation/{completed_tax_return_navigation.rb => archived_intake_navigation.rb} (55%) rename app/views/state_file/questions/{completed_return_email_address => archived_intake_email_address}/edit.html.erb (62%) diff --git a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb new file mode 100644 index 0000000000..7d9bb14716 --- /dev/null +++ b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb @@ -0,0 +1,6 @@ +module StateFile + module Questions + class ArchivedIntakeEmailAddressController < QuestionsController + end + end +end \ No newline at end of file diff --git a/app/controllers/state_file/questions/completed_return_email_address_controller.rb b/app/controllers/state_file/questions/completed_return_email_address_controller.rb deleted file mode 100644 index 5a00418e8c..0000000000 --- a/app/controllers/state_file/questions/completed_return_email_address_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -module StateFile - module Questions - class CompletedReturnEmailAddressController < QuestionsController - end - end -end \ No newline at end of file diff --git a/app/lib/navigation/completed_tax_return_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb similarity index 55% rename from app/lib/navigation/completed_tax_return_navigation.rb rename to app/lib/navigation/archived_intake_navigation.rb index 05bb57f4c8..5110fd5b2d 100644 --- a/app/lib/navigation/completed_tax_return_navigation.rb +++ b/app/lib/navigation/archived_intake_navigation.rb @@ -1,10 +1,10 @@ module Navigation - class CompletedTaxReturnNavigation < Navigation::StateFileBaseQuestionNavigation + class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation include ControllerNavigation SECTIONS = [ Navigation::NavigationSection.new("state_file.navigation.section_1", [ - Navigation::NavigationStep.new(StateFile::Questions::CompletedReturnEmailAddressController), + Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeEmailAddressController), ]), ].freeze FLOW = SECTIONS.map(&:controllers).flatten.freeze diff --git a/app/views/state_file/questions/completed_return_email_address/edit.html.erb b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb similarity index 62% rename from app/views/state_file/questions/completed_return_email_address/edit.html.erb rename to app/views/state_file/questions/archived_intake_email_address/edit.html.erb index dfdfc7b303..646d7bc1c3 100644 --- a/app/views/state_file/questions/completed_return_email_address/edit.html.erb +++ b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb @@ -1,3 +1,3 @@ -<% title = "butt" %> +<% title = "email" %> <% content_for :page_title, title %> \ No newline at end of file diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index eb1a6c10b0..3d69de844e 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -47,6 +47,6 @@
      <%= t(".looking_for_return_html")%>
      - <%= link_to t(".tax_return_link") %> + <%= link_to t(".tax_return_link"), questions_archived_intake_email_address_path %>
      diff --git a/config/routes.rb b/config/routes.rb index db2d21897b..215cf9abc0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -592,7 +592,7 @@ def scoped_navigation_routes(context, navigation) navigation_class = StateFile::StateInformationService.navigation_class(code) scoped_navigation_routes(:questions, navigation_class) end - scoped_navigation_routes(:questions, Navigation::CompletedTaxReturnNavigation) + scoped_navigation_routes(:questions, Navigation::ArchivedIntakeNavigation) match("/code-verified", action: :edit, controller: "state_file/questions/code_verified", via: :get) From eb43c45b1f8bd94b4551b7c13bfb7ee1a0ac62dc Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 27 Dec 2024 12:51:04 -0800 Subject: [PATCH 04/42] delete unused controller --- .../state_file/completed_return_email_address_controller.rb | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 app/forms/state_file/completed_return_email_address_controller.rb diff --git a/app/forms/state_file/completed_return_email_address_controller.rb b/app/forms/state_file/completed_return_email_address_controller.rb deleted file mode 100644 index 58d31df079..0000000000 --- a/app/forms/state_file/completed_return_email_address_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -module StateFile - class CompletedReturnEmailAddressForm < QuestionsForm - - end -end \ No newline at end of file From ca185358d0866222f84068ef230b2f0558c7f8c7 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 27 Dec 2024 12:56:50 -0800 Subject: [PATCH 05/42] remove unused data migration --- ...dd_address_to_completed_2023_tax_return.rb | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 db/data/20241226211010_add_address_to_completed_2023_tax_return.rb diff --git a/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb b/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb deleted file mode 100644 index dc4e05e3e5..0000000000 --- a/db/data/20241226211010_add_address_to_completed_2023_tax_return.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -class AddAddressToCompleted2023TaxReturn < ActiveRecord::Migration[7.1] - def up - puts "Migrating Arizona details" - StateFileAzIntake.all.each do |intake| - completed_return = Completed2023TaxReturn.new - completed_return.mailing_street = intake.direct_file_data.mailing_street - completed_return.mailing_apartment = intake.direct_file_data.mailing_apartment - completed_return.mailing_city = intake.direct_file_data.mailing_city - completed_return.mailing_state = intake.direct_file_data.mailing_state - completed_return.mailing_zip = intake.direct_file_data.mailing_zip - completed_return.email_address = intake.email_address - completed_return.state_code = 'az' - completed_return.hashed_ssn = intake.hashed_ssn - completed_return_pdf = Completed2023TaxReturnPdf.new - - end - - puts "Migrating New York details" - StateFileNyIntake.all.each do |intake| - completed_return = Completed2023TaxReturn.new - completed_return.mailing_street = intake.direct_file_data.mailing_street - completed_return.mailing_apartment = intake.direct_file_data.mailing_apartment - completed_return.mailing_city = intake.direct_file_data.mailing_city - completed_return.mailing_state = intake.direct_file_data.mailing_state - completed_return.mailing_zip = intake.direct_file_data.mailing_zip - completed_return.email_address = intake.email_address - completed_return.state_code = 'ny' - completed_return.hashed_ssn = intake.hashed_ssn - completed_return_pdf = Completed2023TaxReturnPdf.new - - end - end - - def down - raise ActiveRecord::IrreversibleMigration - end -end From a8ad9dbcb6ba1d72233ff80b67d2075541a832f3 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 27 Dec 2024 13:21:27 -0800 Subject: [PATCH 06/42] i18n health --- config/locales/en.yml | 4 ++-- config/locales/es.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 964b737695..ae783596fe 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3794,8 +3794,7 @@ en: We're closed for the tax season. Unfortunately you can no longer file your state return with us this year.

      Already filed your state taxes with us? You can download a copy of your state return until December 31, 2024

      header: A free state filing service for taxpayers using IRS Direct File - looking_for_return_html: Looking for your 2023 Arizona or New York State Tax Return? - tax_return_link: Click here to access your tax return + looking_for_return_html: "Looking for your 2023 Arizona or New York State Tax Return?" section1_html: | How does it work?
        @@ -3810,6 +3809,7 @@ en: subheader_1_html: "FileYourStateTaxes integrates with IRS Direct File to help you complete your state tax return for free." subheader_2_html: IRS Direct File is now broadly available to all eligible taxpayers through April 15, 2024. For more information on timeline and eligibility, or to start filing your federal return, go to directfile.irs.gov subheader_3_html: Already filed your federal return with IRS Direct File and need to complete your state return? Sign in here. + tax_return_link: Click here to access your tax return card_postscript: responses_saved_html: Your responses are saved. If you need a break, you can come back and log in to your account at fileyourstatetaxes.org. coming_soon: diff --git a/config/locales/es.yml b/config/locales/es.yml index edc8ce7912..df5a9fb31b 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -3768,7 +3768,7 @@ es: Estamos cerrados por la temporada de impuestos. Desafortunadamente, no puede presentar tu declaración estatal con nosotros este año.

        ¿Ya presentó tus impuestos estatales con nosotros? Puedes descargar una copia de tu declaración estatal hasta el 31 de diciembre de 2024

        header: Una herramienta sin costo para presentar impuestos estatales para los contribuyentes utilizando IRS Direct File - looking_for_return_html: ¿Está buscando su declaración de impuestos del estado de Arizona o Nueva York de 2023? + looking_for_return_html: "¿Está buscando su declaración de impuestos del estado de Arizona o Nueva York de 2023?" section1_html: | ¿Cómo funciona?
          @@ -3783,6 +3783,7 @@ es: subheader_1_html: "FileYourStateTaxes se integra con IRS Direct File para ayudarte a completar tu declaración de impuestos estatales sin costo." subheader_2_html: El IRS Direct File ahora está ampliamente disponible para todos los contribuyentes elegibles hasta el 15 de abril de 2024. Para obtener más información sobre el cronograma y la elegibilidad, o para comenzar a presentar tu declaración federal, ve a directfile.irs.gov. subheader_3_html: "¿Ya presentaste tu declaración federal con IRS Direct File y necesitas completar tu declaración estatal? Inicia sesión aquí." + tax_return_link: Haga clic aquí para acceder a su declaración de impuestos. card_postscript: responses_saved_html: Tus respuestas han sido guardadas. Si necesitas hacer una pausa, puedes regresar e iniciar sesión en tu cuenta en fileyourstatetaxes.org. coming_soon: From 1cfc369799390ec56d4bf975245ca9f2cee0d77d Mon Sep 17 00:00:00 2001 From: jey Date: Fri, 27 Dec 2024 13:43:37 -0800 Subject: [PATCH 07/42] intake archiving (models and migrations) (#5299) --- app/models/state_file_archived_intake.rb | 21 ++++++++++ .../state_file_archived_intake_access_log.rb | 39 +++++++++++++++++++ ...3827_create_state_file_archived_intakes.rb | 16 ++++++++ ..._state_file_archived_intake_access_logs.rb | 11 ++++++ db/schema.rb | 29 +++++++++++++- .../state_file_archived_intake_access_logs.rb | 25 ++++++++++++ spec/factories/state_file_archived_intakes.rb | 22 +++++++++++ ...te_file_archived_intake_access_log_spec.rb | 25 ++++++++++++ .../models/state_file_archived_intake_spec.rb | 22 +++++++++++ 9 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 app/models/state_file_archived_intake.rb create mode 100644 app/models/state_file_archived_intake_access_log.rb create mode 100644 db/migrate/20241227173827_create_state_file_archived_intakes.rb create mode 100644 db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb create mode 100644 spec/factories/state_file_archived_intake_access_logs.rb create mode 100644 spec/factories/state_file_archived_intakes.rb create mode 100644 spec/models/state_file_archived_intake_access_log_spec.rb create mode 100644 spec/models/state_file_archived_intake_spec.rb diff --git a/app/models/state_file_archived_intake.rb b/app/models/state_file_archived_intake.rb new file mode 100644 index 0000000000..e5c464a926 --- /dev/null +++ b/app/models/state_file_archived_intake.rb @@ -0,0 +1,21 @@ +# == Schema Information +# +# Table name: state_file_archived_intakes +# +# id :bigint not null, primary key +# email_address :string +# hashed_ssn :string +# mailing_apartment :string +# mailing_city :string +# mailing_state :string +# mailing_street :string +# mailing_zip :string +# state_code :string +# tax_year :integer +# created_at :datetime not null +# updated_at :datetime not null +# +class StateFileArchivedIntake < ApplicationRecord + has_one_attached :submission_pdf + has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' +end diff --git a/app/models/state_file_archived_intake_access_log.rb b/app/models/state_file_archived_intake_access_log.rb new file mode 100644 index 0000000000..4968350060 --- /dev/null +++ b/app/models/state_file_archived_intake_access_log.rb @@ -0,0 +1,39 @@ +# == Schema Information +# +# Table name: state_file_archived_intake_access_logs +# +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intakes_id :bigint +# +# Indexes +# +# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# +# Foreign Keys +# +# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# +class StateFileArchivedIntakeAccessLog < ApplicationRecord + belongs_to :state_file_archived_intake + enum event_type: { + issued_email_challenge: 0, + correct_email_code: 1, + incorrect_email_code: 2, + issued_ssn_challenge: 3, + correct_ssn_challenge: 4, + incorrect_ssn_challenge: 5, + client_lockout_begin: 6, + client_lockout_end: 7, + issued_mailing_address_challenge: 8, + correct_mailing_address: 9, + incorrect_mailing_address: 10, + issued_pdf_download_link: 11, + client_pdf_download_click: 12, + pdf_download_link_expired: 13, + }, _prefix: :event_type +end diff --git a/db/migrate/20241227173827_create_state_file_archived_intakes.rb b/db/migrate/20241227173827_create_state_file_archived_intakes.rb new file mode 100644 index 0000000000..76f6e40f30 --- /dev/null +++ b/db/migrate/20241227173827_create_state_file_archived_intakes.rb @@ -0,0 +1,16 @@ +class CreateStateFileArchivedIntakes < ActiveRecord::Migration[7.1] + def change + create_table :state_file_archived_intakes do |t| + t.integer 'tax_year' + t.string 'state_code' + t.string 'hashed_ssn' + t.string 'email_address' + t.string 'mailing_street' + t.string 'mailing_apartment' + t.string 'mailing_city' + t.string 'mailing_state' + t.string 'mailing_zip' + t.timestamps + end + end +end diff --git a/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb b/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb new file mode 100644 index 0000000000..0462ef3a36 --- /dev/null +++ b/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb @@ -0,0 +1,11 @@ +class CreateStateFileArchivedIntakeAccessLogs < ActiveRecord::Migration[7.1] + def change + create_table :state_file_archived_intake_access_logs do |t| + t.belongs_to 'state_file_archived_intakes', foreign_key: true + t.integer 'event_type' + t.string 'ip_address' + t.jsonb 'details', default: '{}' + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 2a6edf3bd3..1c9223ab24 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_12_20_195915) do +ActiveRecord::Schema[7.1].define(version: 2024_12_27_174414) do + create_schema "analytics" + # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" @@ -1683,6 +1685,30 @@ t.index ["record_type", "record_id"], name: "index_state_file_analytics_on_record" end + create_table "state_file_archived_intake_access_logs", force: :cascade do |t| + t.datetime "created_at", null: false + t.jsonb "details", default: "{}" + t.integer "event_type" + t.string "ip_address" + t.bigint "state_file_archived_intakes_id" + t.datetime "updated_at", null: false + t.index ["state_file_archived_intakes_id"], name: "idx_on_state_file_archived_intakes_id_e878049c06" + end + + create_table "state_file_archived_intakes", force: :cascade do |t| + t.datetime "created_at", null: false + t.string "email_address" + t.string "hashed_ssn" + t.string "mailing_apartment" + t.string "mailing_city" + t.string "mailing_state" + t.string "mailing_street" + t.string "mailing_zip" + t.string "state_code" + t.integer "tax_year" + t.datetime "updated_at", null: false + end + create_table "state_file_az1099_r_followups", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -2789,6 +2815,7 @@ add_foreign_key "site_coordinator_roles_vita_partners", "site_coordinator_roles" add_foreign_key "site_coordinator_roles_vita_partners", "vita_partners" add_foreign_key "source_parameters", "vita_partners" + add_foreign_key "state_file_archived_intake_access_logs", "state_file_archived_intakes", column: "state_file_archived_intakes_id" add_foreign_key "state_routing_fractions", "state_routing_targets" add_foreign_key "state_routing_fractions", "vita_partners" add_foreign_key "system_notes", "clients" diff --git a/spec/factories/state_file_archived_intake_access_logs.rb b/spec/factories/state_file_archived_intake_access_logs.rb new file mode 100644 index 0000000000..38637da7b9 --- /dev/null +++ b/spec/factories/state_file_archived_intake_access_logs.rb @@ -0,0 +1,25 @@ +# == Schema Information +# +# Table name: state_file_archived_intake_access_logs +# +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intakes_id :bigint +# +# Indexes +# +# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# +# Foreign Keys +# +# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# +FactoryBot.define do + factory :state_file_archived_intake_access_log do + + end +end diff --git a/spec/factories/state_file_archived_intakes.rb b/spec/factories/state_file_archived_intakes.rb new file mode 100644 index 0000000000..0f68fb4bac --- /dev/null +++ b/spec/factories/state_file_archived_intakes.rb @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: state_file_archived_intakes +# +# id :bigint not null, primary key +# email_address :string +# hashed_ssn :string +# mailing_apartment :string +# mailing_city :string +# mailing_state :string +# mailing_street :string +# mailing_zip :string +# state_code :string +# tax_year :integer +# created_at :datetime not null +# updated_at :datetime not null +# +FactoryBot.define do + factory :state_file_archived_intake do + submission_pdf { nil } + end +end diff --git a/spec/models/state_file_archived_intake_access_log_spec.rb b/spec/models/state_file_archived_intake_access_log_spec.rb new file mode 100644 index 0000000000..0c8b0e1989 --- /dev/null +++ b/spec/models/state_file_archived_intake_access_log_spec.rb @@ -0,0 +1,25 @@ +# == Schema Information +# +# Table name: state_file_archived_intake_access_logs +# +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intakes_id :bigint +# +# Indexes +# +# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# +# Foreign Keys +# +# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# +require 'rails_helper' + +RSpec.describe StateFileArchivedIntakeAccessLog, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/state_file_archived_intake_spec.rb b/spec/models/state_file_archived_intake_spec.rb new file mode 100644 index 0000000000..9b8e946311 --- /dev/null +++ b/spec/models/state_file_archived_intake_spec.rb @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: state_file_archived_intakes +# +# id :bigint not null, primary key +# email_address :string +# hashed_ssn :string +# mailing_apartment :string +# mailing_city :string +# mailing_state :string +# mailing_street :string +# mailing_zip :string +# state_code :string +# tax_year :integer +# created_at :datetime not null +# updated_at :datetime not null +# +require 'rails_helper' + +RSpec.describe StateFileArchivedIntake, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 5b22894d74f5bf99a7217b14f4f00e1f828de3e1 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 27 Dec 2024 16:00:52 -0800 Subject: [PATCH 08/42] wip --- .../archived_intake_email_address_controller.rb | 6 ------ .../email_address_validation_controller.rb | 15 +++++++++++++++ .../state_file/email_address_validation_form.rb | 8 ++++++++ app/lib/navigation/archived_intake_navigation.rb | 2 +- .../email_address_validation/edit.html.erb | 0 5 files changed, 24 insertions(+), 7 deletions(-) delete mode 100644 app/controllers/state_file/questions/archived_intake_email_address_controller.rb create mode 100644 app/controllers/state_file/questions/email_address_validation_controller.rb create mode 100644 app/forms/state_file/email_address_validation_form.rb create mode 100644 app/views/state_file/questions/email_address_validation/edit.html.erb diff --git a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb deleted file mode 100644 index 7d9bb14716..0000000000 --- a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -module StateFile - module Questions - class ArchivedIntakeEmailAddressController < QuestionsController - end - end -end \ No newline at end of file diff --git a/app/controllers/state_file/questions/email_address_validation_controller.rb b/app/controllers/state_file/questions/email_address_validation_controller.rb new file mode 100644 index 0000000000..e7ed662d4d --- /dev/null +++ b/app/controllers/state_file/questions/email_address_validation_controller.rb @@ -0,0 +1,15 @@ +module StateFile + module Questions + class EmailAddressValidationController < QuestionsController + def edit + super + State_file_archived_intake_access_logs.create( + event_type: "submission", + ip_address: ip_for_irs, + intake: current_intake, + ) + end + + end + end +end \ No newline at end of file diff --git a/app/forms/state_file/email_address_validation_form.rb b/app/forms/state_file/email_address_validation_form.rb new file mode 100644 index 0000000000..189a427e5c --- /dev/null +++ b/app/forms/state_file/email_address_validation_form.rb @@ -0,0 +1,8 @@ +module StateFile + class EmailAddressValidationForm < QuestionsForm + set_attributes_for :state_file_archived_intake_access_logs, :ip_address, :event_type, :updated_at + def save + @intake.update(attributes_for(:state_file_archived_intake_access_logs)) + end + end +end \ No newline at end of file diff --git a/app/lib/navigation/archived_intake_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb index 5110fd5b2d..6a0e78f3d7 100644 --- a/app/lib/navigation/archived_intake_navigation.rb +++ b/app/lib/navigation/archived_intake_navigation.rb @@ -4,7 +4,7 @@ class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation SECTIONS = [ Navigation::NavigationSection.new("state_file.navigation.section_1", [ - Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeEmailAddressController), + Navigation::NavigationStep.new(StateFile::Questions::EmailAddressValidationController) ]), ].freeze FLOW = SECTIONS.map(&:controllers).flatten.freeze diff --git a/app/views/state_file/questions/email_address_validation/edit.html.erb b/app/views/state_file/questions/email_address_validation/edit.html.erb new file mode 100644 index 0000000000..e69de29bb2 From a0969e39045f8e650448caaa889951743b589f73 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 30 Dec 2024 07:00:07 -0800 Subject: [PATCH 09/42] wip --- .../state_file_pages/about_page.html.erb | 2 +- db/schema.rb | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index 3d69de844e..c31848e2b1 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -47,6 +47,6 @@
          <%= t(".looking_for_return_html")%>
          - <%= link_to t(".tax_return_link"), questions_archived_intake_email_address_path %> + <%= link_to t(".tax_return_link"), questions_email_address_validation_path %>
          diff --git a/db/schema.rb b/db/schema.rb index 0ad8c85c52..405178f245 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -647,6 +647,33 @@ t.index ["name"], name: "index_coalitions_on_name", unique: true end + create_table "completed_2023_tax_return_logs", force: :cascade do |t| + t.bigint "completed_2023_tax_return_id" + t.datetime "created_at", null: false + t.integer "event_type", null: false + t.inet "ip_address" + t.datetime "updated_at", null: false + t.index ["completed_2023_tax_return_id"], name: "idx_on_completed_2023_tax_return_id_81ce7025c0" + end + + create_table "completed_2023_tax_return_pdfs", force: :cascade do |t| + t.bigint "completed_2023_tax_return_id", null: false + t.index ["completed_2023_tax_return_id"], name: "idx_on_completed_2023_tax_return_id_b19af583f0" + end + + create_table "completed_2023_tax_returns", force: :cascade do |t| + t.datetime "created_at", null: false + t.citext "email_address" + t.string "hashed_ssn" + t.string "mailing_apartment" + t.string "mailing_city" + t.string "mailing_state" + t.string "mailing_street" + t.string "mailing_zip" + t.string "state_code" + t.datetime "updated_at", null: false + end + create_table "consents", force: :cascade do |t| t.bigint "client_id", null: false t.datetime "created_at", null: false @@ -2781,6 +2808,8 @@ add_foreign_key "bulk_tax_return_updates", "users", column: "assigned_user_id" add_foreign_key "clients", "vita_partners" add_foreign_key "coalition_lead_roles", "coalitions" + add_foreign_key "completed_2023_tax_return_logs", "completed_2023_tax_returns" + add_foreign_key "completed_2023_tax_return_pdfs", "completed_2023_tax_returns" add_foreign_key "dependents", "intakes" add_foreign_key "documents", "clients" add_foreign_key "documents", "documents_requests" From f1e52460811cd58d532f62941348653b68e397c3 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 30 Dec 2024 15:26:16 -0800 Subject: [PATCH 10/42] Fyst 1515 add prior year access link button to homepage (#5296) Co-authored-by: Drew Proebstel --- .../archived_intake_email_address_controller.rb | 6 ++++++ app/lib/navigation/archived_intake_navigation.rb | 12 ++++++++++++ .../archived_intake_email_address/edit.html.erb | 3 +++ .../state_file/state_file_pages/about_page.html.erb | 9 ++++++++- config/locales/en.yml | 2 ++ config/locales/es.yml | 2 ++ config/routes.rb | 2 ++ db/schema.rb | 2 ++ 8 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 app/controllers/state_file/questions/archived_intake_email_address_controller.rb create mode 100644 app/lib/navigation/archived_intake_navigation.rb create mode 100644 app/views/state_file/questions/archived_intake_email_address/edit.html.erb diff --git a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb new file mode 100644 index 0000000000..7d9bb14716 --- /dev/null +++ b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb @@ -0,0 +1,6 @@ +module StateFile + module Questions + class ArchivedIntakeEmailAddressController < QuestionsController + end + end +end \ No newline at end of file diff --git a/app/lib/navigation/archived_intake_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb new file mode 100644 index 0000000000..5110fd5b2d --- /dev/null +++ b/app/lib/navigation/archived_intake_navigation.rb @@ -0,0 +1,12 @@ +module Navigation + class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation + include ControllerNavigation + + SECTIONS = [ + Navigation::NavigationSection.new("state_file.navigation.section_1", [ + Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeEmailAddressController), + ]), + ].freeze + FLOW = SECTIONS.map(&:controllers).flatten.freeze + end +end diff --git a/app/views/state_file/questions/archived_intake_email_address/edit.html.erb b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb new file mode 100644 index 0000000000..646d7bc1c3 --- /dev/null +++ b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb @@ -0,0 +1,3 @@ + +<% title = "email" %> +<% content_for :page_title, title %> \ No newline at end of file diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index 7f60c9e235..3d69de844e 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -42,4 +42,11 @@ <% end %> -<% end %> \ No newline at end of file +<% end %> + +
          + <%= t(".looking_for_return_html")%> +
          + <%= link_to t(".tax_return_link"), questions_archived_intake_email_address_path %> +
          +
          diff --git a/config/locales/en.yml b/config/locales/en.yml index f7b49ba628..ae783596fe 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3794,6 +3794,7 @@ en: We're closed for the tax season. Unfortunately you can no longer file your state return with us this year.

          Already filed your state taxes with us? You can download a copy of your state return until December 31, 2024

          header: A free state filing service for taxpayers using IRS Direct File + looking_for_return_html: "Looking for your 2023 Arizona or New York State Tax Return?" section1_html: | How does it work?
            @@ -3808,6 +3809,7 @@ en: subheader_1_html: "FileYourStateTaxes integrates with IRS Direct File to help you complete your state tax return for free." subheader_2_html: IRS Direct File is now broadly available to all eligible taxpayers through April 15, 2024. For more information on timeline and eligibility, or to start filing your federal return, go to directfile.irs.gov subheader_3_html: Already filed your federal return with IRS Direct File and need to complete your state return? Sign in here. + tax_return_link: Click here to access your tax return card_postscript: responses_saved_html: Your responses are saved. If you need a break, you can come back and log in to your account at fileyourstatetaxes.org. coming_soon: diff --git a/config/locales/es.yml b/config/locales/es.yml index 98c5145903..df5a9fb31b 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -3768,6 +3768,7 @@ es: Estamos cerrados por la temporada de impuestos. Desafortunadamente, no puede presentar tu declaración estatal con nosotros este año.

            ¿Ya presentó tus impuestos estatales con nosotros? Puedes descargar una copia de tu declaración estatal hasta el 31 de diciembre de 2024

            header: Una herramienta sin costo para presentar impuestos estatales para los contribuyentes utilizando IRS Direct File + looking_for_return_html: "¿Está buscando su declaración de impuestos del estado de Arizona o Nueva York de 2023?" section1_html: | ¿Cómo funciona?
              @@ -3782,6 +3783,7 @@ es: subheader_1_html: "FileYourStateTaxes se integra con IRS Direct File para ayudarte a completar tu declaración de impuestos estatales sin costo." subheader_2_html: El IRS Direct File ahora está ampliamente disponible para todos los contribuyentes elegibles hasta el 15 de abril de 2024. Para obtener más información sobre el cronograma y la elegibilidad, o para comenzar a presentar tu declaración federal, ve a directfile.irs.gov. subheader_3_html: "¿Ya presentaste tu declaración federal con IRS Direct File y necesitas completar tu declaración estatal? Inicia sesión aquí." + tax_return_link: Haga clic aquí para acceder a su declaración de impuestos. card_postscript: responses_saved_html: Tus respuestas han sido guardadas. Si necesitas hacer una pausa, puedes regresar e iniciar sesión en tu cuenta en fileyourstatetaxes.org. coming_soon: diff --git a/config/routes.rb b/config/routes.rb index 6d167bb0ce..215cf9abc0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -592,6 +592,8 @@ def scoped_navigation_routes(context, navigation) navigation_class = StateFile::StateInformationService.navigation_class(code) scoped_navigation_routes(:questions, navigation_class) end + scoped_navigation_routes(:questions, Navigation::ArchivedIntakeNavigation) + match("/code-verified", action: :edit, controller: "state_file/questions/code_verified", via: :get) match("/code-verified", action: :update, controller: "state_file/questions/code_verified", via: :put) diff --git a/db/schema.rb b/db/schema.rb index 1c9223ab24..0ad8c85c52 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2801,6 +2801,8 @@ add_foreign_key "incoming_text_messages", "clients" add_foreign_key "intake_archives", "intakes", column: "id" add_foreign_key "intakes", "clients" + add_foreign_key "intakes", "drivers_licenses", column: "primary_drivers_license_id" + add_foreign_key "intakes", "drivers_licenses", column: "spouse_drivers_license_id" add_foreign_key "intakes", "intakes", column: "matching_previous_year_intake_id" add_foreign_key "intakes", "vita_partners" add_foreign_key "notes", "clients" From 234b1e303c7d7f0b9b2e5e345bc6d9e876b95662 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 2 Jan 2025 11:07:23 -0800 Subject: [PATCH 11/42] wip --- .../email_address_validation_controller.rb | 10 +++++----- .../state_file/email_address_validation_form.rb | 8 +++++++- .../email_address_validation/edit.html.erb | 14 ++++++++++++++ config/locales/en.yml | 3 +++ 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/app/controllers/state_file/questions/email_address_validation_controller.rb b/app/controllers/state_file/questions/email_address_validation_controller.rb index e7ed662d4d..4c37df80bc 100644 --- a/app/controllers/state_file/questions/email_address_validation_controller.rb +++ b/app/controllers/state_file/questions/email_address_validation_controller.rb @@ -3,11 +3,11 @@ module Questions class EmailAddressValidationController < QuestionsController def edit super - State_file_archived_intake_access_logs.create( - event_type: "submission", - ip_address: ip_for_irs, - intake: current_intake, - ) + # ::StateFileArchivedIntakeAccessLog.create( + # event_type: "submission", + # ip_address: ip_for_irs, + # intake: current_intake, + # ) end end diff --git a/app/forms/state_file/email_address_validation_form.rb b/app/forms/state_file/email_address_validation_form.rb index 189a427e5c..d0d3bf3cc7 100644 --- a/app/forms/state_file/email_address_validation_form.rb +++ b/app/forms/state_file/email_address_validation_form.rb @@ -1,8 +1,14 @@ module StateFile class EmailAddressValidationForm < QuestionsForm - set_attributes_for :state_file_archived_intake_access_logs, :ip_address, :event_type, :updated_at + set_attributes_for :state_file_archived_intake, :email_address + validates :email_address, 'valid_email_2/email': true + validates :email_address, presence: true + validates :email_address_attached_to_an_intake + def save @intake.update(attributes_for(:state_file_archived_intake_access_logs)) end + + end end \ No newline at end of file diff --git a/app/views/state_file/questions/email_address_validation/edit.html.erb b/app/views/state_file/questions/email_address_validation/edit.html.erb index e69de29bb2..bc1cdbf4ad 100644 --- a/app/views/state_file/questions/email_address_validation/edit.html.erb +++ b/app/views/state_file/questions/email_address_validation/edit.html.erb @@ -0,0 +1,14 @@ +<% title = t(".enter_email") %> +<% content_for :page_title, title %> +<% content_for :card do %> +

              <%= title %>

              + + <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> +
              + <%= f.cfa_input_field(:email_address, t("state_file.questions.email_address.edit.email_address_label"), help_text: 'example@email.com', classes: ["form-width--long"]) %> +
              + + <%= f.submit t("state_file.questions.email_address.edit.action"), class: "button button--primary button--wide spacing-below-15" %> + <% end %> + <%= render 'state_file/questions/shared/verification_shortcut' %> +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index ae783596fe..a86ea9de99 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2678,6 +2678,9 @@ en: email_address_label: Your email address subtitle_html: To create a new account, provide an email address that isn't already in use.

              Use an email account you can access. title: Enter your email address + email_address_validation: + edit: + enter_email: Enter the email address linked to your account esign_declaration: edit: already_submitted: You have already submitted your return. From 0798ab6f338c3069a3bdbf79d6c4e70420bbe7c3 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 09:36:34 -0800 Subject: [PATCH 12/42] email form is not using questions controller --- .../email_address_controller.rb | 21 ++++++++++++++ ...ved_intake_verification_code_controller.rb | 20 +++++++++++++ .../email_address_validation_controller.rb | 10 +++---- .../archived_intake_verification_code_form.rb | 7 +++++ .../archived_intakes/email_address_form.rb | 28 +++++++++++++++++++ .../email_address_validation_form.rb | 10 ++----- .../navigation/archived_intake_navigation.rb | 3 +- .../state_file_archived_intake_access_log.rb | 2 +- app/services/verification_code_service.rb | 2 +- .../email_address/edit.html.erb | 16 +++++++++++ .../edit.html.erb | 12 ++++++++ .../email_address_validation/edit.html.erb | 1 - .../state_file_pages/about_page.html.erb | 2 +- config/locales/en.yml | 7 +++-- config/routes.rb | 4 +++ 15 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 app/controllers/state_file/archived_intakes/email_address_controller.rb create mode 100644 app/controllers/state_file/questions/archived_intake_verification_code_controller.rb create mode 100644 app/forms/state_file/archived_intake_verification_code_form.rb create mode 100644 app/forms/state_file/archived_intakes/email_address_form.rb create mode 100644 app/views/state_file/archived_intakes/email_address/edit.html.erb create mode 100644 app/views/state_file/questions/archived_intake_verification_code/edit.html.erb diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb new file mode 100644 index 0000000000..f77c1cca5d --- /dev/null +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -0,0 +1,21 @@ +module StateFile + module ArchivedIntakes + class EmailAddressController < ApplicationController + def edit + @form = EmailAddressForm.new + end + + def update + email_address = params["state_file_archived_intakes_email_address_form"]["email_address"] + archived_intake = StateFileArchivedIntake.find_by(email_address: email_address) + + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + details: { email_address: email_address }, + event_type: 0 + ) + + end + end + end +end diff --git a/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb b/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb new file mode 100644 index 0000000000..4a19625a86 --- /dev/null +++ b/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb @@ -0,0 +1,20 @@ +module StateFile + module Questions + class ArchivedIntakeVerificationCodeController < QuestionsController + def edit + end + + def update + # @form = initialized_update_form + # + # if @form.valid? + # redirect_to(next_path) + # else + # after_update_failure + # track_validation_error + # render :edit + # end + end + end + end +end \ No newline at end of file diff --git a/app/controllers/state_file/questions/email_address_validation_controller.rb b/app/controllers/state_file/questions/email_address_validation_controller.rb index 4c37df80bc..5a74a7e441 100644 --- a/app/controllers/state_file/questions/email_address_validation_controller.rb +++ b/app/controllers/state_file/questions/email_address_validation_controller.rb @@ -2,12 +2,12 @@ module StateFile module Questions class EmailAddressValidationController < QuestionsController def edit + # binding.pry super - # ::StateFileArchivedIntakeAccessLog.create( - # event_type: "submission", - # ip_address: ip_for_irs, - # intake: current_intake, - # ) + ::StateFileArchivedIntakeAccessLog.create( + event_type: "submission", + ip_address: ip_for_irs, + ) end end diff --git a/app/forms/state_file/archived_intake_verification_code_form.rb b/app/forms/state_file/archived_intake_verification_code_form.rb new file mode 100644 index 0000000000..83f393997a --- /dev/null +++ b/app/forms/state_file/archived_intake_verification_code_form.rb @@ -0,0 +1,7 @@ +module Portal + class ArchivedIntakeVerificationCodeForm < Form + include PhoneNumberHelper + attr_accessor :contact_info, :verification_code + validates :verification_code, format: { with: /\A[0-9]{6}\z/ } + end +end \ No newline at end of file diff --git a/app/forms/state_file/archived_intakes/email_address_form.rb b/app/forms/state_file/archived_intakes/email_address_form.rb new file mode 100644 index 0000000000..967bcd830a --- /dev/null +++ b/app/forms/state_file/archived_intakes/email_address_form.rb @@ -0,0 +1,28 @@ +module StateFile + module ArchivedIntakes + class EmailAddressForm < Form + attr_accessor :email_address + + validates :email_address, 'valid_email_2/email': true + validates :email_address, presence: true + + def initialize(attributes = {}) + binding.pry + super + assign_attributes(attributes) + end + + def save + binding.pry + run_callbacks :save do + if valid? + # Logic to persist the form data or perform actions + true + else + false + end + end + end + end + end +end diff --git a/app/forms/state_file/email_address_validation_form.rb b/app/forms/state_file/email_address_validation_form.rb index d0d3bf3cc7..836175a8cc 100644 --- a/app/forms/state_file/email_address_validation_form.rb +++ b/app/forms/state_file/email_address_validation_form.rb @@ -1,14 +1,8 @@ module StateFile class EmailAddressValidationForm < QuestionsForm - set_attributes_for :state_file_archived_intake, :email_address + set_attributes_for :intake, :email_address + validates :email_address, 'valid_email_2/email': true validates :email_address, presence: true - validates :email_address_attached_to_an_intake - - def save - @intake.update(attributes_for(:state_file_archived_intake_access_logs)) - end - - end end \ No newline at end of file diff --git a/app/lib/navigation/archived_intake_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb index 6a0e78f3d7..ecbe4665f9 100644 --- a/app/lib/navigation/archived_intake_navigation.rb +++ b/app/lib/navigation/archived_intake_navigation.rb @@ -4,7 +4,8 @@ class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation SECTIONS = [ Navigation::NavigationSection.new("state_file.navigation.section_1", [ - Navigation::NavigationStep.new(StateFile::Questions::EmailAddressValidationController) + Navigation::NavigationStep.new(StateFile::Questions::EmailAddressValidationController), + Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeVerificationCodeController) ]), ].freeze FLOW = SECTIONS.map(&:controllers).flatten.freeze diff --git a/app/models/state_file_archived_intake_access_log.rb b/app/models/state_file_archived_intake_access_log.rb index 4968350060..e764f7565f 100644 --- a/app/models/state_file_archived_intake_access_log.rb +++ b/app/models/state_file_archived_intake_access_log.rb @@ -19,7 +19,7 @@ # fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) # class StateFileArchivedIntakeAccessLog < ApplicationRecord - belongs_to :state_file_archived_intake + belongs_to :state_file_archived_intake, optional: true enum event_type: { issued_email_challenge: 0, correct_email_code: 1, diff --git a/app/services/verification_code_service.rb b/app/services/verification_code_service.rb index 98afba3694..27a2c0ddc9 100644 --- a/app/services/verification_code_service.rb +++ b/app/services/verification_code_service.rb @@ -7,4 +7,4 @@ def self.generate(contact_info) def self.hash_verification_code_with_contact_info(contact_info, verification_code) Devise.token_generator.digest(VerificationCodeService, :verification_code, "#{contact_info},#{verification_code}") end -end +end \ No newline at end of file diff --git a/app/views/state_file/archived_intakes/email_address/edit.html.erb b/app/views/state_file/archived_intakes/email_address/edit.html.erb new file mode 100644 index 0000000000..64b85b8a85 --- /dev/null +++ b/app/views/state_file/archived_intakes/email_address/edit.html.erb @@ -0,0 +1,16 @@ +<% title = t(".enter_email") %> +<% content_for :page_title, title %> +

              <%= title %>

              +<%= form_with model: @form, url: state_file_archived_intakes_email_address_path, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %> +
              + <%= f.cfa_input_field(:email_address, t("state_file.questions.email_address.edit.email_address_label"), help_text: 'example@email.com', classes: ["form-width--long"]) %> +
              + +
              + +
              +<% end %> + + diff --git a/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb b/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb new file mode 100644 index 0000000000..eb35e1374e --- /dev/null +++ b/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb @@ -0,0 +1,12 @@ +<% title = t("state_file.questions.verification_code.edit.title_html", contact_info: @contact_info) %> +<% content_for :page_title, title %> +<% content_for :card do %> + <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> +

              <%= title %>

              +

              <%= t("state_file.questions.verification_code.edit.subtitle_html") %>

              +
              + <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %> +
              + <%= f.submit t("state_file.questions.verification_code.edit.action"), class: "button button--primary button--wide spacing-below-15"%> + <% end %> +<% end %> diff --git a/app/views/state_file/questions/email_address_validation/edit.html.erb b/app/views/state_file/questions/email_address_validation/edit.html.erb index bc1cdbf4ad..cdcbc940dc 100644 --- a/app/views/state_file/questions/email_address_validation/edit.html.erb +++ b/app/views/state_file/questions/email_address_validation/edit.html.erb @@ -10,5 +10,4 @@ <%= f.submit t("state_file.questions.email_address.edit.action"), class: "button button--primary button--wide spacing-below-15" %> <% end %> - <%= render 'state_file/questions/shared/verification_shortcut' %> <% end %> diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index c31848e2b1..641ea64723 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -47,6 +47,6 @@
              <%= t(".looking_for_return_html")%>
              - <%= link_to t(".tax_return_link"), questions_email_address_validation_path %> + <%= link_to t(".tax_return_link"), state_file_archived_intakes_edit_email_address_path %>
              diff --git a/config/locales/en.yml b/config/locales/en.yml index a86ea9de99..d3dd971cd7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2231,6 +2231,10 @@ en: link_text: Opt in again. mistake: Is this a mistake? title: You've opted out of email notifications from FileYourStateTaxes. + archived_intakes: + email_address: + edit: + enter_email: Enter the email address linked to your account questions: az_charitable_contributions: edit: @@ -2678,9 +2682,6 @@ en: email_address_label: Your email address subtitle_html: To create a new account, provide an email address that isn't already in use.

              Use an email account you can access. title: Enter your email address - email_address_validation: - edit: - enter_email: Enter the email address linked to your account esign_declaration: edit: already_submitted: You have already submitted your return. diff --git a/config/routes.rb b/config/routes.rb index 215cf9abc0..8173fc10a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -555,6 +555,10 @@ def scoped_navigation_routes(context, navigation) constraints(Routes::StateFileDomain.new) do scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do namespace :state_file do + namespace :archived_intakes do + get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' + patch 'email_address', to: 'email_address#update' + end namespace :questions do get "show_xml", to: "confirmation#show_xml" get "explain_calculations", to: "confirmation#explain_calculations" From 4181a66f40bed591a386b76efa725ab970c588af Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 10:05:10 -0800 Subject: [PATCH 13/42] update unused file --- ...ved_intake_verification_code_controller.rb | 20 ------------------- .../email_address_validation_controller.rb | 15 -------------- .../archived_intake_verification_code_form.rb | 7 ------- .../navigation/archived_intake_navigation.rb | 13 ------------ app/services/verification_code_service.rb | 2 +- .../edit.html.erb | 12 ----------- 6 files changed, 1 insertion(+), 68 deletions(-) delete mode 100644 app/controllers/state_file/questions/archived_intake_verification_code_controller.rb delete mode 100644 app/controllers/state_file/questions/email_address_validation_controller.rb delete mode 100644 app/forms/state_file/archived_intake_verification_code_form.rb delete mode 100644 app/lib/navigation/archived_intake_navigation.rb delete mode 100644 app/views/state_file/questions/archived_intake_verification_code/edit.html.erb diff --git a/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb b/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb deleted file mode 100644 index 4a19625a86..0000000000 --- a/app/controllers/state_file/questions/archived_intake_verification_code_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -module StateFile - module Questions - class ArchivedIntakeVerificationCodeController < QuestionsController - def edit - end - - def update - # @form = initialized_update_form - # - # if @form.valid? - # redirect_to(next_path) - # else - # after_update_failure - # track_validation_error - # render :edit - # end - end - end - end -end \ No newline at end of file diff --git a/app/controllers/state_file/questions/email_address_validation_controller.rb b/app/controllers/state_file/questions/email_address_validation_controller.rb deleted file mode 100644 index 5a74a7e441..0000000000 --- a/app/controllers/state_file/questions/email_address_validation_controller.rb +++ /dev/null @@ -1,15 +0,0 @@ -module StateFile - module Questions - class EmailAddressValidationController < QuestionsController - def edit - # binding.pry - super - ::StateFileArchivedIntakeAccessLog.create( - event_type: "submission", - ip_address: ip_for_irs, - ) - end - - end - end -end \ No newline at end of file diff --git a/app/forms/state_file/archived_intake_verification_code_form.rb b/app/forms/state_file/archived_intake_verification_code_form.rb deleted file mode 100644 index 83f393997a..0000000000 --- a/app/forms/state_file/archived_intake_verification_code_form.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Portal - class ArchivedIntakeVerificationCodeForm < Form - include PhoneNumberHelper - attr_accessor :contact_info, :verification_code - validates :verification_code, format: { with: /\A[0-9]{6}\z/ } - end -end \ No newline at end of file diff --git a/app/lib/navigation/archived_intake_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb deleted file mode 100644 index ecbe4665f9..0000000000 --- a/app/lib/navigation/archived_intake_navigation.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Navigation - class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation - include ControllerNavigation - - SECTIONS = [ - Navigation::NavigationSection.new("state_file.navigation.section_1", [ - Navigation::NavigationStep.new(StateFile::Questions::EmailAddressValidationController), - Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeVerificationCodeController) - ]), - ].freeze - FLOW = SECTIONS.map(&:controllers).flatten.freeze - end -end diff --git a/app/services/verification_code_service.rb b/app/services/verification_code_service.rb index 27a2c0ddc9..98afba3694 100644 --- a/app/services/verification_code_service.rb +++ b/app/services/verification_code_service.rb @@ -7,4 +7,4 @@ def self.generate(contact_info) def self.hash_verification_code_with_contact_info(contact_info, verification_code) Devise.token_generator.digest(VerificationCodeService, :verification_code, "#{contact_info},#{verification_code}") end -end \ No newline at end of file +end diff --git a/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb b/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb deleted file mode 100644 index eb35e1374e..0000000000 --- a/app/views/state_file/questions/archived_intake_verification_code/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<% title = t("state_file.questions.verification_code.edit.title_html", contact_info: @contact_info) %> -<% content_for :page_title, title %> -<% content_for :card do %> - <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> -

              <%= title %>

              -

              <%= t("state_file.questions.verification_code.edit.subtitle_html") %>

              -
              - <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %> -
              - <%= f.submit t("state_file.questions.verification_code.edit.action"), class: "button button--primary button--wide spacing-below-15"%> - <% end %> -<% end %> From 5162bf6e9961bb3a1de1d3e59f2d9284db251c15 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 10:11:08 -0800 Subject: [PATCH 14/42] remove unused prys --- app/forms/state_file/archived_intakes/email_address_form.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/forms/state_file/archived_intakes/email_address_form.rb b/app/forms/state_file/archived_intakes/email_address_form.rb index 967bcd830a..323073493c 100644 --- a/app/forms/state_file/archived_intakes/email_address_form.rb +++ b/app/forms/state_file/archived_intakes/email_address_form.rb @@ -7,16 +7,13 @@ class EmailAddressForm < Form validates :email_address, presence: true def initialize(attributes = {}) - binding.pry super assign_attributes(attributes) end def save - binding.pry run_callbacks :save do if valid? - # Logic to persist the form data or perform actions true else false From c39a237e2778a890289445ab585c6174caa10142 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 12:13:08 -0800 Subject: [PATCH 15/42] pages navigate --- .../email_address_controller.rb | 24 +++++++++++++------ .../verification_code_controller.rb | 10 ++++++++ .../archived_intakes/email_address_form.rb | 6 +---- .../verification_code_form.rb | 21 ++++++++++++++++ app/forms/state_file/email_address_form.rb | 12 ---------- .../verification_code/edit.html.erb | 10 ++++++++ config/routes.rb | 4 ++-- 7 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 app/controllers/state_file/archived_intakes/verification_code_controller.rb create mode 100644 app/forms/state_file/archived_intakes/verification_code_form.rb delete mode 100644 app/forms/state_file/email_address_form.rb create mode 100644 app/views/state_file/archived_intakes/verification_code/edit.html.erb diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index f77c1cca5d..6047f18dde 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -6,15 +6,25 @@ def edit end def update - email_address = params["state_file_archived_intakes_email_address_form"]["email_address"] - archived_intake = StateFileArchivedIntake.find_by(email_address: email_address) + @form = EmailAddressForm.new(email_address_form_params) - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - details: { email_address: email_address }, - event_type: 0 - ) + if @form.save + # Assuming you need to log or handle successful form submissions + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + details: { email_address: @form.email_address }, + event_type: 0 + ) + redirect_to state_file_archived_intakes_edit_verification_code_path + else + render :edit + end + end + + private + def email_address_form_params + params.require(:state_file_archived_intakes_email_address_form).permit(:email_address) end end end diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb new file mode 100644 index 0000000000..73d897e597 --- /dev/null +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -0,0 +1,10 @@ +module StateFile + module ArchivedIntakes + class VerificationCodeController < ApplicationController + def edit + @form = VerificationCodeForm.new + end + + end + end +end diff --git a/app/forms/state_file/archived_intakes/email_address_form.rb b/app/forms/state_file/archived_intakes/email_address_form.rb index 323073493c..013c211f6b 100644 --- a/app/forms/state_file/archived_intakes/email_address_form.rb +++ b/app/forms/state_file/archived_intakes/email_address_form.rb @@ -13,11 +13,7 @@ def initialize(attributes = {}) def save run_callbacks :save do - if valid? - true - else - false - end + valid? end end end diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb new file mode 100644 index 0000000000..1d25372d32 --- /dev/null +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -0,0 +1,21 @@ +module StateFile + module ArchivedIntakes + class VerificationCodeForm < Form + attr_accessor :verification_code + + validates :verification_code, presence: true + validates :verification_code, format: { with: /\A[0-9]{6}\z/ } + + def initialize(attributes = {}) + super + assign_attributes(attributes) + end + + def save + run_callbacks :save do + valid? + end + end + end + end +end diff --git a/app/forms/state_file/email_address_form.rb b/app/forms/state_file/email_address_form.rb deleted file mode 100644 index d38abf08b4..0000000000 --- a/app/forms/state_file/email_address_form.rb +++ /dev/null @@ -1,12 +0,0 @@ -module StateFile - class EmailAddressForm < QuestionsForm - set_attributes_for :intake, :email_address - - validates :email_address, 'valid_email_2/email': true - validates :email_address, presence: true - - def save - @intake.update(attributes_for(:intake)) - end - end -end \ No newline at end of file diff --git a/app/views/state_file/archived_intakes/verification_code/edit.html.erb b/app/views/state_file/archived_intakes/verification_code/edit.html.erb new file mode 100644 index 0000000000..191c9cbb08 --- /dev/null +++ b/app/views/state_file/archived_intakes/verification_code/edit.html.erb @@ -0,0 +1,10 @@ +<% title = t("state_file.questions.verification_code.edit.title_html", contact_info: @contact_info) %> +<% content_for :page_title, title %> +<%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> +

              <%= title %>

              +

              <%= t("state_file.questions.verification_code.edit.subtitle_html") %>

              +
              + <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %> +
              +<%= f.submit t("state_file.questions.verification_code.edit.action"), class: "button button--primary button--wide spacing-below-15"%> +<% end %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 8173fc10a9..ed4f040bb4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -558,6 +558,8 @@ def scoped_navigation_routes(context, navigation) namespace :archived_intakes do get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' patch 'email_address', to: 'email_address#update' + get 'verification_code/edit', to: 'verification_code#edit', as: 'edit_verification_code' + patch 'verification_code', to: 'verification_code#update' end namespace :questions do get "show_xml", to: "confirmation#show_xml" @@ -596,8 +598,6 @@ def scoped_navigation_routes(context, navigation) navigation_class = StateFile::StateInformationService.navigation_class(code) scoped_navigation_routes(:questions, navigation_class) end - scoped_navigation_routes(:questions, Navigation::ArchivedIntakeNavigation) - match("/code-verified", action: :edit, controller: "state_file/questions/code_verified", via: :get) match("/code-verified", action: :update, controller: "state_file/questions/code_verified", via: :put) From be8795ec557606320cc5b5f3f5667261e4b3fcf3 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 13:03:51 -0800 Subject: [PATCH 16/42] Revert "Fyst 1515 add prior year access link button to homepage (#5296)" (#5317) This reverts commit f1e52460811cd58d532f62941348653b68e397c3. Co-authored-by: Drew Proebstel --- .../archived_intake_email_address_controller.rb | 6 ------ app/lib/navigation/archived_intake_navigation.rb | 12 ------------ .../archived_intake_email_address/edit.html.erb | 3 --- .../state_file/state_file_pages/about_page.html.erb | 9 +-------- config/locales/en.yml | 2 -- config/locales/es.yml | 2 -- config/routes.rb | 2 -- db/schema.rb | 2 -- 8 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 app/controllers/state_file/questions/archived_intake_email_address_controller.rb delete mode 100644 app/lib/navigation/archived_intake_navigation.rb delete mode 100644 app/views/state_file/questions/archived_intake_email_address/edit.html.erb diff --git a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb b/app/controllers/state_file/questions/archived_intake_email_address_controller.rb deleted file mode 100644 index 7d9bb14716..0000000000 --- a/app/controllers/state_file/questions/archived_intake_email_address_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -module StateFile - module Questions - class ArchivedIntakeEmailAddressController < QuestionsController - end - end -end \ No newline at end of file diff --git a/app/lib/navigation/archived_intake_navigation.rb b/app/lib/navigation/archived_intake_navigation.rb deleted file mode 100644 index 5110fd5b2d..0000000000 --- a/app/lib/navigation/archived_intake_navigation.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Navigation - class ArchivedIntakeNavigation < Navigation::StateFileBaseQuestionNavigation - include ControllerNavigation - - SECTIONS = [ - Navigation::NavigationSection.new("state_file.navigation.section_1", [ - Navigation::NavigationStep.new(StateFile::Questions::ArchivedIntakeEmailAddressController), - ]), - ].freeze - FLOW = SECTIONS.map(&:controllers).flatten.freeze - end -end diff --git a/app/views/state_file/questions/archived_intake_email_address/edit.html.erb b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb deleted file mode 100644 index 646d7bc1c3..0000000000 --- a/app/views/state_file/questions/archived_intake_email_address/edit.html.erb +++ /dev/null @@ -1,3 +0,0 @@ - -<% title = "email" %> -<% content_for :page_title, title %> \ No newline at end of file diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index 3d69de844e..7f60c9e235 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -42,11 +42,4 @@ <% end %> -<% end %> - -
              - <%= t(".looking_for_return_html")%> -
              - <%= link_to t(".tax_return_link"), questions_archived_intake_email_address_path %> -
              -
              +<% end %> \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index ae783596fe..f7b49ba628 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3794,7 +3794,6 @@ en: We're closed for the tax season. Unfortunately you can no longer file your state return with us this year.

              Already filed your state taxes with us? You can download a copy of your state return until December 31, 2024

              header: A free state filing service for taxpayers using IRS Direct File - looking_for_return_html: "Looking for your 2023 Arizona or New York State Tax Return?" section1_html: | How does it work?
                @@ -3809,7 +3808,6 @@ en: subheader_1_html: "FileYourStateTaxes integrates with IRS Direct File to help you complete your state tax return for free." subheader_2_html: IRS Direct File is now broadly available to all eligible taxpayers through April 15, 2024. For more information on timeline and eligibility, or to start filing your federal return, go to directfile.irs.gov subheader_3_html: Already filed your federal return with IRS Direct File and need to complete your state return? Sign in here. - tax_return_link: Click here to access your tax return card_postscript: responses_saved_html: Your responses are saved. If you need a break, you can come back and log in to your account at fileyourstatetaxes.org. coming_soon: diff --git a/config/locales/es.yml b/config/locales/es.yml index df5a9fb31b..98c5145903 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -3768,7 +3768,6 @@ es: Estamos cerrados por la temporada de impuestos. Desafortunadamente, no puede presentar tu declaración estatal con nosotros este año.

                ¿Ya presentó tus impuestos estatales con nosotros? Puedes descargar una copia de tu declaración estatal hasta el 31 de diciembre de 2024

                header: Una herramienta sin costo para presentar impuestos estatales para los contribuyentes utilizando IRS Direct File - looking_for_return_html: "¿Está buscando su declaración de impuestos del estado de Arizona o Nueva York de 2023?" section1_html: | ¿Cómo funciona?
                  @@ -3783,7 +3782,6 @@ es: subheader_1_html: "FileYourStateTaxes se integra con IRS Direct File para ayudarte a completar tu declaración de impuestos estatales sin costo." subheader_2_html: El IRS Direct File ahora está ampliamente disponible para todos los contribuyentes elegibles hasta el 15 de abril de 2024. Para obtener más información sobre el cronograma y la elegibilidad, o para comenzar a presentar tu declaración federal, ve a directfile.irs.gov. subheader_3_html: "¿Ya presentaste tu declaración federal con IRS Direct File y necesitas completar tu declaración estatal? Inicia sesión aquí." - tax_return_link: Haga clic aquí para acceder a su declaración de impuestos. card_postscript: responses_saved_html: Tus respuestas han sido guardadas. Si necesitas hacer una pausa, puedes regresar e iniciar sesión en tu cuenta en fileyourstatetaxes.org. coming_soon: diff --git a/config/routes.rb b/config/routes.rb index 215cf9abc0..6d167bb0ce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -592,8 +592,6 @@ def scoped_navigation_routes(context, navigation) navigation_class = StateFile::StateInformationService.navigation_class(code) scoped_navigation_routes(:questions, navigation_class) end - scoped_navigation_routes(:questions, Navigation::ArchivedIntakeNavigation) - match("/code-verified", action: :edit, controller: "state_file/questions/code_verified", via: :get) match("/code-verified", action: :update, controller: "state_file/questions/code_verified", via: :put) diff --git a/db/schema.rb b/db/schema.rb index 0ad8c85c52..1c9223ab24 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2801,8 +2801,6 @@ add_foreign_key "incoming_text_messages", "clients" add_foreign_key "intake_archives", "intakes", column: "id" add_foreign_key "intakes", "clients" - add_foreign_key "intakes", "drivers_licenses", column: "primary_drivers_license_id" - add_foreign_key "intakes", "drivers_licenses", column: "spouse_drivers_license_id" add_foreign_key "intakes", "intakes", column: "matching_previous_year_intake_id" add_foreign_key "intakes", "vita_partners" add_foreign_key "notes", "clients" From 90da0019c703329657e85d2e882d2b9b34bf0496 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Mon, 6 Jan 2025 13:09:50 -0800 Subject: [PATCH 17/42] delete unused views --- .../archived_intake_email_address/edit.html.erb | 3 --- .../email_address_validation/edit.html.erb | 13 ------------- 2 files changed, 16 deletions(-) delete mode 100644 app/views/state_file/questions/archived_intake_email_address/edit.html.erb delete mode 100644 app/views/state_file/questions/email_address_validation/edit.html.erb diff --git a/app/views/state_file/questions/archived_intake_email_address/edit.html.erb b/app/views/state_file/questions/archived_intake_email_address/edit.html.erb deleted file mode 100644 index 646d7bc1c3..0000000000 --- a/app/views/state_file/questions/archived_intake_email_address/edit.html.erb +++ /dev/null @@ -1,3 +0,0 @@ - -<% title = "email" %> -<% content_for :page_title, title %> \ No newline at end of file diff --git a/app/views/state_file/questions/email_address_validation/edit.html.erb b/app/views/state_file/questions/email_address_validation/edit.html.erb deleted file mode 100644 index cdcbc940dc..0000000000 --- a/app/views/state_file/questions/email_address_validation/edit.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<% title = t(".enter_email") %> -<% content_for :page_title, title %> -<% content_for :card do %> -

                  <%= title %>

                  - - <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> -
                  - <%= f.cfa_input_field(:email_address, t("state_file.questions.email_address.edit.email_address_label"), help_text: 'example@email.com', classes: ["form-width--long"]) %> -
                  - - <%= f.submit t("state_file.questions.email_address.edit.action"), class: "button button--primary button--wide spacing-below-15" %> - <% end %> -<% end %> From e3be6eee70592f9e77a5af64cd72645a4d4180e0 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 00:29:42 -0800 Subject: [PATCH 18/42] some tests --- .../email_address_controller.rb | 9 ++- .../verification_code_controller.rb | 16 ++++++ .../verification_code_form.rb | 1 - .../state_file_archived_intake_access_log.rb | 2 +- .../verification_code/edit.html.erb | 12 ++-- config/locales/en.yml | 6 ++ .../email_address_controller_spec.rb | 55 +++++++++++++++++++ .../verification_code_controller_spec.rb | 0 spec/factories/state_file_archived_intakes.rb | 11 +++- .../email_address_form_spec.rb | 55 +++++++++++++++++++ .../verification_code_form_spec.rb | 48 ++++++++++++++++ 11 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 spec/controllers/state_file/archived_intake/email_address_controller_spec.rb create mode 100644 spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb create mode 100644 spec/forms/state_file/archived_intakes/email_address_form_spec.rb create mode 100644 spec/forms/state_file/archived_intakes/verification_code_form_spec.rb diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 6047f18dde..721a7c1a5e 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -9,13 +9,16 @@ def update @form = EmailAddressForm.new(email_address_form_params) if @form.save - # Assuming you need to log or handle successful form submissions + + archived_intake = StateFileArchivedIntake.find_by(email_address: @form.email_address) + StateFileArchivedIntakeAccessLog.create!( ip_address: ip_for_irs, details: { email_address: @form.email_address }, - event_type: 0 + event_type: 0, + state_file_archived_intake: archived_intake ) - redirect_to state_file_archived_intakes_edit_verification_code_path + redirect_to state_file_archived_intakes_edit_verification_code_path(email_address: @form.email_address) else render :edit end diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 73d897e597..2fb5b360cd 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -3,8 +3,24 @@ module ArchivedIntakes class VerificationCodeController < ApplicationController def edit @form = VerificationCodeForm.new + @email_address = params[:email_address] end + def update + @form = VerificationCodeForm.new(verification_code_form_params) + + if @form.save + redirect_to root_path + else + render :edit + end + end + + private + + def verification_code_form_params + params.require(:state_file_archived_intakes_verification_code_form).permit(:verification_code) + end end end end diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb index 1d25372d32..ce89604656 100644 --- a/app/forms/state_file/archived_intakes/verification_code_form.rb +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -4,7 +4,6 @@ class VerificationCodeForm < Form attr_accessor :verification_code validates :verification_code, presence: true - validates :verification_code, format: { with: /\A[0-9]{6}\z/ } def initialize(attributes = {}) super diff --git a/app/models/state_file_archived_intake_access_log.rb b/app/models/state_file_archived_intake_access_log.rb index e764f7565f..f1e9cb042a 100644 --- a/app/models/state_file_archived_intake_access_log.rb +++ b/app/models/state_file_archived_intake_access_log.rb @@ -19,7 +19,7 @@ # fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) # class StateFileArchivedIntakeAccessLog < ApplicationRecord - belongs_to :state_file_archived_intake, optional: true + belongs_to :state_file_archived_intake, foreign_key: :state_file_archived_intakes_id, optional: true enum event_type: { issued_email_challenge: 0, correct_email_code: 1, diff --git a/app/views/state_file/archived_intakes/verification_code/edit.html.erb b/app/views/state_file/archived_intakes/verification_code/edit.html.erb index 191c9cbb08..dda35fb4c8 100644 --- a/app/views/state_file/archived_intakes/verification_code/edit.html.erb +++ b/app/views/state_file/archived_intakes/verification_code/edit.html.erb @@ -1,10 +1,14 @@ -<% title = t("state_file.questions.verification_code.edit.title_html", contact_info: @contact_info) %> +<% title = t(".title_html", email_address: @email_address) %> <% content_for :page_title, title %> -<%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> +<%= form_with model: @form, url: { action: :update }, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %>

                  <%= title %>

                  -

                  <%= t("state_file.questions.verification_code.edit.subtitle_html") %>

                  +

                  <%= t(".subtitle_html") %>

                  <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %>
                  -<%= f.submit t("state_file.questions.verification_code.edit.action"), class: "button button--primary button--wide spacing-below-15"%> +
                  + +
                  <% end %> \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index d3dd971cd7..5a0d68976e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2235,6 +2235,12 @@ en: email_address: edit: enter_email: Enter the email address linked to your account + verification_code: + edit: + action: Verify code + subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. + title_html: We’ve sent your code to %{email_address} + verification_code_label: Enter the 6-digit code questions: az_charitable_contributions: edit: diff --git a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb new file mode 100644 index 0000000000..2ea175f516 --- /dev/null +++ b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe StateFile::ArchivedIntakes::EmailAddressController, type: :controller do + describe "GET #edit" do + it "renders the edit template with a new EmailAddressForm" do + get :edit + + expect(assigns(:form)).to be_a(StateFile::ArchivedIntakes::EmailAddressForm) + expect(response).to render_template(:edit) + end + end + + describe "POST #update" do + let(:valid_email_address) { "test@example.com" } + let(:invalid_email_address) { "" } + let(:ip_address) { "127.0.0.1" } + + before do + allow(controller).to receive(:ip_for_irs).and_return(ip_address) + end + + context "when the form is valid" do + + it "creates an access log and redirects to the verification code page" do + post :update, params: { + state_file_archived_intakes_email_address_form: { email_address: valid_email_address } + } + expect(assigns(:form)).to be_valid + + access_log = StateFileArchivedIntakeAccessLog.last + expect(access_log.ip_address).to eq(ip_address) + expect(access_log.details["email_address"]).to eq(valid_email_address) + expect(access_log.event_type).to eq("issued_email_challenge") + + expect(response).to redirect_to( + state_file_archived_intakes_edit_verification_code_path(email_address: valid_email_address) + ) + end + end + + context "when the form is invalid" do + it "renders the edit template" do + post :update, params: { + state_file_archived_intakes_email_address_form: { email_address: invalid_email_address } + } + + expect(assigns(:form)).not_to be_valid + + expect(StateFileArchivedIntakeAccessLog.count).to eq(0) + + expect(response).to render_template(:edit) + end + end + end +end diff --git a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/factories/state_file_archived_intakes.rb b/spec/factories/state_file_archived_intakes.rb index 0f68fb4bac..3c61fa00a5 100644 --- a/spec/factories/state_file_archived_intakes.rb +++ b/spec/factories/state_file_archived_intakes.rb @@ -17,6 +17,15 @@ # FactoryBot.define do factory :state_file_archived_intake do + email_address { "geddy_lee@example.com" } + hashed_ssn { "hashed_ssn_value" } + mailing_apartment { "Apt 1" } + mailing_city { "Test City" } + mailing_state { "CA" } + mailing_street { "123 Test Street" } + mailing_zip { "12345" } + state_code { "CA" } + tax_year { 2023 } submission_pdf { nil } end -end +end \ No newline at end of file diff --git a/spec/forms/state_file/archived_intakes/email_address_form_spec.rb b/spec/forms/state_file/archived_intakes/email_address_form_spec.rb new file mode 100644 index 0000000000..8f3b88d4d9 --- /dev/null +++ b/spec/forms/state_file/archived_intakes/email_address_form_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe StateFile::ArchivedIntakes::EmailAddressForm do + describe "#valid?" do + context "when the email address is valid" do + it "returns true" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "test@example.com") + + expect(form.valid?).to be true + end + end + + context "when the email address is invalid" do + it "returns false for an improperly formatted email" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "invalid-email") + + expect(form.valid?).to be false + expect(form.errors[:email_address]).to include("Please enter a valid email address.") + end + + it "returns false when the email is blank" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "") + + expect(form.valid?).to be false + expect(form.errors[:email_address]).to include("Can't be blank.") + end + end + end + + describe "#save" do + context "when the form is valid" do + it "returns true" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "test@example.com") + + expect(form.save).to be true + end + end + + context "when the form is invalid" do + it "returns false" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "") + + expect(form.save).to be false + end + end + end + + describe "#initialize" do + it "assigns attributes correctly" do + form = StateFile::ArchivedIntakes::EmailAddressForm.new(email_address: "test@example.com") + + expect(form.email_address).to eq("test@example.com") + end + end +end diff --git a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb new file mode 100644 index 0000000000..df093310b6 --- /dev/null +++ b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb @@ -0,0 +1,48 @@ +require "rails_helper" + +RSpec.describe StateFile::ArchivedIntakes::VerificationCodeForm do + describe "#valid?" do + context "when the verification code is present" do + it "returns true" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + + expect(form.valid?).to be true + end + end + + context "when the verification code is blank" do + it "returns false" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "") + + expect(form.valid?).to be false + expect(form.errors[:verification_code]).to include("Can't be blank.") + end + end + end + + describe "#save" do + context "when the form is valid" do + it "returns true" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + + expect(form.save).to be true + end + end + + context "when the form is invalid" do + it "returns false" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "") + + expect(form.save).to be false + end + end + end + + describe "#initialize" do + it "assigns attributes correctly" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + + expect(form.verification_code).to eq("123456") + end + end +end From 4bc1aaf7875162c35b4aba763a27da071b161706 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 09:46:02 -0800 Subject: [PATCH 19/42] update schema --- app/models/intake.rb | 2 -- app/models/intake/ctc_intake.rb | 2 -- app/models/intake/gyr_intake.rb | 2 -- db/schema.rb | 33 --------------------------- spec/models/intake/gyr_intake_spec.rb | 2 -- spec/models/intake_spec.rb | 2 -- 6 files changed, 43 deletions(-) diff --git a/app/models/intake.rb b/app/models/intake.rb index a43da723da..9263fea383 100644 --- a/app/models/intake.rb +++ b/app/models/intake.rb @@ -306,8 +306,6 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) -# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) -# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # diff --git a/app/models/intake/ctc_intake.rb b/app/models/intake/ctc_intake.rb index 6508bc0ea8..dd8d7f07d8 100644 --- a/app/models/intake/ctc_intake.rb +++ b/app/models/intake/ctc_intake.rb @@ -306,8 +306,6 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) -# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) -# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::CtcIntake < Intake diff --git a/app/models/intake/gyr_intake.rb b/app/models/intake/gyr_intake.rb index db753f432f..a897d0084e 100644 --- a/app/models/intake/gyr_intake.rb +++ b/app/models/intake/gyr_intake.rb @@ -306,8 +306,6 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) -# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) -# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # class Intake::GyrIntake < Intake diff --git a/db/schema.rb b/db/schema.rb index 405178f245..9a57ba9410 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,8 +11,6 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.1].define(version: 2024_12_27_174414) do - create_schema "analytics" - # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" @@ -647,33 +645,6 @@ t.index ["name"], name: "index_coalitions_on_name", unique: true end - create_table "completed_2023_tax_return_logs", force: :cascade do |t| - t.bigint "completed_2023_tax_return_id" - t.datetime "created_at", null: false - t.integer "event_type", null: false - t.inet "ip_address" - t.datetime "updated_at", null: false - t.index ["completed_2023_tax_return_id"], name: "idx_on_completed_2023_tax_return_id_81ce7025c0" - end - - create_table "completed_2023_tax_return_pdfs", force: :cascade do |t| - t.bigint "completed_2023_tax_return_id", null: false - t.index ["completed_2023_tax_return_id"], name: "idx_on_completed_2023_tax_return_id_b19af583f0" - end - - create_table "completed_2023_tax_returns", force: :cascade do |t| - t.datetime "created_at", null: false - t.citext "email_address" - t.string "hashed_ssn" - t.string "mailing_apartment" - t.string "mailing_city" - t.string "mailing_state" - t.string "mailing_street" - t.string "mailing_zip" - t.string "state_code" - t.datetime "updated_at", null: false - end - create_table "consents", force: :cascade do |t| t.bigint "client_id", null: false t.datetime "created_at", null: false @@ -2808,8 +2779,6 @@ add_foreign_key "bulk_tax_return_updates", "users", column: "assigned_user_id" add_foreign_key "clients", "vita_partners" add_foreign_key "coalition_lead_roles", "coalitions" - add_foreign_key "completed_2023_tax_return_logs", "completed_2023_tax_returns" - add_foreign_key "completed_2023_tax_return_pdfs", "completed_2023_tax_returns" add_foreign_key "dependents", "intakes" add_foreign_key "documents", "clients" add_foreign_key "documents", "documents_requests" @@ -2830,8 +2799,6 @@ add_foreign_key "incoming_text_messages", "clients" add_foreign_key "intake_archives", "intakes", column: "id" add_foreign_key "intakes", "clients" - add_foreign_key "intakes", "drivers_licenses", column: "primary_drivers_license_id" - add_foreign_key "intakes", "drivers_licenses", column: "spouse_drivers_license_id" add_foreign_key "intakes", "intakes", column: "matching_previous_year_intake_id" add_foreign_key "intakes", "vita_partners" add_foreign_key "notes", "clients" diff --git a/spec/models/intake/gyr_intake_spec.rb b/spec/models/intake/gyr_intake_spec.rb index 861e555dba..ff99754925 100644 --- a/spec/models/intake/gyr_intake_spec.rb +++ b/spec/models/intake/gyr_intake_spec.rb @@ -306,8 +306,6 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) -# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) -# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # require "rails_helper" diff --git a/spec/models/intake_spec.rb b/spec/models/intake_spec.rb index 8cf0af8a39..7402905340 100644 --- a/spec/models/intake_spec.rb +++ b/spec/models/intake_spec.rb @@ -306,8 +306,6 @@ # # fk_rails_... (client_id => clients.id) # fk_rails_... (matching_previous_year_intake_id => intakes.id) -# fk_rails_... (primary_drivers_license_id => drivers_licenses.id) -# fk_rails_... (spouse_drivers_license_id => drivers_licenses.id) # fk_rails_... (vita_partner_id => vita_partners.id) # From 8b830ce85ec14c1cb219a80f8d51a4b7e5bc32cc Mon Sep 17 00:00:00 2001 From: Hugo Melo Date: Tue, 7 Jan 2025 16:04:38 -0500 Subject: [PATCH 20/42] Add last year verification email (#5314) * Add last year verification email Co-authored-by: Em Barnard-Shao Co-authored-by: Hugo Melo * Rename previous year to archived intake Co-authored-by: Hugo Melo * normalize Co-authored-by: Hugo Melo --------- Co-authored-by: Em Barnard-Shao --- .../hub/automated_messages_controller.rb | 1 + app/jobs/request_verification_code_email_job.rb | 2 +- ...est_verification_code_for_previous_year_job.rb | 11 +++++++++++ app/mailers/verification_code_mailer.rb | 13 +++++++++++++ .../archived_intake_verification_code.html.erb | 1 + .../archived_intake_verification_code.text.erb | 1 + config/locales/en.yml | 15 +++++++++++++++ config/locales/es.yml | 15 +++++++++++++++ .../hub/automated_messages_controller_spec.rb | 2 +- 9 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 app/jobs/request_verification_code_for_previous_year_job.rb create mode 100644 app/views/verification_code_mailer/archived_intake_verification_code.html.erb create mode 100644 app/views/verification_code_mailer/archived_intake_verification_code.text.erb diff --git a/app/controllers/hub/automated_messages_controller.rb b/app/controllers/hub/automated_messages_controller.rb index 4ccaafb3ab..7420e857ce 100644 --- a/app/controllers/hub/automated_messages_controller.rb +++ b/app/controllers/hub/automated_messages_controller.rb @@ -25,6 +25,7 @@ def messages_preview "UserMailer.assignment_email" => UserMailer.assignment_email(assigned_user: User.last, assigning_user: User.first, tax_return: TaxReturn.last, assigned_at: TaxReturn.last.updated_at), "VerificationCodeMailer.with_code" => VerificationCodeMailer.with(to: "example@example.com", locale: :en, service_type: :gyr, verification_code: '000000').with_code, "VerificationCodeMailer.no_match_found" => VerificationCodeMailer.no_match_found(to: "example@example.com", locale: :en, service_type: :gyr), + "VerificationCodeMailer.archived_intake_verification_code" => VerificationCodeMailer.archived_intake_verification_code(to: "example@example.com", locale: :en, verification_code: '000000'), "DiyIntakeEmailMailer.high_support_message" => DiyIntakeEmailMailer.high_support_message(diy_intake: DiyIntake.new(email_address: 'example@example.com', preferred_first_name: "Preferredfirstname")), "CtcSignupMailer.launch_announcement" => CtcSignupMailer.launch_announcement(email_address: "example@example.com", name: "Preferredfirstname") } diff --git a/app/jobs/request_verification_code_email_job.rb b/app/jobs/request_verification_code_email_job.rb index 943587c1a1..24b7e9125b 100644 --- a/app/jobs/request_verification_code_email_job.rb +++ b/app/jobs/request_verification_code_email_job.rb @@ -14,4 +14,4 @@ def perform(email_address: , locale: , visitor_id: , client_id: nil, service_typ def priority PRIORITY_HIGH end -end \ No newline at end of file +end diff --git a/app/jobs/request_verification_code_for_previous_year_job.rb b/app/jobs/request_verification_code_for_previous_year_job.rb new file mode 100644 index 0000000000..d5d7f58842 --- /dev/null +++ b/app/jobs/request_verification_code_for_previous_year_job.rb @@ -0,0 +1,11 @@ +class RequestVerificationCodeForPreviousYearJob < ApplicationJob + retry_on Mailgun::CommunicationError + + def priority + PRIORITY_HIGH - 1 # Subtracting one to push to the top of the queue + end + + def perform(email_address: nil, locale:) + VerificationCodeMailer.archived_intake_verification_code(to: email_address, locale: locale, verification_code: 'todo-generate-code').deliver_now + end +end diff --git a/app/mailers/verification_code_mailer.rb b/app/mailers/verification_code_mailer.rb index 539798f818..03d6a2e791 100644 --- a/app/mailers/verification_code_mailer.rb +++ b/app/mailers/verification_code_mailer.rb @@ -25,4 +25,17 @@ def no_match_found(to:, locale:, service_type:) attachments.inline['logo.png'] = service.email_logo mail(to: to, subject: @subject, from: service.noreply_email, delivery_method_options: service.delivery_method_options) end + + def archived_intake_verification_code(to:, locale:, verification_code:) + @locale = locale + service = MultiTenantService.new(:statefile) + @service_name = service.service_name + @service_name_lower = @service_name.downcase + @service_type = service.service_type + @url = service.url(locale: locale) + @verification_code = verification_code + attachments.inline['logo.png'] = service.email_logo + @subject = I18n.t("verification_code_mailer.archived_intake_verification_code.subject", service_name: @service_name, url: @url, locale: @locale) + mail(to: to, subject: @subject, from: service.noreply_email, delivery_method_options: service.delivery_method_options) + end end diff --git a/app/views/verification_code_mailer/archived_intake_verification_code.html.erb b/app/views/verification_code_mailer/archived_intake_verification_code.html.erb new file mode 100644 index 0000000000..6aeb8600fe --- /dev/null +++ b/app/views/verification_code_mailer/archived_intake_verification_code.html.erb @@ -0,0 +1 @@ +<%= t("verification_code_mailer.archived_intake_verification_code.body_html", url: @url, service_name: @service_name, service_name_lower: @service_name_lower, locale: @locale, verification_code: @verification_code) %> diff --git a/app/views/verification_code_mailer/archived_intake_verification_code.text.erb b/app/views/verification_code_mailer/archived_intake_verification_code.text.erb new file mode 100644 index 0000000000..479e78e5d1 --- /dev/null +++ b/app/views/verification_code_mailer/archived_intake_verification_code.text.erb @@ -0,0 +1 @@ +<%= t("verification_code_mailer.archived_intake_verification_code.body_text", url: @url, service_name: @service_name, service_name_lower: @service_name_lower, locale: @locale, verification_code: @verification_code) %> diff --git a/config/locales/en.yml b/config/locales/en.yml index e0de5ec7aa..92a16fee05 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3966,6 +3966,21 @@ en: zip: Please enter a valid 5-digit zip code. zip_code_with_optional_extra_digits: Please enter a valid 5-digit zip code plus optional 4 or 7 digits. verification_code_mailer: + archived_intake_verification_code: + body_html: | +

                  Hello!

                  +

                  Your six-digit verification code for %{service_name} is: %{verification_code}. This code will expire after 30 minutes.

                  +

                  Did you receive this code without signing up? Email us at help@%{service_name_lower}.org

                  +

                  Your tax team at %{service_name}.org

                  + body_text: | + Hello! + + Your six-digit verification code for %{service_name} is: %{verification_code}. This code will expire after 30 minutes. + + Did you receive this code without signing up? Email us at help@%{service_name_lower}.org + + Your tax team at %{service_name}.org + subject: Six-Digit Code from FileYourStateTaxes no_match: body_html: | Hello,

                  diff --git a/config/locales/es.yml b/config/locales/es.yml index c91709fcaa..aaf9b20d28 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -3940,6 +3940,21 @@ es: zip: Por favor, ingrese un código postal válido de 5 dígitos. zip_code_with_optional_extra_digits: Por favor, ingrese un código postal válido de 5 dígitos más los 4 o 7 dígitos opcionales. verification_code_mailer: + archived_intake_verification_code: + body_html: | +

                  Hello!

                  +

                  Your six-digit verification code for %{service_name} is: %{verification_code}. This code will expire after 30 minutes.

                  +

                  Did you receive this code without signing up? Email us at help@%{service_name_lower}.org

                  +

                  Your tax team at %{service_name}.org

                  + body_text: | + Hello! + + Your six-digit verification code for %{service_name} is: %{verification_code}. This code will expire after 30 minutes. + + Did you receive this code without signing up? Email us at help@%{service_name_lower}.org + + Your tax team at %{service_name}.org + subject: Six-Digit Code from FileYourStateTaxes no_match: body_html: | Hola,

                  diff --git a/spec/controllers/hub/automated_messages_controller_spec.rb b/spec/controllers/hub/automated_messages_controller_spec.rb index ec41c2fdb7..8837c98bc1 100644 --- a/spec/controllers/hub/automated_messages_controller_spec.rb +++ b/spec/controllers/hub/automated_messages_controller_spec.rb @@ -23,7 +23,7 @@ get :index shown_message_classes = assigns(:messages).keys - message_class_names = (AutomatedMessage::AutomatedMessage.descendants + ["UserMailer.assignment_email", "VerificationCodeMailer.with_code", "VerificationCodeMailer.no_match_found", "DiyIntakeEmailMailer.high_support_message", "CtcSignupMailer.launch_announcement", SurveyMessages::GyrCompletionSurvey, SurveyMessages::CtcExperienceSurvey]) + message_class_names = (AutomatedMessage::AutomatedMessage.descendants + ["UserMailer.assignment_email", "VerificationCodeMailer.with_code", "VerificationCodeMailer.no_match_found", "VerificationCodeMailer.archived_intake_verification_code", "DiyIntakeEmailMailer.high_support_message", "CtcSignupMailer.launch_announcement", SurveyMessages::GyrCompletionSurvey, SurveyMessages::CtcExperienceSurvey]) expect(shown_message_classes).to match_array(message_class_names) end From 32803b9f5b153d4f3de4751eedda81b8dc136046 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 13:07:14 -0800 Subject: [PATCH 21/42] wip --- .../email_address_controller.rb | 2 ++ .../verification_code_controller.rb | 7 ++++++ .../email_address_validation_form.rb | 8 ------- ..._intake_email_verification_code_service.rb | 22 +++++++++++++++++++ .../questions/verification_code/edit.html.erb | 1 + config/locales/en.yml | 2 +- .../helpers/state_file_intake_helper.rb | 2 +- 7 files changed, 34 insertions(+), 10 deletions(-) delete mode 100644 app/forms/state_file/email_address_validation_form.rb create mode 100644 app/services/archived_intake_email_verification_code_service.rb diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 721a7c1a5e..49f0b4d0ef 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -18,6 +18,8 @@ def update event_type: 0, state_file_archived_intake: archived_intake ) + + redirect_to state_file_archived_intakes_edit_verification_code_path(email_address: @form.email_address) else render :edit diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 2fb5b360cd..431b8a6820 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -4,6 +4,13 @@ class VerificationCodeController < ApplicationController def edit @form = VerificationCodeForm.new @email_address = params[:email_address] + RequestVerificationCodeEmailJob.perform_later( + email_address: @email_address, + locale: I18n.locale, + visitor_id: current_intake.visitor_id, + client_id: nil, + service_type: :statefile + ) end def update diff --git a/app/forms/state_file/email_address_validation_form.rb b/app/forms/state_file/email_address_validation_form.rb deleted file mode 100644 index 836175a8cc..0000000000 --- a/app/forms/state_file/email_address_validation_form.rb +++ /dev/null @@ -1,8 +0,0 @@ -module StateFile - class EmailAddressValidationForm < QuestionsForm - set_attributes_for :intake, :email_address - - validates :email_address, 'valid_email_2/email': true - validates :email_address, presence: true - end -end \ No newline at end of file diff --git a/app/services/archived_intake_email_verification_code_service.rb b/app/services/archived_intake_email_verification_code_service.rb new file mode 100644 index 0000000000..f217f43c8b --- /dev/null +++ b/app/services/archived_intake_email_verification_code_service.rb @@ -0,0 +1,22 @@ +class ArchivedIntakeEmailVerificationCodeService + def initialize(email_address: , locale: :en) + @service_data = MultiTenantService.new(:statefile) + @email_address = email_address + @locale = locale + end + + def request_code + _, verification_code = EmailAccessToken.generate!(email_address: @email_address) + VerificationCodeMailer.with( + to: @email_address, + verification_code: verification_code, + locale: @locale + ).archived_intake_verification_code.deliver_now + end + + private + + def self.request_code(**args) + new(**args).request_code + end +end \ No newline at end of file diff --git a/app/views/state_file/questions/verification_code/edit.html.erb b/app/views/state_file/questions/verification_code/edit.html.erb index 5a6e121d80..762467970c 100644 --- a/app/views/state_file/questions/verification_code/edit.html.erb +++ b/app/views/state_file/questions/verification_code/edit.html.erb @@ -1,4 +1,5 @@ <% title = t(".title_html", contact_info: @contact_info) %> +<%binding.pry %> <% content_for :page_title, title %> <% content_for :card do %> <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 5a0d68976e..587f8b26d4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2239,7 +2239,7 @@ en: edit: action: Verify code subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. - title_html: We’ve sent your code to %{email_address} + title_html: We’ve sent your code to %{contact_info} verification_code_label: Enter the 6-digit code questions: az_charitable_contributions: diff --git a/spec/support/helpers/state_file_intake_helper.rb b/spec/support/helpers/state_file_intake_helper.rb index 856f65f5c1..e070e47009 100644 --- a/spec/support/helpers/state_file_intake_helper.rb +++ b/spec/support/helpers/state_file_intake_helper.rb @@ -92,7 +92,7 @@ def step_through_initial_authentication(contact_preference: :text_message) expect(page).to have_text "Enter your email address" fill_in I18n.t("state_file.questions.email_address.edit.email_address_label"), with: "someone@example.com" click_on "Send code" - + save_and_open_page expect(page).to have_text "We’ve sent your code to someone@example.com" perform_enqueued_jobs From cff9432fa4e9e4772cd05ceacab25fb2ecb9e97d Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 13:50:38 -0800 Subject: [PATCH 22/42] verification code is being sent --- .../archived_intakes/verification_code_controller.rb | 7 ++----- .../archived_intake_email_verification_code_job.rb | 12 ++++++++++++ ...equest_verification_code_for_previous_year_job.rb | 11 ----------- ...rchived_intake_email_verification_code_service.rb | 9 +++------ config/locales/en.yml | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) create mode 100644 app/jobs/archived_intake_email_verification_code_job.rb delete mode 100644 app/jobs/request_verification_code_for_previous_year_job.rb diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 431b8a6820..7def835add 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -4,12 +4,9 @@ class VerificationCodeController < ApplicationController def edit @form = VerificationCodeForm.new @email_address = params[:email_address] - RequestVerificationCodeEmailJob.perform_later( + ArchivedIntakeEmailVerificationCodeJob.perform_later( email_address: @email_address, - locale: I18n.locale, - visitor_id: current_intake.visitor_id, - client_id: nil, - service_type: :statefile + locale: I18n.locale ) end diff --git a/app/jobs/archived_intake_email_verification_code_job.rb b/app/jobs/archived_intake_email_verification_code_job.rb new file mode 100644 index 0000000000..541e46dcb4 --- /dev/null +++ b/app/jobs/archived_intake_email_verification_code_job.rb @@ -0,0 +1,12 @@ +class ArchivedIntakeEmailVerificationCodeJob < ApplicationJob + retry_on Mailgun::CommunicationError + + def priority + PRIORITY_HIGH - 1 # Subtracting one to push to the top of the queue + end + + # def perform(email_address: nil, locale:) + def perform(email_address:, locale:) + ArchivedIntakeEmailVerificationCodeService.request_code(email_address: email_address, locale: locale) + end +end diff --git a/app/jobs/request_verification_code_for_previous_year_job.rb b/app/jobs/request_verification_code_for_previous_year_job.rb deleted file mode 100644 index d5d7f58842..0000000000 --- a/app/jobs/request_verification_code_for_previous_year_job.rb +++ /dev/null @@ -1,11 +0,0 @@ -class RequestVerificationCodeForPreviousYearJob < ApplicationJob - retry_on Mailgun::CommunicationError - - def priority - PRIORITY_HIGH - 1 # Subtracting one to push to the top of the queue - end - - def perform(email_address: nil, locale:) - VerificationCodeMailer.archived_intake_verification_code(to: email_address, locale: locale, verification_code: 'todo-generate-code').deliver_now - end -end diff --git a/app/services/archived_intake_email_verification_code_service.rb b/app/services/archived_intake_email_verification_code_service.rb index f217f43c8b..55391c2c4f 100644 --- a/app/services/archived_intake_email_verification_code_service.rb +++ b/app/services/archived_intake_email_verification_code_service.rb @@ -1,21 +1,18 @@ class ArchivedIntakeEmailVerificationCodeService def initialize(email_address: , locale: :en) - @service_data = MultiTenantService.new(:statefile) @email_address = email_address @locale = locale end def request_code - _, verification_code = EmailAccessToken.generate!(email_address: @email_address) - VerificationCodeMailer.with( + verification_code, = EmailAccessToken.generate!(email_address: @email_address) + VerificationCodeMailer.archived_intake_verification_code( to: @email_address, verification_code: verification_code, locale: @locale - ).archived_intake_verification_code.deliver_now + ).deliver_now end - private - def self.request_code(**args) new(**args).request_code end diff --git a/config/locales/en.yml b/config/locales/en.yml index e95c798d10..b6badb3aa1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2249,7 +2249,7 @@ en: edit: action: Verify code subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. - title_html: We’ve sent your code to %{contact_info} + title_html: We’ve sent your code to %{email_address} verification_code_label: Enter the 6-digit code questions: az_charitable_contributions: From a9df1c4d8d73cfb3e506d2e291ae40a312f1bb08 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 14:33:02 -0800 Subject: [PATCH 23/42] remove pry --- .../questions/verification_code/edit.html.erb | 1 - config/locales/en.yml | 18 ++++++++---------- config/locales/es.yml | 8 ++++++++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/views/state_file/questions/verification_code/edit.html.erb b/app/views/state_file/questions/verification_code/edit.html.erb index 762467970c..5a6e121d80 100644 --- a/app/views/state_file/questions/verification_code/edit.html.erb +++ b/app/views/state_file/questions/verification_code/edit.html.erb @@ -1,5 +1,4 @@ <% title = t(".title_html", contact_info: @contact_info) %> -<%binding.pry %> <% content_for :page_title, title %> <% content_for :card do %> <%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %> diff --git a/config/locales/en.yml b/config/locales/en.yml index b6badb3aa1..5641ba6891 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2063,6 +2063,14 @@ en: 04_detail_links_html: See our Terms and Conditions and Privacy Policy. subheader: Please sign up here to receive a notification when we open in January. state_file: + archived_intakes: + email_address: + edit: + enter_email: Enter the email address linked to your account + verification_code: + edit: + subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. + title_html: We’ve sent your code to %{email_address} faq: index: title: Common questions from %{state} taxpayers @@ -2241,16 +2249,6 @@ en: link_text: Opt in again. mistake: Is this a mistake? title: You've opted out of email notifications from FileYourStateTaxes. - archived_intakes: - email_address: - edit: - enter_email: Enter the email address linked to your account - verification_code: - edit: - action: Verify code - subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. - title_html: We’ve sent your code to %{email_address} - verification_code_label: Enter the 6-digit code questions: az_charitable_contributions: edit: diff --git a/config/locales/es.yml b/config/locales/es.yml index 8565b5c913..7f49dea250 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -2015,6 +2015,14 @@ es: 04_detail_links_html: Favor de consultar nuestras Condiciones generales y Política de privacidad. subheader: Regístrese aquí para recibir una notificación cuando abramos en enero. state_file: + archived_intakes: + email_address: + edit: + enter_email: Ingresa la dirección de correo electrónico vinculada a tu cuenta + verification_code: + edit: + subtitle_html: Si no recibiste un código, revisa tu carpeta de spam. Si aún necesitas ayuda para volver a suscribirte, chatea con nosotros. + title_html: Hemos enviado tu código a %{email_address} faq: index: title: 'Preguntas frecuentes de los contribuyentes de %{state}:' From 8d0787eaadc34eee7ae2d6951fe8d74cad407aee Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Tue, 7 Jan 2025 15:27:59 -0800 Subject: [PATCH 24/42] adds missing form --- app/forms/state_file/email_address_form.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 app/forms/state_file/email_address_form.rb diff --git a/app/forms/state_file/email_address_form.rb b/app/forms/state_file/email_address_form.rb new file mode 100644 index 0000000000..6658c7e88e --- /dev/null +++ b/app/forms/state_file/email_address_form.rb @@ -0,0 +1,12 @@ +module StateFile + class EmailAddressForm < QuestionsForm + set_attributes_for :intake, :email_address + + validates :email_address, 'valid_email_2/email': true + validates :email_address, presence: true + + def save + @intake.update(attributes_for(:intake)) + end + end +end From 01a2ea6df0875d0db41cf07e59423aebbbf15a4d Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Wed, 8 Jan 2025 15:36:08 -0800 Subject: [PATCH 25/42] wip --- .../email_address_controller.rb | 1 + .../verification_code_controller.rb | 3 ++- .../verification_code_form.rb | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 49f0b4d0ef..a13ae21e75 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -19,6 +19,7 @@ def update state_file_archived_intake: archived_intake ) + session[:email_address] = @form.email_address redirect_to state_file_archived_intakes_edit_verification_code_path(email_address: @form.email_address) else diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 7def835add..10ecc808bf 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -2,6 +2,7 @@ module StateFile module ArchivedIntakes class VerificationCodeController < ApplicationController def edit + binding.pry @form = VerificationCodeForm.new @email_address = params[:email_address] ArchivedIntakeEmailVerificationCodeJob.perform_later( @@ -13,7 +14,7 @@ def edit def update @form = VerificationCodeForm.new(verification_code_form_params) - if @form.save + if @form.valid? redirect_to root_path else render :edit diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb index ce89604656..69ca8cb66b 100644 --- a/app/forms/state_file/archived_intakes/verification_code_form.rb +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -10,6 +10,27 @@ def initialize(attributes = {}) assign_attributes(attributes) end + def valid? + binding.pry + hashed_verification_code = VerificationCodeService.hash_verification_code_with_contact_info(nil, verification_code) + # # Magic codes provide a way of bypassing security in a development context. + # # The easiest way to do this was to update the last entry to actually have the magic code. + # if Rails.configuration.allow_magic_verification_code && verification_code == "000000" + # token = EmailAccessToken.where(email_address: @intake.email_address).last + # if token.present? + # token.update( + # token: Devise.token_generator.digest(EmailAccessToken, :token, hashed_verification_code), + # ) + # end + # return true + # end + + valid_code = EmailAccessToken.lookup(hashed_verification_code).exists? + + errors.add(:verification_code, I18n.t("views.questions.verification.error_message")) unless valid_code + + valid_code.present? + end def save run_callbacks :save do valid? From 9fa60cb8c73bd49e4898a6342f45c31fe24fdcfc Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Wed, 8 Jan 2025 17:54:09 -0800 Subject: [PATCH 26/42] add devise table --- .../archived_intake_controller.rb | 9 ++++++ .../email_address_controller.rb | 18 ++++++------ .../verification_code_controller.rb | 10 +++---- .../verification_code_form.rb | 12 ++++---- app/models/state_file_archived_intake.rb | 2 +- .../state_file_archived_intake_access_log.rb | 22 ++++++-------- .../state_file_archived_intake_request.rb | 29 +++++++++++++++++++ config/routes.rb | 1 + ...853_state_file_archived_intake_requests.rb | 14 +++++++++ ..._to_state_file_archived_intake_requests.rb | 8 +++++ ..._state_file_archived_intake_access_logs.rb | 6 ++++ ..._state_file_archived_intake_access_logs.rb | 5 ++++ db/schema.rb | 18 ++++++++++-- .../state_file_archived_intake_access_logs.rb | 20 +++++-------- ...te_file_archived_intake_access_log_spec.rb | 20 +++++-------- 15 files changed, 133 insertions(+), 61 deletions(-) create mode 100644 app/controllers/state_file/archived_intakes/archived_intake_controller.rb create mode 100644 app/models/state_file_archived_intake_request.rb create mode 100644 db/migrate/20250108221853_state_file_archived_intake_requests.rb create mode 100644 db/migrate/20250108223733_add_devise_to_state_file_archived_intake_requests.rb create mode 100644 db/migrate/20250108230315_add_foreign_keyto_state_file_archived_intake_access_logs.rb create mode 100644 db/migrate/20250108231212_validate_foreign_keyfor_state_file_archived_intake_access_logs.rb diff --git a/app/controllers/state_file/archived_intakes/archived_intake_controller.rb b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb new file mode 100644 index 0000000000..1f09c3be9e --- /dev/null +++ b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb @@ -0,0 +1,9 @@ +module StateFile + module ArchivedIntakes + class ArchivedIntakeController < ApplicationController + def current_request + StateFileArchivedIntakeRequest.where(ip_address: ip_for_irs).order(created_at: :desc).first + end + end + end +end diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index a13ae21e75..3f7cb03a41 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -1,6 +1,6 @@ module StateFile module ArchivedIntakes - class EmailAddressController < ApplicationController + class EmailAddressController < ArchivedIntakeController def edit @form = EmailAddressForm.new end @@ -12,16 +12,16 @@ def update archived_intake = StateFileArchivedIntake.find_by(email_address: @form.email_address) - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - details: { email_address: @form.email_address }, - event_type: 0, - state_file_archived_intake: archived_intake - ) + StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs ) + # StateFileArchivedIntakeAccessLog.create!( + # ip_address: ip_for_irs, + # details: { email_address: @form.email_address }, + # event_type: 0, + # state_file_archived_intake: archived_intake + # ) - session[:email_address] = @form.email_address - redirect_to state_file_archived_intakes_edit_verification_code_path(email_address: @form.email_address) + redirect_to state_file_archived_intakes_edit_verification_code_path else render :edit end diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 10ecc808bf..96c91f5d74 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -1,10 +1,10 @@ module StateFile module ArchivedIntakes - class VerificationCodeController < ApplicationController + class VerificationCodeController < ArchivedIntakeController def edit - binding.pry - @form = VerificationCodeForm.new - @email_address = params[:email_address] + + @form = VerificationCodeForm.new(email_address: current_request.email_address) + @email_address = current_request.email_address ArchivedIntakeEmailVerificationCodeJob.perform_later( email_address: @email_address, locale: I18n.locale @@ -12,7 +12,7 @@ def edit end def update - @form = VerificationCodeForm.new(verification_code_form_params) + @form = VerificationCodeForm.new(verification_code_form_params, email_address: current_request.email_address) if @form.valid? redirect_to root_path diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb index 69ca8cb66b..971cbd340c 100644 --- a/app/forms/state_file/archived_intakes/verification_code_form.rb +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -1,18 +1,18 @@ module StateFile module ArchivedIntakes class VerificationCodeForm < Form - attr_accessor :verification_code + attr_accessor :verification_code, :email_address validates :verification_code, presence: true - - def initialize(attributes = {}) - super + def initialize(attributes = {}, email_address: nil) + super(attributes) # Pass attributes to the parent class + @email_address = email_address # Assign email_address to an instance variable assign_attributes(attributes) end + def valid? - binding.pry - hashed_verification_code = VerificationCodeService.hash_verification_code_with_contact_info(nil, verification_code) + hashed_verification_code = VerificationCodeService.hash_verification_code_with_contact_info(@email_address, verification_code) # # Magic codes provide a way of bypassing security in a development context. # # The easiest way to do this was to update the last entry to actually have the magic code. # if Rails.configuration.allow_magic_verification_code && verification_code == "000000" diff --git a/app/models/state_file_archived_intake.rb b/app/models/state_file_archived_intake.rb index e5c464a926..e4ea6a41db 100644 --- a/app/models/state_file_archived_intake.rb +++ b/app/models/state_file_archived_intake.rb @@ -17,5 +17,5 @@ # class StateFileArchivedIntake < ApplicationRecord has_one_attached :submission_pdf - has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' + has_many :intake_requests, class_name: 'StateFileArchivedIntakeRequest' end diff --git a/app/models/state_file_archived_intake_access_log.rb b/app/models/state_file_archived_intake_access_log.rb index f1e9cb042a..71f41b7af5 100644 --- a/app/models/state_file_archived_intake_access_log.rb +++ b/app/models/state_file_archived_intake_access_log.rb @@ -2,24 +2,20 @@ # # Table name: state_file_archived_intake_access_logs # -# id :bigint not null, primary key -# details :jsonb -# event_type :integer -# ip_address :string -# created_at :datetime not null -# updated_at :datetime not null -# state_file_archived_intakes_id :bigint -# -# Indexes -# -# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intake_request_id :bigint # # Foreign Keys # -# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# fk_rails_... (state_file_archived_intake_request_id => state_file_archived_intake_requests.id) # class StateFileArchivedIntakeAccessLog < ApplicationRecord - belongs_to :state_file_archived_intake, foreign_key: :state_file_archived_intakes_id, optional: true + belongs_to :state_file_archived_intake_request enum event_type: { issued_email_challenge: 0, correct_email_code: 1, diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb new file mode 100644 index 0000000000..1b6e79729f --- /dev/null +++ b/app/models/state_file_archived_intake_request.rb @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: state_file_archived_intake_requests +# +# id :bigint not null, primary key +# details :jsonb +# email_address :string +# failed_attempts :integer default(0), not null +# ip_address :string +# locked_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intakes_id :bigint +# +# Indexes +# +# idx_on_state_file_archived_intakes_id_31501c23f8 (state_file_archived_intakes_id) +# +# Foreign Keys +# +# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# +class StateFileArchivedIntakeRequest < ApplicationRecord + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :lockable, :timeoutable, :trackable + + has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' +end diff --git a/config/routes.rb b/config/routes.rb index ed4f040bb4..0b7da310f9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + devise_for :state_file_archived_intake_requests active_state_codes = StateFile::StateInformationService.active_state_codes active_state_codes.each do |code| diff --git a/db/migrate/20250108221853_state_file_archived_intake_requests.rb b/db/migrate/20250108221853_state_file_archived_intake_requests.rb new file mode 100644 index 0000000000..55c19af010 --- /dev/null +++ b/db/migrate/20250108221853_state_file_archived_intake_requests.rb @@ -0,0 +1,14 @@ +class StateFileArchivedIntakeRequests < ActiveRecord::Migration[7.1] + def change + create_table :state_file_archived_intake_requests do |t| + t.belongs_to :state_file_archived_intakes, foreign_key: true + t.string 'ip_address' + t.string 'email_address' + t.jsonb 'details', default: '{}' + t.timestamps + end + + remove_foreign_key :state_file_archived_intake_access_logs, :state_file_archived_intakes + safety_assured { remove_column :state_file_archived_intake_access_logs, :state_file_archived_intakes_id } + end +end diff --git a/db/migrate/20250108223733_add_devise_to_state_file_archived_intake_requests.rb b/db/migrate/20250108223733_add_devise_to_state_file_archived_intake_requests.rb new file mode 100644 index 0000000000..4f453ec1fb --- /dev/null +++ b/db/migrate/20250108223733_add_devise_to_state_file_archived_intake_requests.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddDeviseToStateFileArchivedIntakeRequests < ActiveRecord::Migration[7.1] + def change + add_column :state_file_archived_intake_requests, :failed_attempts, :integer, default: 0, null: false + add_column :state_file_archived_intake_requests, :locked_at, :datetime + end +end diff --git a/db/migrate/20250108230315_add_foreign_keyto_state_file_archived_intake_access_logs.rb b/db/migrate/20250108230315_add_foreign_keyto_state_file_archived_intake_access_logs.rb new file mode 100644 index 0000000000..062afa8263 --- /dev/null +++ b/db/migrate/20250108230315_add_foreign_keyto_state_file_archived_intake_access_logs.rb @@ -0,0 +1,6 @@ +class AddForeignKeytoStateFileArchivedIntakeAccessLogs < ActiveRecord::Migration[7.1] + def change + add_column :state_file_archived_intake_access_logs, :state_file_archived_intake_request_id, :bigint + add_foreign_key :state_file_archived_intake_access_logs, :state_file_archived_intake_requests, column: :state_file_archived_intake_request_id, validate: false + end +end diff --git a/db/migrate/20250108231212_validate_foreign_keyfor_state_file_archived_intake_access_logs.rb b/db/migrate/20250108231212_validate_foreign_keyfor_state_file_archived_intake_access_logs.rb new file mode 100644 index 0000000000..0f849150dc --- /dev/null +++ b/db/migrate/20250108231212_validate_foreign_keyfor_state_file_archived_intake_access_logs.rb @@ -0,0 +1,5 @@ +class ValidateForeignKeyforStateFileArchivedIntakeAccessLogs < ActiveRecord::Migration[7.1] + def change + validate_foreign_key :state_file_archived_intake_access_logs, :state_file_archived_intake_requests + end +end diff --git a/db/schema.rb b/db/schema.rb index 251acca2f2..bab3b849e8 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.1].define(version: 2024_12_27_174414) do +ActiveRecord::Schema[7.1].define(version: 2025_01_08_231212) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" @@ -1688,9 +1688,20 @@ t.jsonb "details", default: "{}" t.integer "event_type" t.string "ip_address" + t.bigint "state_file_archived_intake_request_id" + t.datetime "updated_at", null: false + end + + create_table "state_file_archived_intake_requests", force: :cascade do |t| + t.datetime "created_at", null: false + t.jsonb "details", default: "{}" + t.string "email_address" + t.integer "failed_attempts", default: 0, null: false + t.string "ip_address" + t.datetime "locked_at" t.bigint "state_file_archived_intakes_id" t.datetime "updated_at", null: false - t.index ["state_file_archived_intakes_id"], name: "idx_on_state_file_archived_intakes_id_e878049c06" + t.index ["state_file_archived_intakes_id"], name: "idx_on_state_file_archived_intakes_id_31501c23f8" end create_table "state_file_archived_intakes", force: :cascade do |t| @@ -2812,7 +2823,8 @@ add_foreign_key "site_coordinator_roles_vita_partners", "site_coordinator_roles" add_foreign_key "site_coordinator_roles_vita_partners", "vita_partners" add_foreign_key "source_parameters", "vita_partners" - add_foreign_key "state_file_archived_intake_access_logs", "state_file_archived_intakes", column: "state_file_archived_intakes_id" + add_foreign_key "state_file_archived_intake_access_logs", "state_file_archived_intake_requests" + add_foreign_key "state_file_archived_intake_requests", "state_file_archived_intakes", column: "state_file_archived_intakes_id" add_foreign_key "state_routing_fractions", "state_routing_targets" add_foreign_key "state_routing_fractions", "vita_partners" add_foreign_key "system_notes", "clients" diff --git a/spec/factories/state_file_archived_intake_access_logs.rb b/spec/factories/state_file_archived_intake_access_logs.rb index 38637da7b9..b0fded157f 100644 --- a/spec/factories/state_file_archived_intake_access_logs.rb +++ b/spec/factories/state_file_archived_intake_access_logs.rb @@ -2,21 +2,17 @@ # # Table name: state_file_archived_intake_access_logs # -# id :bigint not null, primary key -# details :jsonb -# event_type :integer -# ip_address :string -# created_at :datetime not null -# updated_at :datetime not null -# state_file_archived_intakes_id :bigint -# -# Indexes -# -# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intake_request_id :bigint # # Foreign Keys # -# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# fk_rails_... (state_file_archived_intake_request_id => state_file_archived_intake_requests.id) # FactoryBot.define do factory :state_file_archived_intake_access_log do diff --git a/spec/models/state_file_archived_intake_access_log_spec.rb b/spec/models/state_file_archived_intake_access_log_spec.rb index 0c8b0e1989..21100194bb 100644 --- a/spec/models/state_file_archived_intake_access_log_spec.rb +++ b/spec/models/state_file_archived_intake_access_log_spec.rb @@ -2,21 +2,17 @@ # # Table name: state_file_archived_intake_access_logs # -# id :bigint not null, primary key -# details :jsonb -# event_type :integer -# ip_address :string -# created_at :datetime not null -# updated_at :datetime not null -# state_file_archived_intakes_id :bigint -# -# Indexes -# -# idx_on_state_file_archived_intakes_id_e878049c06 (state_file_archived_intakes_id) +# id :bigint not null, primary key +# details :jsonb +# event_type :integer +# ip_address :string +# created_at :datetime not null +# updated_at :datetime not null +# state_file_archived_intake_request_id :bigint # # Foreign Keys # -# fk_rails_... (state_file_archived_intakes_id => state_file_archived_intakes.id) +# fk_rails_... (state_file_archived_intake_request_id => state_file_archived_intake_requests.id) # require 'rails_helper' From 33a73757094af2f7dd56bf16ad2cac3d82cf695a Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 9 Jan 2025 15:13:56 -0800 Subject: [PATCH 27/42] add flipper --- .../email_address_controller.rb | 17 ++-- .../verification_code_controller.rb | 23 ++++++ .../verification_code_form.rb | 19 +---- .../state_file_archived_intake_request.rb | 8 ++ .../state_file_pages/about_page.html.erb | 10 ++- config/routes.rb | 12 +-- .../email_address_controller_spec.rb | 55 ++++++++++--- .../verification_code_controller_spec.rb | 81 +++++++++++++++++++ .../state_file_archived_intake_requests.rb | 11 +++ 9 files changed, 189 insertions(+), 47 deletions(-) create mode 100644 spec/factories/state_file/state_file_archived_intake_requests.rb diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 3f7cb03a41..a4b477d8d0 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -9,17 +9,14 @@ def update @form = EmailAddressForm.new(email_address_form_params) if @form.save - archived_intake = StateFileArchivedIntake.find_by(email_address: @form.email_address) - - StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs ) - # StateFileArchivedIntakeAccessLog.create!( - # ip_address: ip_for_irs, - # details: { email_address: @form.email_address }, - # event_type: 0, - # state_file_archived_intake: archived_intake - # ) - + request = StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs, state_file_archived_intakes_id: archived_intake&.id ) + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + details: { email_address: @form.email_address }, + event_type: 0, + state_file_archived_intake_request: request + ) redirect_to state_file_archived_intakes_edit_verification_code_path else diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 96c91f5d74..3ec3ec0393 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -15,8 +15,31 @@ def update @form = VerificationCodeForm.new(verification_code_form_params, email_address: current_request.email_address) if @form.valid? + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + event_type: 1, + state_file_archived_intake_request: current_request + ) + redirect_to root_path else + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + event_type: 2, + state_file_archived_intake_request: current_request + ) + current_request.increment!(:failed_attempts) + if current_request.failed_attempts == 1 + errors.add(:verification_code, "Incorrect verification code. After 2 failed attempts, accounts are locked.") + elsif current_request.failed_attempts > 1 + StateFileArchivedIntakeAccessLog.create!( + ip_address: ip_for_irs, + event_type: 6, + state_file_archived_intake_request: current_request + ) + current_request.lock_access! + redirect_to root_path + end render :edit end end diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb index 971cbd340c..64f65e89da 100644 --- a/app/forms/state_file/archived_intakes/verification_code_form.rb +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -5,32 +5,21 @@ class VerificationCodeForm < Form validates :verification_code, presence: true def initialize(attributes = {}, email_address: nil) - super(attributes) # Pass attributes to the parent class - @email_address = email_address # Assign email_address to an instance variable + super(attributes) + @email_address = email_address assign_attributes(attributes) end - def valid? hashed_verification_code = VerificationCodeService.hash_verification_code_with_contact_info(@email_address, verification_code) - # # Magic codes provide a way of bypassing security in a development context. - # # The easiest way to do this was to update the last entry to actually have the magic code. - # if Rails.configuration.allow_magic_verification_code && verification_code == "000000" - # token = EmailAccessToken.where(email_address: @intake.email_address).last - # if token.present? - # token.update( - # token: Devise.token_generator.digest(EmailAccessToken, :token, hashed_verification_code), - # ) - # end - # return true - # end valid_code = EmailAccessToken.lookup(hashed_verification_code).exists? - errors.add(:verification_code, I18n.t("views.questions.verification.error_message")) unless valid_code + errors.add(:verification_code, "Incorrect verification code. After 2 failed attempts, accounts are locked.") unless valid_code valid_code.present? end + def save run_callbacks :save do valid? diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb index 1b6e79729f..6ef46d16f8 100644 --- a/app/models/state_file_archived_intake_request.rb +++ b/app/models/state_file_archived_intake_request.rb @@ -26,4 +26,12 @@ class StateFileArchivedIntakeRequest < ApplicationRecord devise :lockable, :timeoutable, :trackable has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' + + def lock_strategy + :failed_attempts + end + + def unlock_strategy + :time + end end diff --git a/app/views/state_file/state_file_pages/about_page.html.erb b/app/views/state_file/state_file_pages/about_page.html.erb index 641ea64723..b9d54ff9d2 100644 --- a/app/views/state_file/state_file_pages/about_page.html.erb +++ b/app/views/state_file/state_file_pages/about_page.html.erb @@ -45,8 +45,10 @@ <% end %>
                  - <%= t(".looking_for_return_html")%> -
                  - <%= link_to t(".tax_return_link"), state_file_archived_intakes_edit_email_address_path %> -
                  + <% if Flipper.enabled?(:get_your_pdf) %> + <%= t(".looking_for_return_html")%> +
                  + <%= link_to t(".tax_return_link"), state_file_archived_intakes_edit_email_address_path %> +
                  + <% end %>
                  diff --git a/config/routes.rb b/config/routes.rb index 0b7da310f9..6e1f420596 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -556,11 +556,13 @@ def scoped_navigation_routes(context, navigation) constraints(Routes::StateFileDomain.new) do scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do namespace :state_file do - namespace :archived_intakes do - get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' - patch 'email_address', to: 'email_address#update' - get 'verification_code/edit', to: 'verification_code#edit', as: 'edit_verification_code' - patch 'verification_code', to: 'verification_code#update' + if Flipper.enabled?(:get_your_pdf) + namespace :archived_intakes do + get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' + patch 'email_address', to: 'email_address#update' + get 'verification_code/edit', to: 'verification_code#edit', as: 'edit_verification_code' + patch 'verification_code', to: 'verification_code#update' + end end namespace :questions do get "show_xml", to: "confirmation#show_xml" diff --git a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb index 2ea175f516..af635557fb 100644 --- a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb @@ -20,24 +20,53 @@ end context "when the form is valid" do + context "and a archived intake exists with the email address" do + let!(:archived_intake) { create :state_file_archived_intake, email_address: valid_email_address } + it "creates an access log create a request and redirects to the verification code page" do + post :update, params: { + state_file_archived_intakes_email_address_form: { email_address: valid_email_address } + } + expect(assigns(:form)).to be_valid - it "creates an access log and redirects to the verification code page" do - post :update, params: { - state_file_archived_intakes_email_address_form: { email_address: valid_email_address } - } - expect(assigns(:form)).to be_valid + request = StateFileArchivedIntakeRequest.last + expect(request.ip_address).to eq(ip_address) + expect(request.email_address).to eq(valid_email_address) + expect(request.state_file_archived_intakes_id).to eq(archived_intake.id) - access_log = StateFileArchivedIntakeAccessLog.last - expect(access_log.ip_address).to eq(ip_address) - expect(access_log.details["email_address"]).to eq(valid_email_address) - expect(access_log.event_type).to eq("issued_email_challenge") + log = StateFileArchivedIntakeAccessLog.last + expect(log.ip_address).to eq(ip_address) + expect(log.state_file_archived_intake_request_id).to eq(request.id) + expect(log.event_type).to eq("issued_email_challenge") - expect(response).to redirect_to( - state_file_archived_intakes_edit_verification_code_path(email_address: valid_email_address) - ) + expect(response).to redirect_to( + state_file_archived_intakes_edit_verification_code_path + ) + end end - end + context "and a archived does not exist with the email address" do + it "creates an access log create a request and redirects to the verification code page" do + post :update, params: { + state_file_archived_intakes_email_address_form: { email_address: valid_email_address } + } + expect(assigns(:form)).to be_valid + + request = StateFileArchivedIntakeRequest.last + expect(request.ip_address).to eq(ip_address) + expect(request.email_address).to eq(valid_email_address) + expect(request.state_file_archived_intakes_id).to eq(nil) + + log = StateFileArchivedIntakeAccessLog.last + expect(log.ip_address).to eq(ip_address) + expect(log.state_file_archived_intake_request_id).to eq(request.id) + expect(log.event_type).to eq("issued_email_challenge") + + expect(response).to redirect_to( + state_file_archived_intakes_edit_verification_code_path + ) + end + end + end context "when the form is invalid" do it "renders the edit template" do post :update, params: { diff --git a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb index e69de29bb2..4a2fb1a9c7 100644 --- a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb @@ -0,0 +1,81 @@ +RSpec.describe StateFile::ArchivedIntakes::VerificationCodeController, type: :controller do + let(:current_request) { create(:state_file_archived_intake_request, failed_attempts: 0) } + let(:email_address) { "test@example.com" } + let(:valid_verification_code) { "123456" } + let(:invalid_verification_code) { "654321" } + + before do + allow(controller).to receive(:current_request).and_return(current_request) + allow(current_request).to receive(:email_address).and_return(email_address) + allow(I18n).to receive(:locale).and_return(:en) + end + + describe "GET #edit" do + it "initializes a new VerificationCodeForm and queues a job to send the verification code" do + expect(ArchivedIntakeEmailVerificationCodeJob).to receive(:perform_later).with( + email_address: email_address, + locale: :en + ) + + get :edit + + expect(assigns(:form)).to be_a(StateFile::ArchivedIntakes::VerificationCodeForm) + expect(assigns(:email_address)).to eq(email_address) + expect(response).to render_template(:edit) + end + end + + describe "POST #update" do + context "with valid verification code" do + before do + allow_any_instance_of(StateFile::ArchivedIntakes::VerificationCodeForm).to receive(:valid?).and_return(true) + end + + it "creates a success access log, redirects to root path, and does not increment failed_attempts" do + expect { + post :update, params: { state_file_archived_intakes_verification_code_form: { verification_code: valid_verification_code } } + }.to change(StateFileArchivedIntakeAccessLog, :count).by(1) + + log = StateFileArchivedIntakeAccessLog.last + expect(log.event_type).to eq(1) + + expect(current_request.failed_attempts).to eq(0) + expect(response).to redirect_to(root_path) + end + end + + context "with invalid verification code" do + before do + allow_any_instance_of(StateFile::ArchivedIntakes::VerificationCodeForm).to receive(:valid?).and_return(false) + end + + it "creates a failure access log, increments failed_attempts, and re-renders edit on first failed attempt" do + expect { + post :update, params: { state_file_archived_intakes_verification_code_form: { verification_code: invalid_verification_code } } + }.to change(StateFileArchivedIntakeAccessLog, :count).by(1) + + log = StateFileArchivedIntakeAccessLog.last + expect(log.event_type).to eq(2) + + expect(current_request.reload.failed_attempts).to eq(1) + expect(assigns(:form)).to be_a(StateFile::ArchivedIntakes::VerificationCodeForm) + expect(response).to render_template(:edit) + end + + it "locks the account and redirects to root path after multiple failed attempts" do + current_request.update!(failed_attempts: 1) + + expect { + post :update, params: { state_file_archived_intakes_verification_code_form: { verification_code: invalid_verification_code } } + }.to change(StateFileArchivedIntakeAccessLog, :count).by(2) # One for failure, one for lock + + log = StateFileArchivedIntakeAccessLog.last + expect(log.event_type).to eq(6) # Account locked event + + expect(current_request.reload.failed_attempts).to eq(2) + expect(current_request.reload.locked?).to be_truthy + expect(response).to redirect_to(root_path) + end + end + end +end diff --git a/spec/factories/state_file/state_file_archived_intake_requests.rb b/spec/factories/state_file/state_file_archived_intake_requests.rb new file mode 100644 index 0000000000..bc6b96dc4c --- /dev/null +++ b/spec/factories/state_file/state_file_archived_intake_requests.rb @@ -0,0 +1,11 @@ +FactoryBot.define do + factory :state_file_archived_intake_request do + email_address { "geddy_lee@gmail.com" } + failed_attempts { 0 } + locked_at { nil } + + trait :locked do + locked_at { Time.current } + end + end +end From 7b4a3ebe5bc7e1fd9b3a838f7c748eec32ac0e48 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 9 Jan 2025 15:27:09 -0800 Subject: [PATCH 28/42] improved flipper --- .../archived_intakes/email_address_controller.rb | 8 ++++++++ .../archived_intakes/verification_code_controller.rb | 7 +++++++ config/routes.rb | 12 +++++------- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index a4b477d8d0..81c300c6ba 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -1,6 +1,7 @@ module StateFile module ArchivedIntakes class EmailAddressController < ArchivedIntakeController + before_action :check_feature_flag def edit @form = EmailAddressForm.new end @@ -29,6 +30,13 @@ def update def email_address_form_params params.require(:state_file_archived_intakes_email_address_form).permit(:email_address) end + + def check_feature_flag + unless Flipper.enabled?(:get_your_pdf) + redirect_to root_path + end + end + end end end diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 3ec3ec0393..7f9fe0af99 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -1,6 +1,7 @@ module StateFile module ArchivedIntakes class VerificationCodeController < ArchivedIntakeController + before_action :check_feature_flag def edit @form = VerificationCodeForm.new(email_address: current_request.email_address) @@ -49,6 +50,12 @@ def update def verification_code_form_params params.require(:state_file_archived_intakes_verification_code_form).permit(:verification_code) end + + def check_feature_flag + unless Flipper.enabled?(:get_your_pdf) + redirect_to root_path + end + end end end end diff --git a/config/routes.rb b/config/routes.rb index 6e1f420596..0b7da310f9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -556,13 +556,11 @@ def scoped_navigation_routes(context, navigation) constraints(Routes::StateFileDomain.new) do scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do namespace :state_file do - if Flipper.enabled?(:get_your_pdf) - namespace :archived_intakes do - get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' - patch 'email_address', to: 'email_address#update' - get 'verification_code/edit', to: 'verification_code#edit', as: 'edit_verification_code' - patch 'verification_code', to: 'verification_code#update' - end + namespace :archived_intakes do + get 'email_address/edit', to: 'email_address#edit', as: 'edit_email_address' + patch 'email_address', to: 'email_address#update' + get 'verification_code/edit', to: 'verification_code#edit', as: 'edit_verification_code' + patch 'verification_code', to: 'verification_code#update' end namespace :questions do get "show_xml", to: "confirmation#show_xml" From 192ceccbf24ff74af891b98389243ad8990a5515 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 9 Jan 2025 16:11:49 -0800 Subject: [PATCH 29/42] update tests --- .../verification_code_controller.rb | 6 +- .../email_address_controller_spec.rb | 3 + .../verification_code_controller_spec.rb | 18 ++--- .../verification_code_form_spec.rb | 67 ++++++++++++++++--- 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 7f9fe0af99..c568704a95 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -30,9 +30,8 @@ def update state_file_archived_intake_request: current_request ) current_request.increment!(:failed_attempts) - if current_request.failed_attempts == 1 - errors.add(:verification_code, "Incorrect verification code. After 2 failed attempts, accounts are locked.") - elsif current_request.failed_attempts > 1 + + if current_request.failed_attempts > 1 StateFileArchivedIntakeAccessLog.create!( ip_address: ip_for_irs, event_type: 6, @@ -40,6 +39,7 @@ def update ) current_request.lock_access! redirect_to root_path + return end render :edit end diff --git a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb index af635557fb..f7f8957112 100644 --- a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb @@ -1,6 +1,9 @@ require "rails_helper" RSpec.describe StateFile::ArchivedIntakes::EmailAddressController, type: :controller do + before do + Flipper.enable(:get_your_pdf) + end describe "GET #edit" do it "renders the edit template with a new EmailAddressForm" do get :edit diff --git a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb index 4a2fb1a9c7..0aa653daf8 100644 --- a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb @@ -1,3 +1,5 @@ +require "rails_helper" + RSpec.describe StateFile::ArchivedIntakes::VerificationCodeController, type: :controller do let(:current_request) { create(:state_file_archived_intake_request, failed_attempts: 0) } let(:email_address) { "test@example.com" } @@ -5,13 +7,14 @@ let(:invalid_verification_code) { "654321" } before do + Flipper.enable(:get_your_pdf) allow(controller).to receive(:current_request).and_return(current_request) allow(current_request).to receive(:email_address).and_return(email_address) allow(I18n).to receive(:locale).and_return(:en) end describe "GET #edit" do - it "initializes a new VerificationCodeForm and queues a job to send the verification code" do + it "renders the edit template with a new VerificationCodeForm and queues a job" do expect(ArchivedIntakeEmailVerificationCodeJob).to receive(:perform_later).with( email_address: email_address, locale: :en @@ -26,7 +29,7 @@ end describe "POST #update" do - context "with valid verification code" do + context "with a valid verification code" do before do allow_any_instance_of(StateFile::ArchivedIntakes::VerificationCodeForm).to receive(:valid?).and_return(true) end @@ -37,14 +40,13 @@ }.to change(StateFileArchivedIntakeAccessLog, :count).by(1) log = StateFileArchivedIntakeAccessLog.last - expect(log.event_type).to eq(1) - + expect(log.event_type).to eq("correct_email_code") expect(current_request.failed_attempts).to eq(0) expect(response).to redirect_to(root_path) end end - context "with invalid verification code" do + context "with an invalid verification code" do before do allow_any_instance_of(StateFile::ArchivedIntakes::VerificationCodeForm).to receive(:valid?).and_return(false) end @@ -55,7 +57,7 @@ }.to change(StateFileArchivedIntakeAccessLog, :count).by(1) log = StateFileArchivedIntakeAccessLog.last - expect(log.event_type).to eq(2) + expect(log.event_type).to eq("incorrect_email_code") expect(current_request.reload.failed_attempts).to eq(1) expect(assigns(:form)).to be_a(StateFile::ArchivedIntakes::VerificationCodeForm) @@ -70,10 +72,10 @@ }.to change(StateFileArchivedIntakeAccessLog, :count).by(2) # One for failure, one for lock log = StateFileArchivedIntakeAccessLog.last - expect(log.event_type).to eq(6) # Account locked event + expect(log.event_type).to eq("client_lockout_begin") expect(current_request.reload.failed_attempts).to eq(2) - expect(current_request.reload.locked?).to be_truthy + expect(current_request.reload.access_locked?).to be_truthy expect(response).to redirect_to(root_path) end end diff --git a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb index df093310b6..a2985b72e4 100644 --- a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb +++ b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb @@ -2,20 +2,49 @@ RSpec.describe StateFile::ArchivedIntakes::VerificationCodeForm do describe "#valid?" do - context "when the verification code is present" do + context "when the verification code is present and valid" do it "returns true" do - form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + allow(VerificationCodeService).to receive(:hash_verification_code_with_contact_info) + .with("test@example.com", "123456") + .and_return("hashed_code") + + allow(EmailAccessToken).to receive_message_chain(:lookup, :exists?).and_return(true) + + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "123456" }, + email_address: "test@example.com" + ) expect(form.valid?).to be true end end + context "when the verification code is present but invalid" do + it "adds an error and returns false" do + allow(VerificationCodeService).to receive(:hash_verification_code_with_contact_info) + .with("test@example.com", "123456") + .and_return("hashed_code") + + allow(EmailAccessToken).to receive_message_chain(:lookup, :exists?).and_return(false) + + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "123456" }, + email_address: "test@example.com" + ) + + expect(form.valid?).to be false + expect(form.errors[:verification_code]).to include("Incorrect verification code. After 2 failed attempts, accounts are locked.") + end + end + context "when the verification code is blank" do - it "returns false" do - form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "") + it "adds a presence error and returns false" do + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "" }, + email_address: "test@example.com" + ) expect(form.valid?).to be false - expect(form.errors[:verification_code]).to include("Can't be blank.") end end end @@ -23,7 +52,16 @@ describe "#save" do context "when the form is valid" do it "returns true" do - form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + allow(VerificationCodeService).to receive(:hash_verification_code_with_contact_info) + .with("test@example.com", "123456") + .and_return("hashed_code") + + allow(EmailAccessToken).to receive_message_chain(:lookup, :exists?).and_return(true) + + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "123456" }, + email_address: "test@example.com" + ) expect(form.save).to be true end @@ -31,7 +69,16 @@ context "when the form is invalid" do it "returns false" do - form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "") + allow(VerificationCodeService).to receive(:hash_verification_code_with_contact_info) + .with("test@example.com", "") + .and_return("hashed_code") + + allow(EmailAccessToken).to receive_message_chain(:lookup, :exists?).and_return(false) + + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "" }, + email_address: "test@example.com" + ) expect(form.save).to be false end @@ -40,9 +87,13 @@ describe "#initialize" do it "assigns attributes correctly" do - form = StateFile::ArchivedIntakes::VerificationCodeForm.new(verification_code: "123456") + form = StateFile::ArchivedIntakes::VerificationCodeForm.new( + { verification_code: "123456" }, + email_address: "test@example.com" + ) expect(form.verification_code).to eq("123456") + expect(form.email_address).to eq("test@example.com") end end end From a6edbfd7faac4e6d3a0d263274e140c6fedb70c2 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 9 Jan 2025 16:18:36 -0800 Subject: [PATCH 30/42] remove redunt column for access logs --- .../state_file/archived_intakes/email_address_controller.rb | 1 - app/models/state_file_archived_intake_access_log.rb | 1 - ...241227174414_create_state_file_archived_intake_access_logs.rb | 1 - db/schema.rb | 1 - spec/factories/state_file_archived_intake_access_logs.rb | 1 - spec/models/state_file_archived_intake_access_log_spec.rb | 1 - 6 files changed, 6 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 81c300c6ba..22dbc78e82 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -14,7 +14,6 @@ def update request = StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs, state_file_archived_intakes_id: archived_intake&.id ) StateFileArchivedIntakeAccessLog.create!( ip_address: ip_for_irs, - details: { email_address: @form.email_address }, event_type: 0, state_file_archived_intake_request: request ) diff --git a/app/models/state_file_archived_intake_access_log.rb b/app/models/state_file_archived_intake_access_log.rb index 71f41b7af5..e8b6a045f4 100644 --- a/app/models/state_file_archived_intake_access_log.rb +++ b/app/models/state_file_archived_intake_access_log.rb @@ -5,7 +5,6 @@ # id :bigint not null, primary key # details :jsonb # event_type :integer -# ip_address :string # created_at :datetime not null # updated_at :datetime not null # state_file_archived_intake_request_id :bigint diff --git a/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb b/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb index 0462ef3a36..9a0b9c385b 100644 --- a/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb +++ b/db/migrate/20241227174414_create_state_file_archived_intake_access_logs.rb @@ -3,7 +3,6 @@ def change create_table :state_file_archived_intake_access_logs do |t| t.belongs_to 'state_file_archived_intakes', foreign_key: true t.integer 'event_type' - t.string 'ip_address' t.jsonb 'details', default: '{}' t.timestamps end diff --git a/db/schema.rb b/db/schema.rb index bab3b849e8..693a4a1523 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1687,7 +1687,6 @@ t.datetime "created_at", null: false t.jsonb "details", default: "{}" t.integer "event_type" - t.string "ip_address" t.bigint "state_file_archived_intake_request_id" t.datetime "updated_at", null: false end diff --git a/spec/factories/state_file_archived_intake_access_logs.rb b/spec/factories/state_file_archived_intake_access_logs.rb index b0fded157f..6c094cd6dd 100644 --- a/spec/factories/state_file_archived_intake_access_logs.rb +++ b/spec/factories/state_file_archived_intake_access_logs.rb @@ -5,7 +5,6 @@ # id :bigint not null, primary key # details :jsonb # event_type :integer -# ip_address :string # created_at :datetime not null # updated_at :datetime not null # state_file_archived_intake_request_id :bigint diff --git a/spec/models/state_file_archived_intake_access_log_spec.rb b/spec/models/state_file_archived_intake_access_log_spec.rb index 21100194bb..b65c56e7bd 100644 --- a/spec/models/state_file_archived_intake_access_log_spec.rb +++ b/spec/models/state_file_archived_intake_access_log_spec.rb @@ -5,7 +5,6 @@ # id :bigint not null, primary key # details :jsonb # event_type :integer -# ip_address :string # created_at :datetime not null # updated_at :datetime not null # state_file_archived_intake_request_id :bigint From a75955b8004d60b49d348c81d2a70d6dbd066ff6 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Thu, 9 Jan 2025 16:55:41 -0800 Subject: [PATCH 31/42] update some tests --- .../archived_intake_controller.rb | 7 +++++++ .../email_address_controller.rb | 8 ++------ .../verification_code_controller.rb | 18 +++--------------- .../email_address_controller_spec.rb | 2 -- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/archived_intake_controller.rb b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb index 1f09c3be9e..a3eb16b078 100644 --- a/app/controllers/state_file/archived_intakes/archived_intake_controller.rb +++ b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb @@ -4,6 +4,13 @@ class ArchivedIntakeController < ApplicationController def current_request StateFileArchivedIntakeRequest.where(ip_address: ip_for_irs).order(created_at: :desc).first end + + def create_state_file_access_log(event_type) + StateFileArchivedIntakeAccessLog.create!( + event_type: event_type, + state_file_archived_intake_request: current_request + ) + end end end end diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 22dbc78e82..2fbcf2700c 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -11,12 +11,8 @@ def update if @form.save archived_intake = StateFileArchivedIntake.find_by(email_address: @form.email_address) - request = StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs, state_file_archived_intakes_id: archived_intake&.id ) - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - event_type: 0, - state_file_archived_intake_request: request - ) + StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs, state_file_archived_intakes_id: archived_intake&.id ) + create_state_file_access_log(0) redirect_to state_file_archived_intakes_edit_verification_code_path else diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index c568704a95..c232d82172 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -16,27 +16,15 @@ def update @form = VerificationCodeForm.new(verification_code_form_params, email_address: current_request.email_address) if @form.valid? - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - event_type: 1, - state_file_archived_intake_request: current_request - ) + create_state_file_access_log(1) redirect_to root_path else - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - event_type: 2, - state_file_archived_intake_request: current_request - ) + create_state_file_access_log(2) current_request.increment!(:failed_attempts) if current_request.failed_attempts > 1 - StateFileArchivedIntakeAccessLog.create!( - ip_address: ip_for_irs, - event_type: 6, - state_file_archived_intake_request: current_request - ) + create_state_file_access_log(6) current_request.lock_access! redirect_to root_path return diff --git a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb index f7f8957112..84a0cd9d4d 100644 --- a/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/email_address_controller_spec.rb @@ -37,7 +37,6 @@ expect(request.state_file_archived_intakes_id).to eq(archived_intake.id) log = StateFileArchivedIntakeAccessLog.last - expect(log.ip_address).to eq(ip_address) expect(log.state_file_archived_intake_request_id).to eq(request.id) expect(log.event_type).to eq("issued_email_challenge") @@ -60,7 +59,6 @@ expect(request.state_file_archived_intakes_id).to eq(nil) log = StateFileArchivedIntakeAccessLog.last - expect(log.ip_address).to eq(ip_address) expect(log.state_file_archived_intake_request_id).to eq(request.id) expect(log.event_type).to eq("issued_email_challenge") From b5ec8d3a15c9a6c1c71d3565f91aba30fafae855 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 09:42:55 -0800 Subject: [PATCH 32/42] remove a save and open --- .../archived_intakes/verification_code_controller.rb | 5 ++--- app/models/state_file_archived_intake_request.rb | 12 +++++++++++- .../archived_intakes/verification_code_form_spec.rb | 1 + spec/support/helpers/state_file_intake_helper.rb | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index c232d82172..3aa955cf71 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -3,7 +3,6 @@ module ArchivedIntakes class VerificationCodeController < ArchivedIntakeController before_action :check_feature_flag def edit - @form = VerificationCodeForm.new(email_address: current_request.email_address) @email_address = current_request.email_address ArchivedIntakeEmailVerificationCodeJob.perform_later( @@ -17,11 +16,11 @@ def update if @form.valid? create_state_file_access_log(1) - + current_request.reset_failed_attempts! redirect_to root_path else create_state_file_access_log(2) - current_request.increment!(:failed_attempts) + current_request.increment_failed_attempts if current_request.failed_attempts > 1 create_state_file_access_log(6) diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb index 6ef46d16f8..bfe17825cf 100644 --- a/app/models/state_file_archived_intake_request.rb +++ b/app/models/state_file_archived_intake_request.rb @@ -23,7 +23,9 @@ class StateFileArchivedIntakeRequest < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable - devise :lockable, :timeoutable, :trackable + devise :lockable, :timeoutable, :trackable, + lock_strategy: :failed_attempts, + unlock_strategy: :time has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' @@ -34,4 +36,12 @@ def lock_strategy def unlock_strategy :time end + + def self.maximum_attempts + 2 + end + + def self.unlock_in + 30.minutes + end end diff --git a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb index a2985b72e4..c327ceb0b4 100644 --- a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb +++ b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb @@ -45,6 +45,7 @@ ) expect(form.valid?).to be false + expect(form.errors[:verification_code]).to include("can't be blank") end end end diff --git a/spec/support/helpers/state_file_intake_helper.rb b/spec/support/helpers/state_file_intake_helper.rb index e070e47009..856f65f5c1 100644 --- a/spec/support/helpers/state_file_intake_helper.rb +++ b/spec/support/helpers/state_file_intake_helper.rb @@ -92,7 +92,7 @@ def step_through_initial_authentication(contact_preference: :text_message) expect(page).to have_text "Enter your email address" fill_in I18n.t("state_file.questions.email_address.edit.email_address_label"), with: "someone@example.com" click_on "Send code" - save_and_open_page + expect(page).to have_text "We’ve sent your code to someone@example.com" perform_enqueued_jobs From 48a8f45ee244e157915f15a05d89baa675b0105c Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 10:02:53 -0800 Subject: [PATCH 33/42] fixes a test --- .../archived_intakes/verification_code_form_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb index c327ceb0b4..3bce7d1a55 100644 --- a/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb +++ b/spec/forms/state_file/archived_intakes/verification_code_form_spec.rb @@ -38,14 +38,14 @@ end context "when the verification code is blank" do - it "adds a presence error and returns false" do + it "adds an error and returns false" do form = StateFile::ArchivedIntakes::VerificationCodeForm.new( { verification_code: "" }, email_address: "test@example.com" ) expect(form.valid?).to be false - expect(form.errors[:verification_code]).to include("can't be blank") + expect(form.errors[:verification_code]).to include("Incorrect verification code. After 2 failed attempts, accounts are locked.") end end end From ad8f820831da78419c4a939c994eeb94c500c9e3 Mon Sep 17 00:00:00 2001 From: jey Date: Fri, 10 Jan 2025 12:22:40 -0800 Subject: [PATCH 34/42] Add data backfill task for StateFileArchivedIntake (#5305) --- .../state_file/ty23_archiver_service.rb | 87 +++++++++++ lib/tasks/state_file_archive_intakes.rake | 27 ++++ spec/factories/state_file_az_intakes.rb | 22 +++ spec/factories/state_file_ny_intakes.rb | 22 +++ .../state_file/ty23_archiver_service_spec.rb | 139 ++++++++++++++++++ 5 files changed, 297 insertions(+) create mode 100644 app/services/state_file/ty23_archiver_service.rb create mode 100644 lib/tasks/state_file_archive_intakes.rake create mode 100644 spec/services/state_file/ty23_archiver_service_spec.rb diff --git a/app/services/state_file/ty23_archiver_service.rb b/app/services/state_file/ty23_archiver_service.rb new file mode 100644 index 0000000000..bfc0c694a3 --- /dev/null +++ b/app/services/state_file/ty23_archiver_service.rb @@ -0,0 +1,87 @@ +module StateFile + class Ty23ArchiverService + INTAKE_MAP = { + :az => StateFileAzIntake, + :ny => StateFileNyIntake, + }.freeze + + attr_reader :state_code, :batch_size, :data_source, :tax_year, :current_batch, :cutoff + + def initialize(state_code:, batch_size: 100, cutoff: '2025-01-01') + @state_code = state_code + @batch_size = batch_size + @data_source = INTAKE_MAP[state_code.to_sym] + @tax_year = 2023 + @cutoff = cutoff + @current_batch = nil + raise ArgumentError, "#{state_code} isn't an archiveable state. Expected one of #{INTAKE_MAP.keys.join(', ')}" unless data_source + end + + def find_archiveables + query_result = ActiveRecord::Base.connection.exec_query(query_archiveable_intakes) + @current_batch = query_result.as_json + Rails.logger.info("Found #{current_batch.count} #{data_source.name.pluralize} to archive.") + end + + def archive_batch + archived_ids = [] + current_batch&.each do |batch_data| + archived_intake = StateFileArchivedIntake.new(hashed_ssn: batch_data['hashed_ssn']) + archived_intake.state_code = state_code + archived_intake.tax_year = tax_year + + source_intake = data_source.find(batch_data['intake_id']) + archived_intake.email_address = source_intake.email_address + archived_intake.mailing_street = source_intake.direct_file_data.mailing_street + archived_intake.mailing_apartment = source_intake.direct_file_data.mailing_apartment + archived_intake.mailing_city = source_intake.direct_file_data.mailing_city + archived_intake.mailing_state = source_intake.direct_file_data.mailing_state + archived_intake.mailing_zip = source_intake.direct_file_data.mailing_zip + + if source_intake.submission_pdf.attached? + archived_intake.submission_pdf.attach(source_intake.submission_pdf.blob) + else + Rails.logger.warn("No submission pdf attached to intake #{batch_data['intake_id']}. Continuing with batch.") + end + + archived_intake.save! + archived_ids << batch_data['intake_id'] + rescue StandardError => e + Rails.logger.warn("Caught exception #{e} for #{batch_data}. Continuing with batch.") + next + end + Rails.logger.info("Archived #{archived_ids.count} #{data_source.name.pluralize}: [#{archived_ids.join(', ')}]") + @current_batch = nil # reset the batch + archived_ids + end + + def query_archiveable_intakes + <<~SQL + SELECT + id AS intake_id, hashed_ssn + FROM + #{data_source.table_name} + WHERE id IN ( + SELECT + efs.data_source_id + FROM + efile_submission_transitions est + LEFT JOIN efile_submissions efs ON efs.ID = est.efile_submission_id + WHERE + est.most_recent = TRUE + AND est.to_state = 'accepted' + AND est.created_at < '#{cutoff}' + AND efs.data_source_type = '#{data_source}' + ORDER BY + efs.data_source_id ASC + ) + AND hashed_ssn NOT IN ( + SELECT hashed_ssn + FROM state_file_archived_intakes + WHERE state_code = '#{state_code}' and tax_year = #{tax_year} + ) + LIMIT #{batch_size} + SQL + end + end +end diff --git a/lib/tasks/state_file_archive_intakes.rake b/lib/tasks/state_file_archive_intakes.rake new file mode 100644 index 0000000000..0b1bef637a --- /dev/null +++ b/lib/tasks/state_file_archive_intakes.rake @@ -0,0 +1,27 @@ +namespace :state_file do + namespace :ty23 do + desc 'find archiveable az intakes and create their archival record' + task archive_az_intakes: :environment do + Rails.logger = Logger.new($stdout) + batch_size = 10 # we batch these since archiving involves copying the submission pdf to a new location in s3 + archiver = StateFile::Ty23ArchiverService.new(state_code: 'az', batch_size: batch_size) + archiver.find_archiveables # sets `current_batch` on the archiver instance + while archiver.current_batch.count.positive? # keep archiving, in batches, until the archiver doesn't find anything else + archiver.archive_batch # process the batch + archiver.find_archiveables # set the next batch + end + end + + desc 'find archiveable ny intakes and create their archival record' + task archive_ny_intakes: :environment do + Rails.logger = Logger.new($stdout) + batch_size = 10 # we batch these since archiving involves copying the submission pdf to a new location in s3 + archiver = StateFile::Ty23ArchiverService.new(state_code: 'ny', batch_size: batch_size) + archiver.find_archiveables # sets `current_batch` on the archiver instance + while archiver.current_batch.count.positive? # keep archiving, in batches, until the archiver doesn't find anything else + archiver.archive_batch # process the batch + archiver.find_archiveables # set the next batch + end + end + end +end diff --git a/spec/factories/state_file_az_intakes.rb b/spec/factories/state_file_az_intakes.rb index 49ab5e0883..95b4353cdd 100644 --- a/spec/factories/state_file_az_intakes.rb +++ b/spec/factories/state_file_az_intakes.rb @@ -281,5 +281,27 @@ raw_direct_file_data { StateFile::DirectFileApiResponseSampleService.new.read_xml('az_atticus_itin_single') } raw_direct_file_intake_data { StateFile::DirectFileApiResponseSampleService.new.read_json('az_atticus_itin_single') } end + + trait :with_mailing_address do + after(:build) do |intake| + intake.direct_file_data.mailing_street = "321 Main St" + intake.direct_file_data.mailing_apartment = "Apt 2" + intake.direct_file_data.mailing_city = "Springfield" + intake.direct_file_data.mailing_state = "AZ" + intake.direct_file_data.mailing_zip = "12345" + intake.update!(raw_direct_file_data: intake.direct_file_data.to_s) + end + end + + trait :with_submission_pdf do + test_pdf = Rails.root.join("spec", "fixtures", "files", "document_bundle.pdf") + after(:build) do |intake| + intake.submission_pdf.attach( + io: File.open(test_pdf), + filename: "test.pdf", + content_type: 'application/pdf' + ) + end + end end end diff --git a/spec/factories/state_file_ny_intakes.rb b/spec/factories/state_file_ny_intakes.rb index 02c740b46f..f7c46ec3bd 100644 --- a/spec/factories/state_file_ny_intakes.rb +++ b/spec/factories/state_file_ny_intakes.rb @@ -242,5 +242,27 @@ raw_direct_file_data { StateFile::DirectFileApiResponseSampleService.new.read_xml('ny_bloombito_w2s') } raw_direct_file_intake_data { StateFile::DirectFileApiResponseSampleService.new.read_json('ny_bloombito_w2s') } end + + trait :with_mailing_address do + after(:build) do |intake| + intake.direct_file_data.mailing_street = "321 Main St" + intake.direct_file_data.mailing_apartment = "Apt 2" + intake.direct_file_data.mailing_city = "Springfield" + intake.direct_file_data.mailing_state = "NY" + intake.direct_file_data.mailing_zip = "12345" + intake.update!(raw_direct_file_data: intake.direct_file_data.to_s) + end + end + + trait :with_submission_pdf do + test_pdf = Rails.root.join("spec", "fixtures", "files", "document_bundle.pdf") + after(:build) do |intake| + intake.submission_pdf.attach( + io: File.open(test_pdf), + filename: "test.pdf", + content_type: 'application/pdf' + ) + end + end end end diff --git a/spec/services/state_file/ty23_archiver_service_spec.rb b/spec/services/state_file/ty23_archiver_service_spec.rb new file mode 100644 index 0000000000..72ae775c9d --- /dev/null +++ b/spec/services/state_file/ty23_archiver_service_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require "rails_helper" +require 'json' + +RSpec.describe StateFile::Ty23ArchiverService do + + describe '#find_archiveables' do + %w[az ny].each do |state_code| + + context 'when there are accepted intakes to archive' do + let(:archiver) { described_class.new(state_code: state_code) } + let(:intake1) { create(archiver.data_source.table_name.singularize, created_at: Date.parse("1/5/23"), hashed_ssn: "fake hashed ssn1") } + let(:intake2) { create(archiver.data_source.table_name.singularize, created_at: Date.parse("1/5/23"), hashed_ssn: "fake hashed ssn2") } + let(:submission1) { create(:efile_submission, :for_state, :accepted, data_source: intake1, created_at: Date.parse("1/5/23")) } + let(:submission2) { create(:efile_submission, :for_state, :accepted, data_source: intake2, created_at: Date.parse("1/5/23")) } + + before do + submission1.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + submission2.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + end + + it 'finds them and sets them as the current batch' do + archiver.find_archiveables + expect(archiver.current_batch.count).to eq(2) + expect(archiver.current_batch[0]['intake_id']).to eq intake1.id + expect(archiver.current_batch[0]['hashed_ssn']).to eq intake1.hashed_ssn + expect(archiver.current_batch[1]['intake_id']).to eq intake2.id + expect(archiver.current_batch[1]['hashed_ssn']).to eq intake2.hashed_ssn + end + end + + context 'when there are only non-accepted submissions' do + let(:archiver) { described_class.new(state_code: state_code) } + let!(:intake) { create("state_file_#{state_code}_intake".to_sym, created_at: Date.parse("1/5/23"), hashed_ssn: "fake hashed ssn") } + let!(:rejected_submission) { create(:efile_submission, :for_state, :rejected, data_source: intake, created_at: Date.parse("1/5/23")) } + let!(:resubmitted_submission) { create(:efile_submission, :for_state, :resubmitted, data_source: intake, created_at: Date.parse("1/5/23")) } + let!(:cancelled_submission) { create(:efile_submission, :for_state, :cancelled, data_source: intake, created_at: Date.parse("1/5/23")) } + let!(:waiting_submission) { create(:efile_submission, :for_state, :waiting, data_source: intake, created_at: Date.parse("1/5/23")) } + + before do + rejected_submission.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + resubmitted_submission.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + cancelled_submission.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + waiting_submission.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + end + + it 'makes an empty current batch' do + archiver.find_archiveables + expect(archiver.current_batch.count).to eq(0) + end + end + + context 'when a submission has already been archived' do + let(:archiver) { described_class.new(state_code: state_code) } + let(:intake) { create(archiver.data_source.table_name.singularize, created_at: Date.parse("1/5/23"), hashed_ssn: "fake hashed ssn") } + let(:submission) { create(:efile_submission, :for_state, :accepted, data_source: intake, created_at: Date.parse("1/5/23")) } + let!(:archived_intake) { create(:state_file_archived_intake, hashed_ssn: "fake hashed ssn", state_code: state_code, tax_year: archiver.tax_year) } + + before do + submission.efile_submission_transitions.last.update(created_at: Date.parse("1/5/23")) + end + + it 'does not add it to the archiveable batch' do + archiver.find_archiveables + expect(archiver.current_batch.count).to eq(0) + end + end + end + end + + describe '#archive_batch' do + %w[az ny].each do |state_code| + describe 'when there is a current batch to archive' do + let(:archiver) { described_class.new(state_code: state_code, batch_size: 5) } + let!(:intake1) { + create(archiver.data_source.table_name.singularize, :with_mailing_address, :with_submission_pdf, + hashed_ssn: "fake hashed ssn1", email_address: "fake1@email.com") + } + let!(:intake2) { + create(archiver.data_source.table_name.singularize, :with_mailing_address, :with_submission_pdf, + hashed_ssn: "fake hashed ssn2", email_address: "fake2@email.com") + } + let(:mock_batch) { + [ + { :intake_id => intake1.id, :hashed_ssn => intake1.hashed_ssn }, + { :intake_id => intake2.id, :hashed_ssn => intake2.hashed_ssn }, + ].as_json + } + + before do + archiver.instance_variable_set(:@current_batch, mock_batch) + end + + it 'creates an archived intake for each intake in the batch' do + archived_ids = archiver.archive_batch + expect(archived_ids.count).to eq(mock_batch.count) + + archived_ids.each do |archived_id| + source_intake = archiver.data_source.find(archived_id) + matching_archived_intakes = StateFileArchivedIntake.where( + hashed_ssn: source_intake.hashed_ssn, state_code: archiver.state_code, tax_year: archiver.tax_year + ) + + # Verify there is exactly one archived intake for each source intake + expect(matching_archived_intakes.count).to eq(1) + archived_intake = matching_archived_intakes.first + + # Verify the email and mailing address information is populated correctly on the archived intake + expect(archived_intake&.email_address).to eq(source_intake.email_address) + expect(archived_intake&.mailing_street).to eq(source_intake.direct_file_data.mailing_street) + expect(archived_intake&.mailing_apartment).to eq(source_intake.direct_file_data.mailing_apartment) + expect(archived_intake&.mailing_city).to eq(source_intake.direct_file_data.mailing_city) + expect(archived_intake&.mailing_state).to eq(source_intake.direct_file_data.mailing_state) + expect(archived_intake&.mailing_zip).to eq(source_intake.direct_file_data.mailing_zip) + + # Verify that the PDF is attached to the archived intake and matches the source pdf + expect(archived_intake&.submission_pdf&.download).to eq(source_intake.submission_pdf.download) + expect(archived_intake&.submission_pdf&.filename).to eq(source_intake.submission_pdf.filename) + expect(archived_intake&.submission_pdf&.content_type).to eq(source_intake.submission_pdf.content_type) + + # Ensure the PDF remains attached to the source intake + expect(source_intake.submission_pdf.attached?).to be true + end + end + end + + describe 'when there is no batch' do + let(:archiver) { described_class.new(state_code: state_code, batch_size: 5) } + + it 'quietly archives nothing' do + expect { + archiver.archive_batch + }.not_to change(StateFileArchivedIntake, :count) + end + end + end + end +end From 72af870f198dab85f3c5e0b8a08aada13459a93b Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 12:34:32 -0800 Subject: [PATCH 35/42] wip --- .../archived_intake_controller.rb | 4 ++-- .../email_address_controller.rb | 1 + .../verification_code_controller.rb | 3 ++- .../state_file_archived_intake_request.rb | 23 ++++++------------- app/models/state_file_base_intake.rb | 2 +- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/archived_intake_controller.rb b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb index a3eb16b078..da3f6cc9fd 100644 --- a/app/controllers/state_file/archived_intakes/archived_intake_controller.rb +++ b/app/controllers/state_file/archived_intakes/archived_intake_controller.rb @@ -2,7 +2,7 @@ module StateFile module ArchivedIntakes class ArchivedIntakeController < ApplicationController def current_request - StateFileArchivedIntakeRequest.where(ip_address: ip_for_irs).order(created_at: :desc).first + StateFileArchivedIntakeRequest.find_by(ip_address: ip_for_irs, email_address: session[:email_address]) end def create_state_file_access_log(event_type) @@ -13,4 +13,4 @@ def create_state_file_access_log(event_type) end end end -end +end \ No newline at end of file diff --git a/app/controllers/state_file/archived_intakes/email_address_controller.rb b/app/controllers/state_file/archived_intakes/email_address_controller.rb index 2fbcf2700c..4f69c7f025 100644 --- a/app/controllers/state_file/archived_intakes/email_address_controller.rb +++ b/app/controllers/state_file/archived_intakes/email_address_controller.rb @@ -11,6 +11,7 @@ def update if @form.save archived_intake = StateFileArchivedIntake.find_by(email_address: @form.email_address) + session[:email_address] = @form.email_address StateFileArchivedIntakeRequest.find_or_create_by(email_address: @form.email_address, ip_address: ip_for_irs, state_file_archived_intakes_id: archived_intake&.id ) create_state_file_access_log(0) diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index 3aa955cf71..a0d1b301e1 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -21,7 +21,8 @@ def update else create_state_file_access_log(2) current_request.increment_failed_attempts - + current_request.lock_access! + binding.pry if current_request.failed_attempts > 1 create_state_file_access_log(6) current_request.lock_access! diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb index bfe17825cf..d0c9d26d55 100644 --- a/app/models/state_file_archived_intake_request.rb +++ b/app/models/state_file_archived_intake_request.rb @@ -23,25 +23,16 @@ class StateFileArchivedIntakeRequest < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable - devise :lockable, :timeoutable, :trackable, - lock_strategy: :failed_attempts, - unlock_strategy: :time + devise :lockable, :timeoutable, :trackable + # devise :timeoutable, :timeout_in => 2.minutes, :unlock_strategy => :time - has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' - - def lock_strategy - :failed_attempts - end - def unlock_strategy - :time - end + # devise :lockable, :maximum_attempts => 2 - def self.maximum_attempts - 2 - end + has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' - def self.unlock_in - 30.minutes + def lockable + self.unlock_in = 2.minutes + self.unlock_strategy = :time end end diff --git a/app/models/state_file_base_intake.rb b/app/models/state_file_base_intake.rb index a40409aef1..268ca267a9 100644 --- a/app/models/state_file_base_intake.rb +++ b/app/models/state_file_base_intake.rb @@ -18,7 +18,7 @@ class StateFileBaseIntake < ApplicationRecord accepts_nested_attributes_for :primary_state_id, :spouse_state_id scope :accessible_intakes, -> { all } - devise :timeoutable, :timeout_in => 15.minutes, :unlock_strategy => :time + devise :timeoutable, :timeout_in => 15.minutes, :unlock_strategy => :time validates :email_address, 'valid_email_2/email': true validates :phone_number, allow_blank: true, e164_phone: true From 2daf9d26484eb2b6be7a10d90e2147dbda298729 Mon Sep 17 00:00:00 2001 From: Anisha Ramnani Date: Fri, 10 Jan 2025 16:45:53 -0500 Subject: [PATCH 36/42] Add Lockable Devise Attributes to State File Archived Requests --- .../verification_code_controller.rb | 9 +++++---- .../state_file_archived_intake_request.rb | 20 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/controllers/state_file/archived_intakes/verification_code_controller.rb b/app/controllers/state_file/archived_intakes/verification_code_controller.rb index a0d1b301e1..0886525f9c 100644 --- a/app/controllers/state_file/archived_intakes/verification_code_controller.rb +++ b/app/controllers/state_file/archived_intakes/verification_code_controller.rb @@ -3,6 +3,10 @@ module ArchivedIntakes class VerificationCodeController < ArchivedIntakeController before_action :check_feature_flag def edit + if current_request.access_locked? + redirect_to root_path + return + end @form = VerificationCodeForm.new(email_address: current_request.email_address) @email_address = current_request.email_address ArchivedIntakeEmailVerificationCodeJob.perform_later( @@ -21,11 +25,8 @@ def update else create_state_file_access_log(2) current_request.increment_failed_attempts - current_request.lock_access! - binding.pry - if current_request.failed_attempts > 1 + if current_request.access_locked? create_state_file_access_log(6) - current_request.lock_access! redirect_to root_path return end diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb index d0c9d26d55..93be208e04 100644 --- a/app/models/state_file_archived_intake_request.rb +++ b/app/models/state_file_archived_intake_request.rb @@ -22,17 +22,17 @@ # class StateFileArchivedIntakeRequest < ApplicationRecord # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable - devise :lockable, :timeoutable, :trackable - # devise :timeoutable, :timeout_in => 2.minutes, :unlock_strategy => :time - - - # devise :lockable, :maximum_attempts => 2 - + devise :lockable, unlock_in: 1.minutes, unlock_strategy: :time has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' - def lockable - self.unlock_in = 2.minutes - self.unlock_strategy = :time + def self.maximum_attempts + 2 + end + + def increment_failed_attempts + super + if attempts_exceeded? && !access_locked? + lock_access! + end end end From 520602363a4f60c4a2bc85b0ad9c649161a608bc Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 13:57:31 -0800 Subject: [PATCH 37/42] update lockout time to 1 hour --- app/models/state_file_archived_intake_request.rb | 2 +- .../archived_intake/verification_code_controller_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/state_file_archived_intake_request.rb b/app/models/state_file_archived_intake_request.rb index 93be208e04..cd1666add2 100644 --- a/app/models/state_file_archived_intake_request.rb +++ b/app/models/state_file_archived_intake_request.rb @@ -22,7 +22,7 @@ # class StateFileArchivedIntakeRequest < ApplicationRecord # Include default devise modules. Others available are: - devise :lockable, unlock_in: 1.minutes, unlock_strategy: :time + devise :lockable, unlock_in: 60.minutes, unlock_strategy: :time has_many :access_logs, class_name: 'StateFileArchivedIntakeAccessLog' def self.maximum_attempts diff --git a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb index 0aa653daf8..d984941885 100644 --- a/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb +++ b/spec/controllers/state_file/archived_intake/verification_code_controller_spec.rb @@ -34,7 +34,7 @@ allow_any_instance_of(StateFile::ArchivedIntakes::VerificationCodeForm).to receive(:valid?).and_return(true) end - it "creates a success access log, redirects to root path, and does not increment failed_attempts" do + it "creates a success access log and does not increment failed_attempts" do expect { post :update, params: { state_file_archived_intakes_verification_code_form: { verification_code: valid_verification_code } } }.to change(StateFileArchivedIntakeAccessLog, :count).by(1) @@ -69,7 +69,7 @@ expect { post :update, params: { state_file_archived_intakes_verification_code_form: { verification_code: invalid_verification_code } } - }.to change(StateFileArchivedIntakeAccessLog, :count).by(2) # One for failure, one for lock + }.to change(StateFileArchivedIntakeAccessLog, :count).by(2) log = StateFileArchivedIntakeAccessLog.last expect(log.event_type).to eq("client_lockout_begin") From d357bbc4d66dd9d3769c55c0c16b240f2090e8a8 Mon Sep 17 00:00:00 2001 From: Martha Pidcock Date: Fri, 10 Jan 2025 13:59:04 -0800 Subject: [PATCH 38/42] annotate --- app/models/state_file1099_g.rb | 1 - spec/factories/state_file1099_gs.rb | 1 - spec/models/state_file1099_g_spec.rb | 1 - 3 files changed, 3 deletions(-) diff --git a/app/models/state_file1099_g.rb b/app/models/state_file1099_g.rb index 99d8f88aa8..af47b33a1d 100644 --- a/app/models/state_file1099_g.rb +++ b/app/models/state_file1099_g.rb @@ -14,7 +14,6 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string -# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string diff --git a/spec/factories/state_file1099_gs.rb b/spec/factories/state_file1099_gs.rb index c5f40e4ae9..32f38dee93 100644 --- a/spec/factories/state_file1099_gs.rb +++ b/spec/factories/state_file1099_gs.rb @@ -14,7 +14,6 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string -# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string diff --git a/spec/models/state_file1099_g_spec.rb b/spec/models/state_file1099_g_spec.rb index 5993f5f5af..0e6395c3df 100644 --- a/spec/models/state_file1099_g_spec.rb +++ b/spec/models/state_file1099_g_spec.rb @@ -14,7 +14,6 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string -# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string From dc36bc66cd89af08b17c191f950c64d34fe60ec2 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 14:03:33 -0800 Subject: [PATCH 39/42] remove uneeded change --- app/forms/state_file/email_address_form.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/forms/state_file/email_address_form.rb b/app/forms/state_file/email_address_form.rb index 6658c7e88e..d38abf08b4 100644 --- a/app/forms/state_file/email_address_form.rb +++ b/app/forms/state_file/email_address_form.rb @@ -9,4 +9,4 @@ def save @intake.update(attributes_for(:intake)) end end -end +end \ No newline at end of file From aea04334a72c5707b39f5089a7b26085fbcc449a Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 16:25:37 -0800 Subject: [PATCH 40/42] update formating --- .../verification_code_form.rb | 2 +- app/models/state_file_base_intake.rb | 6 +- .../email_address/edit.html.erb | 27 +++++---- .../verification_code/edit.html.erb | 31 ++++++---- config/locales/en.yml | 4 +- db/schema.rb | 2 - .../archived_intake_controller_spec.rb | 58 +++++++++++++++++++ 7 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 spec/controllers/state_file/archived_intake/archived_intake_controller_spec.rb diff --git a/app/forms/state_file/archived_intakes/verification_code_form.rb b/app/forms/state_file/archived_intakes/verification_code_form.rb index 64f65e89da..78d1f2f5bb 100644 --- a/app/forms/state_file/archived_intakes/verification_code_form.rb +++ b/app/forms/state_file/archived_intakes/verification_code_form.rb @@ -15,7 +15,7 @@ def valid? valid_code = EmailAccessToken.lookup(hashed_verification_code).exists? - errors.add(:verification_code, "Incorrect verification code. After 2 failed attempts, accounts are locked.") unless valid_code + errors.add(:verification_code, I18n.t("state_file.archived_intakes.verification_code.edit.error_message")) unless valid_code valid_code.present? end diff --git a/app/models/state_file_base_intake.rb b/app/models/state_file_base_intake.rb index dd92daf9c9..a40409aef1 100644 --- a/app/models/state_file_base_intake.rb +++ b/app/models/state_file_base_intake.rb @@ -18,7 +18,7 @@ class StateFileBaseIntake < ApplicationRecord accepts_nested_attributes_for :primary_state_id, :spouse_state_id scope :accessible_intakes, -> { all } - devise :timeoutable, :timeout_in => 15.minutes, :unlock_strategy => :time + devise :timeoutable, :timeout_in => 15.minutes, :unlock_strategy => :time validates :email_address, 'valid_email_2/email': true validates :phone_number, allow_blank: true, e164_phone: true @@ -135,8 +135,8 @@ def synchronize_df_w2s_to_database box_14_values[deduction[:other_description]] = deduction[:other_amount] end state_file_w2.assign_attributes( - box14_ui_wf_swf: box_14_values['UIWFSWF'], - box14_ui_hc_wd: box_14_values['UIHCWD'], + box14_ui_wf_swf: box_14_values['UI/WF/SWF'], + box14_ui_hc_wd: box_14_values['UI/HC/WD'], box14_fli: box_14_values['FLI'], box14_stpickup: box_14_values['STPICKUP'], employer_ein: direct_file_w2.EmployerEIN, diff --git a/app/views/state_file/archived_intakes/email_address/edit.html.erb b/app/views/state_file/archived_intakes/email_address/edit.html.erb index 64b85b8a85..f221bc5556 100644 --- a/app/views/state_file/archived_intakes/email_address/edit.html.erb +++ b/app/views/state_file/archived_intakes/email_address/edit.html.erb @@ -1,16 +1,21 @@ <% title = t(".enter_email") %> <% content_for :page_title, title %> -

                  <%= title %>

                  -<%= form_with model: @form, url: state_file_archived_intakes_email_address_path, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %> -
                  - <%= f.cfa_input_field(:email_address, t("state_file.questions.email_address.edit.email_address_label"), help_text: 'example@email.com', classes: ["form-width--long"]) %> -
                  +
                  -outer"> +
                  +
                  +

                  <%= title %>

                  + <%= form_with model: @form, url: state_file_archived_intakes_email_address_path, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %> +
                  + <%= f.cfa_input_field(:email_address, t("state_file.questions.email_address.edit.email_address_label"), help_text: 'example@email.com', classes: ["form-width--long"]) %> +
                  -
                  - +
                  + +
                  + <% end %> +
                  -<% end %> - +
                  diff --git a/app/views/state_file/archived_intakes/verification_code/edit.html.erb b/app/views/state_file/archived_intakes/verification_code/edit.html.erb index dda35fb4c8..658c97964a 100644 --- a/app/views/state_file/archived_intakes/verification_code/edit.html.erb +++ b/app/views/state_file/archived_intakes/verification_code/edit.html.erb @@ -1,14 +1,23 @@ <% title = t(".title_html", email_address: @email_address) %> -<% content_for :page_title, title %> -<%= form_with model: @form, url: { action: :update }, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %> -

                  <%= title %>

                  -

                  <%= t(".subtitle_html") %>

                  -
                  - <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %> +
                  -outer"> +
                  +
                  +
                  + <% content_for :page_title, title %> + <%= form_with model: @form, url: { action: :update }, local: true, method: :patch, builder: VitaMinFormBuilder do |f| %> +

                  <%= title %>

                  +

                  <%= t(".subtitle_html") %>

                  +

                  <%= t(".subtitle_html_2") %>

                  +
                  + <%= f.cfa_input_field(:verification_code, t("state_file.questions.verification_code.edit.verification_code_label"), classes: ["form-width--long"]) %> +
                  +
                  + +
                  + <% end %> +
                  -
                  -
                  -<% end %> \ No newline at end of file +
                  \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 7d8b9f0dfa..7218277dc7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2069,8 +2069,10 @@ en: enter_email: Enter the email address linked to your account verification_code: edit: - subtitle_html: If you didn’t receive a code, please check your spam folder. If you still need help resubscribing, chat with us. + subtitle_html: If you didn’t receive a code, please check your spam folder. + subtitle_html_2: If you still need help resubscribing, chat with us. title_html: We’ve sent your code to %{email_address} + error_message: "Incorrect verification code. After 2 failed attempts, accounts are locked." faq: index: title: Common questions from %{state} taxpayers diff --git a/db/schema.rb b/db/schema.rb index a8dbfa09d3..8695dc3c61 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,8 +11,6 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.1].define(version: 2025_01_08_233940) do - create_schema "analytics" - # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "plpgsql" diff --git a/spec/controllers/state_file/archived_intake/archived_intake_controller_spec.rb b/spec/controllers/state_file/archived_intake/archived_intake_controller_spec.rb new file mode 100644 index 0000000000..299a0f3bac --- /dev/null +++ b/spec/controllers/state_file/archived_intake/archived_intake_controller_spec.rb @@ -0,0 +1,58 @@ +require 'rails_helper' + +describe StateFile::ArchivedIntakes::ArchivedIntakeController, type: :controller do + let(:ip_address) { '192.168.0.1' } + let(:email_address) { 'test@example.com' } + let(:request_instance) { instance_double(StateFileArchivedIntakeRequest) } + + before do + allow(controller).to receive(:ip_for_irs).and_return(ip_address) + allow(session).to receive(:[]).with(:email_address).and_return(email_address) + end + + describe '#current_request' do + it 'finds the StateFileArchivedIntakeRequest by IP and email address' do + expect(StateFileArchivedIntakeRequest).to receive(:find_by).with( + ip_address: ip_address, + email_address: email_address + ).and_return(request_instance) + + expect(controller.current_request).to eq(request_instance) + end + + it 'returns nil if no request is found' do + expect(StateFileArchivedIntakeRequest).to receive(:find_by).with( + ip_address: ip_address, + email_address: email_address + ).and_return(nil) + + expect(controller.current_request).to be_nil + end + end + + describe '#create_state_file_access_log' do + let(:event_type) { 'access_granted' } + let(:access_log_instance) { instance_double(StateFileArchivedIntakeAccessLog) } + + before do + allow(controller).to receive(:current_request).and_return(request_instance) + end + + it 'creates a StateFileArchivedIntakeAccessLog with the correct attributes' do + expect(StateFileArchivedIntakeAccessLog).to receive(:create!).with( + event_type: event_type, + state_file_archived_intake_request: request_instance + ).and_return(access_log_instance) + + controller.create_state_file_access_log(event_type) + end + + it 'raises an error if the log cannot be created' do + allow(StateFileArchivedIntakeAccessLog).to receive(:create!).and_raise(ActiveRecord::RecordInvalid) + + expect { + controller.create_state_file_access_log(event_type) + }.to raise_error(ActiveRecord::RecordInvalid) + end + end +end From e0e9bd18c727a32dd76e45291a06f3d387d2f9cd Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Fri, 10 Jan 2025 16:32:59 -0800 Subject: [PATCH 41/42] annotate --- app/models/state_file1099_g.rb | 1 + spec/factories/state_file1099_gs.rb | 1 + spec/models/state_file1099_g_spec.rb | 1 + 3 files changed, 3 insertions(+) diff --git a/app/models/state_file1099_g.rb b/app/models/state_file1099_g.rb index af47b33a1d..99d8f88aa8 100644 --- a/app/models/state_file1099_g.rb +++ b/app/models/state_file1099_g.rb @@ -14,6 +14,7 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string +# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string diff --git a/spec/factories/state_file1099_gs.rb b/spec/factories/state_file1099_gs.rb index 32f38dee93..c5f40e4ae9 100644 --- a/spec/factories/state_file1099_gs.rb +++ b/spec/factories/state_file1099_gs.rb @@ -14,6 +14,7 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string +# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string diff --git a/spec/models/state_file1099_g_spec.rb b/spec/models/state_file1099_g_spec.rb index 0e6395c3df..5993f5f5af 100644 --- a/spec/models/state_file1099_g_spec.rb +++ b/spec/models/state_file1099_g_spec.rb @@ -14,6 +14,7 @@ # payer_zip :string # recipient :integer default("unfilled"), not null # recipient_city :string +# recipient_state :string # recipient_street_address :string # recipient_street_address_apartment :string # recipient_zip :string From a9218aeace47b48aaa7e3ced1f21b751d194fb01 Mon Sep 17 00:00:00 2001 From: Drew Proebstel Date: Sun, 12 Jan 2025 23:10:29 -0800 Subject: [PATCH 42/42] i18n health --- config/locales/en.yml | 4 ++-- config/locales/es.yml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 7218277dc7..d054bfb7be 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2069,10 +2069,10 @@ en: enter_email: Enter the email address linked to your account verification_code: edit: + error_message: Incorrect verification code. After 2 failed attempts, accounts are locked. subtitle_html: If you didn’t receive a code, please check your spam folder. - subtitle_html_2: If you still need help resubscribing, chat with us. + subtitle_html_2: If you still need help resubscribing, chat with us. title_html: We’ve sent your code to %{email_address} - error_message: "Incorrect verification code. After 2 failed attempts, accounts are locked." faq: index: title: Common questions from %{state} taxpayers diff --git a/config/locales/es.yml b/config/locales/es.yml index 00b097ebd8..ea12e07f5f 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -2021,7 +2021,9 @@ es: enter_email: Ingresa la dirección de correo electrónico vinculada a tu cuenta verification_code: edit: + error_message: Después de 2 intentos fallidos, las cuentas serán bloqueadas. subtitle_html: Si no recibiste un código, revisa tu carpeta de spam. Si aún necesitas ayuda para volver a suscribirte, chatea con nosotros. + subtitle_html_2: Si aún necesitas ayuda para resuscribirte, chatea con nosotros. title_html: Hemos enviado tu código a %{email_address} faq: index: