From c4200e27f01a55773abdc40ffcccebe232bbd5e9 Mon Sep 17 00:00:00 2001 From: Zach Margolis Date: Tue, 5 Apr 2022 14:21:21 -0700 Subject: [PATCH 1/3] download personal key via link or js --- .../packs/personal-key-page-controller.js | 15 +++++++++++++++ app/views/shared/_personal_key.html.erb | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/javascript/packs/personal-key-page-controller.js b/app/javascript/packs/personal-key-page-controller.js index 188dd896d77..e65aa35c564 100644 --- a/app/javascript/packs/personal-key-page-controller.js +++ b/app/javascript/packs/personal-key-page-controller.js @@ -9,6 +9,7 @@ const formEl = document.getElementById('confirm-key'); const input = formEl.querySelector('input[type="text"]'); const modalTrigger = document.querySelector('[data-toggle="modal"]'); const modalDismiss = document.querySelector('[data-dismiss="personal-key-confirm"]'); +const downloadLink = document.querySelector('a[download]'); let isInvalidForm = false; @@ -114,6 +115,20 @@ function hide() { modal.hide(); } +function downloadForIE(event) { + event.preventDefault(); + + const filename = downloadLink.getAttribute('download'); + const data = scrapePersonalKey(); + const blob = new Blob([data], { type: 'text/plain' }); + + window.navigator.msSaveBlob(blob, filename); +} + modalTrigger.addEventListener('click', show); modalDismiss.addEventListener('click', hide); formEl.addEventListener('submit', handleSubmit); + +if (window.navigator.msSaveBlob) { + downloadLink.addEventListener('click', downloadForIE); +} diff --git a/app/views/shared/_personal_key.html.erb b/app/views/shared/_personal_key.html.erb index 833913bc17d..61e507778eb 100644 --- a/app/views/shared/_personal_key.html.erb +++ b/app/views/shared/_personal_key.html.erb @@ -10,7 +10,12 @@ <%= render ButtonComponent.new( action: ->(**tag_options, &block) do - link_to(idv_download_personal_key_path, **tag_options, &block) + link_to( + "data:text/plain;charset=utf-8,#{CGI.escape(code)}", + download: 'personal_key.txt', + **tag_options, + &block + ) end, icon: :file_download, outline: true, From 8f625234ef42116fdc65379bc5075edd18b2d4af Mon Sep 17 00:00:00 2001 From: Zach Margolis Date: Tue, 5 Apr 2022 14:50:28 -0700 Subject: [PATCH 2/3] specs and removal notes --- Gemfile | 1 + Gemfile.lock | 2 ++ .../idv/personal_key_controller.rb | 1 + config/routes.rb | 1 + .../shared/_personal_key.html.erb_spec.rb | 32 +++++++++++++++++++ 5 files changed, 37 insertions(+) create mode 100644 spec/views/shared/_personal_key.html.erb_spec.rb diff --git a/Gemfile b/Gemfile index 910f3069053..12b135de834 100644 --- a/Gemfile +++ b/Gemfile @@ -88,6 +88,7 @@ group :development, :test do gem 'aws-sdk-cloudwatchlogs', require: false gem 'brakeman', require: false gem 'bullet', '>= 6.0.2' + gem 'data_uri', require: false gem 'erb_lint', '~> 0.1.0', require: false gem 'i18n-tasks', '>= 0.9.31' gem 'knapsack' diff --git a/Gemfile.lock b/Gemfile.lock index b6f512a163d..065111e5e41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,6 +211,7 @@ GEM addressable cssbundling-rails (1.0.0) railties (>= 6.0.0) + data_uri (0.1.0) debug_inspector (1.1.0) derailed_benchmarks (1.8.1) benchmark-ips (~> 2) @@ -702,6 +703,7 @@ DEPENDENCIES capybara-selenium (>= 0.0.6) connection_pool cssbundling-rails + data_uri derailed_benchmarks (~> 1.8) devise (~> 4.8) dotiw (>= 4.0.1) diff --git a/app/controllers/idv/personal_key_controller.rb b/app/controllers/idv/personal_key_controller.rb index 341ab7316d4..e54dbb05edf 100644 --- a/app/controllers/idv/personal_key_controller.rb +++ b/app/controllers/idv/personal_key_controller.rb @@ -22,6 +22,7 @@ def update redirect_to next_step end + # Remove this after the next deploy def download personal_key = user_session[:personal_key] diff --git a/config/routes.rb b/config/routes.rb index 93bb582bbed..46cea19738e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -276,6 +276,7 @@ get '/come_back_later' => 'come_back_later#show' get '/personal_key' => 'personal_key#show' post '/personal_key' => 'personal_key#update' + # Remove this after the next deploy get '/download_personal_key' => 'personal_key#download' get '/forgot_password' => 'forgot_password#new' post '/forgot_password' => 'forgot_password#update' diff --git a/spec/views/shared/_personal_key.html.erb_spec.rb b/spec/views/shared/_personal_key.html.erb_spec.rb new file mode 100644 index 00000000000..bff0e986e8e --- /dev/null +++ b/spec/views/shared/_personal_key.html.erb_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' +require 'data_uri' + +RSpec.describe 'shared/_personal_key.html.erb' do + let(:personal_key) { RandomPhrase.new(num_words: 4).to_s } + + describe 'download link' do + around do |ex| + # data_uri depends on URI.decode which was removed in Ruby 3.0 :sob: + module URI + def self.decode(value) + CGI.unescape(value) + end + end + + ex.run + + URI.singleton_class.undef_method(:decode) + end + + it 'has the download attribute and a data: url for the personal key' do + render 'shared/personal_key', code: personal_key, update_path: '/test' + + doc = Nokogiri::HTML(rendered) + download_link = doc.at_css('a[download]') + data_uri = URI::Data.new(download_link[:href]) + + expect(data_uri.content_type).to eq('text/plain') + expect(data_uri.data).to eq(personal_key) + end + end +end From d11f63d710a807187470d776da90dc3535d7d570 Mon Sep 17 00:00:00 2001 From: Zach Margolis Date: Tue, 5 Apr 2022 14:59:05 -0700 Subject: [PATCH 3/3] changelog: Bug Fixes, Personal keys, Fixes downloading personal keys outside of identity verification