diff --git a/app/controllers/reveal_access_token_controller.rb b/app/controllers/reveal_access_token_controller.rb new file mode 100644 index 00000000..c8959afd --- /dev/null +++ b/app/controllers/reveal_access_token_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class RevealAccessTokenController < ApplicationController + def show + authorize!(:manage, current_user.access_token) + end + + def create + authorize!(:manage, current_user.access_token) + + if current_user.valid_password?(params[:password]) + render turbo_stream: turbo_stream.replace(:access_token_container, + partial: 'reveal_access_token/access_token', + locals: { token: current_user.access_token.token }) + else + render turbo_stream: turbo_stream.replace(:modal, template: 'reveal_access_token/show', + locals: { error_message: I18n.t('wrong_password') }), + status: :unprocessable_content + end + end +end diff --git a/app/views/api_settings/index.html.erb b/app/views/api_settings/index.html.erb index c5a761a8..57f6fa16 100644 --- a/app/views/api_settings/index.html.erb +++ b/app/views/api_settings/index.html.erb @@ -11,10 +11,21 @@
<% token = current_user.access_token.token %> - - - - <%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %> + <% obscured_token = current_user.access_token.token.sub(token[5..], '*' * token[5..].size) %> + <% if current_account.testing? %> + + + + <%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %> + <% else %> + + +
+ <%= svg_icon('copy', class: 'w-6 h-6 text-white') %> + +
+
+ <% end %>
<%= button_to button_title(title: t('rotate'), disabled_with: t('rotate'), icon: svg_icon('reload', class: 'w-6 h-6')), settings_api_index_path, class: 'white-button w-full', data: { turbo_confirm: t('remove_existing_api_token_and_generated_a_new_one_are_you_sure_') } %>
diff --git a/app/views/reveal_access_token/_access_token.html.erb b/app/views/reveal_access_token/_access_token.html.erb new file mode 100644 index 00000000..960faf7f --- /dev/null +++ b/app/views/reveal_access_token/_access_token.html.erb @@ -0,0 +1,2 @@ + +<%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %> diff --git a/app/views/reveal_access_token/show.html.erb b/app/views/reveal_access_token/show.html.erb new file mode 100644 index 00000000..4ee8c5fb --- /dev/null +++ b/app/views/reveal_access_token/show.html.erb @@ -0,0 +1,14 @@ +<%= render 'shared/turbo_modal', title: t('reveal_api_key') do %> + <%= form_tag settings_reveal_access_token_path, enctype: 'multipart/form-data', data: { turbo_frame: :_top } do %> +
+ <%= label_tag :password, t('enter_your_password_to_reveal_the_api_key'), class: 'label' %> + <%= password_field_tag :password, nil, class: 'base-input', autocomplete: 'current-password', required: true, autofocus: true, placeholder: t('password') %> + <% if local_assigns[:error_message].present? %> + <%= local_assigns[:error_message] %> + <% end %> +
+
+ <%= submit_tag t('submit'), class: 'base-button' %> +
+ <% end %> +<% end %> diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index ef30b27b..6af9db8d 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -798,6 +798,9 @@ en: &en template_name_has_been_completed_by_submitters_html: '"{template.name}" has been completed by {submission.submitters}' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Please check the copy of your "{template.name}" in the email attachments.' you_have_been_invited_to_sign_the_template_name_html: 'You have been invited to sign the "{template.name}".' + reveal_api_key: Reveal API Key + enter_your_password_to_reveal_the_api_key: Enter your password to reveal the API key + wrong_password: Wrong password. submission_sources: api: API bulk: Bulk Send @@ -1682,6 +1685,9 @@ es: &es template_name_has_been_completed_by_submitters_html: '"{template.name}" ha sido completado por {submission.submitters}' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos del correo electrónico.' you_have_been_invited_to_sign_the_template_name_html: 'Has sido invitado a firmar el "{template.name}".' + reveal_api_key: Revelar clave API + enter_your_password_to_reveal_the_api_key: Introduce tu contraseña para revelar la clave API + wrong_password: Contraseña incorrecta. submission_sources: api: API bulk: Envío masivo @@ -2566,6 +2572,9 @@ it: &it template_name_has_been_completed_by_submitters_html: '"{template.name}" è stato completato da {submission.submitters}' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Per favore, controlla la copia del tuo "{template.name}" negli allegati dell''email.' you_have_been_invited_to_sign_the_template_name_html: 'Sei stato invitato a firmare il "{template.name}".' + reveal_api_key: Mostra chiave API + enter_your_password_to_reveal_the_api_key: Inserisci la tua password per mostrare la chiave API + wrong_password: Password errata. submission_sources: api: API bulk: Invio massivo @@ -3453,6 +3462,9 @@ fr: &fr template_name_has_been_completed_by_submitters_html: '"{template.name}" a été complété par {submission.submitters}' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes de l’e-mail.' you_have_been_invited_to_sign_the_template_name_html: 'Vous avez été invité à signer le "{template.name}".' + reveal_api_key: Révéler la clé API + enter_your_password_to_reveal_the_api_key: Entrez votre mot de passe pour révéler la clé API + wrong_password: Mot de passe incorrect. submission_sources: api: API bulk: Envoi en masse @@ -4338,6 +4350,9 @@ pt: &pt template_name_has_been_completed_by_submitters_html: '"{template.name}" foi concluído por {submission.submitters}' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, verifique a cópia do seu "{template.name}" nos anexos do e-mail.' you_have_been_invited_to_sign_the_template_name_html: 'Você foi convidado a assinar o "{template.name}".' + reveal_api_key: Revelar chave API + enter_your_password_to_reveal_the_api_key: Insira sua senha para revelar a chave API + wrong_password: Senha incorreta. submission_sources: api: API bulk: Envio em massa @@ -5223,6 +5238,9 @@ de: &de template_name_has_been_completed_by_submitters_html: '"{template.name}" wurde von {submission.submitters} abgeschlossen' please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Bitte prüfen Sie die Kopie Ihres "{template.name}" in den E-Mail-Anhängen.' you_have_been_invited_to_sign_the_template_name_html: 'Du wurdest eingeladen, "{template.name}" zu unterschreiben.' + reveal_api_key: API-Schlüssel anzeigen + enter_your_password_to_reveal_the_api_key: Gib dein Passwort ein, um den API-Schlüssel anzuzeigen + wrong_password: Falsches Passwort. submission_sources: api: API bulk: Massenversand diff --git a/config/routes.rb b/config/routes.rb index 76ed7af9..072faa4e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -179,6 +179,7 @@ Rails.application.routes.draw do defaults: { status: :integration } resource :personalization, only: %i[show create], controller: 'personalization_settings' resources :api, only: %i[index create], controller: 'api_settings' + resource :reveal_access_token, only: %i[show create], controller: 'reveal_access_token' resources :webhooks, only: %i[index show new create update destroy], controller: 'webhook_settings' do post :resend diff --git a/spec/system/api_settings_spec.rb b/spec/system/api_settings_spec.rb index a14ef36d..6f796add 100644 --- a/spec/system/api_settings_spec.rb +++ b/spec/system/api_settings_spec.rb @@ -14,4 +14,26 @@ RSpec.describe 'API Settings' do token = user.access_token.token expect(page).to have_field('X-Auth-Token', with: token.sub(token[5..], '*' * token[5..].size)) end + + it 'reveals API key with correct password' do + find('#api_key').click + + within('.modal') do + fill_in 'password', with: user.password + click_button 'Submit' + end + + expect(page).to have_field('X-Auth-Token', with: user.access_token.token) + end + + it 'shows error with incorrect password' do + find('#api_key').click + + within('.modal') do + fill_in 'password', with: 'wrong_password' + click_button 'Submit' + end + + expect(page).to have_content('Wrong password') + end end