Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions app/controllers/account_reset/delete_account_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,31 @@ def check_granted_token
def prevent_parameter_leak
token = params[:token]
return if token.blank?
if AccountResetRequest.find_by(granted_token: token)&.granted_token_valid?
remove_token_from_url(token)
end

def remove_token_from_url(token)
ar = AccountResetRequest.find_by(granted_token: token)
if ar&.granted_token_valid?
session[:granted_token] = token
redirect_to url_for
else
redirect_to root_url
return
end
handle_expired_token(ar) if ar&.granted_token_expired?
redirect_to root_url
end

def handle_expired_token(ar)
analytics.track_event(Analytics::ACCOUNT_RESET,
event: :delete,
token_valid: true,
expired: true,
user_id: ar&.user&.uuid)
flash[:error] = link_expired
end

def link_expired
t('devise.two_factor_authentication.account_reset.link_expired')
end
end
end
8 changes: 6 additions & 2 deletions app/models/account_reset_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ def self.from_valid_granted_token(granted_token)
end

def granted_token_valid?
!granted_token.nil? &&
((Time.zone.now - granted_at) <= Figaro.env.account_reset_token_valid_for_days.to_i.days)
granted_token.present? && !granted_token_expired?
end

def granted_token_expired?
granted_at.present? &&
((Time.zone.now - granted_at) > Figaro.env.account_reset_token_valid_for_days.to_i.days)
end
end
6 changes: 5 additions & 1 deletion app/presenters/two_factor_login_options_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def options
end

def account_reset_or_cancel_link
account_reset_token ? account_reset_cancel_link : account_reset_link
account_reset_token_valid? ? account_reset_cancel_link : account_reset_link
end

private
Expand All @@ -71,6 +71,10 @@ def account_reset_token
current_user&.account_reset_request&.request_token
end

def account_reset_token_valid?
current_user&.account_reset_request&.granted_token_valid?
end

def configured_2fa_types
POSSIBLE_OPTIONS.each_with_object([]) do |option, result|
result << option if POLICIES[option].new(@current_user).configured?
Expand Down
2 changes: 2 additions & 0 deletions config/locales/devise/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ en:
code below.
please_try_again_html: Please try again in <strong id=%{id}>%{time_remaining}</strong>.
account_reset:
link_expired: The link to delete your login.gov account has expired. Please
create another request to delete your account.
successful_cancel: Thank you. Your request to delete your login.gov account
has been cancelled.
link: deleting your account
Expand Down
2 changes: 2 additions & 0 deletions config/locales/devise/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ es:
el código de seguridad a continuación.
please_try_again_html: Inténtelo de nuevo en <strong id=%{id}>%{time_remaining}</strong>.
account_reset:
link_expired: El enlace para eliminar su cuenta de login.gov ha caducado.
Crea otra solicitud para eliminar tu cuenta.
successful_cancel: Gracias. Su solicitud para eliminar su cuenta de login.gov
ha sido cancelada.
link: eliminando su cuenta
Expand Down
2 changes: 2 additions & 0 deletions config/locales/devise/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ fr:
le code de sécurité ci-dessous.
please_try_again_html: Veuillez essayer de nouveau dans <strong id=%{id}>%{time_remaining}</strong>.
account_reset:
link_expired: Le lien pour supprimer votre compte login.gov a expiré. Veuillez
créer une autre demande pour supprimer votre compte.
successful_cancel: Je vous remercie. Votre demande de suppression de votre
compte login.gov a été annulée.
link: supprimer votre compte
Expand Down
2 changes: 1 addition & 1 deletion config/locales/user_mailer/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ en:
link_text: Create your account
subject: Your login.gov password reset request
account_reset_cancel:
intro: This email confirms you have cancelled the request to delete your login.gov
intro: This email confirms you have cancelled your request to delete your login.gov
account.
subject: Delete your account
help: ''
Expand Down
2 changes: 1 addition & 1 deletion config/locales/user_mailer/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ es:
link_text: NOT TRANSLATED YET
subject: NOT TRANSLATED YET
account_reset_cancel:
intro: Este correo electrónico confirma que ha cancelado la solicitud para eliminar
intro: Este correo electrónico confirma que ha cancelado su solicitud para eliminar
su cuenta de login.gov.
subject: Eliminar su cuenta
help: ''
Expand Down
4 changes: 2 additions & 2 deletions config/locales/user_mailer/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ fr:
link_text: NOT TRANSLATED YET
subject: NOT TRANSLATED YET
account_reset_cancel:
intro: Cet e-mail confirme que vous avez annulé la demande de suppression de
votre compte login.gov.
intro: Cet e-mail confirme que vous avez annulé votre demande de suppression
de votre compte login.gov.
subject: Supprimer votre compte
help: ''
account_reset_request:
Expand Down
18 changes: 18 additions & 0 deletions spec/controllers/account_reset/delete_account_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,23 @@

expect(response).to render_template(:show)
end

it 'displays a flash and redirects to root if the token is expired' do
user = create(:user)
AccountResetService.new(user).create_request
AccountResetService.new(user).grant_request

stub_analytics
expect(@analytics).to receive(:track_event).
with(Analytics::ACCOUNT_RESET,
event: :delete, token_valid: true, expired: true, user_id: user.uuid)

Timecop.travel(Time.zone.now + 2.days) do
get :show, params: { token: AccountResetRequest.all[0].granted_token }
end

expect(response).to redirect_to(root_url)
expect(flash[:error]).to eq t('devise.two_factor_authentication.account_reset.link_expired')
end
end
end
23 changes: 23 additions & 0 deletions spec/models/account_reset_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@
end
end

describe '#granted_token_expired?' do
it 'returns false if the token does not exist' do
subject.granted_token = nil
subject.granted_at = nil

expect(subject.granted_token_expired?).to eq(false)
end

it 'returns true if the token is expired' do
subject.granted_token = '123'
subject.granted_at = Time.zone.now - 7.days

expect(subject.granted_token_expired?).to eq(true)
end

it 'returns false if the token is valid' do
subject.granted_token = '123'
subject.granted_at = Time.zone.now

expect(subject.granted_token_expired?).to eq(false)
end
end

describe '.from_valid_granted_token' do
it 'returns nil if the token does not exist' do
expect(AccountResetRequest.from_valid_granted_token('123')).to eq(nil)
Expand Down
11 changes: 8 additions & 3 deletions spec/presenters/two_factor_login_options_presenter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@
t('two_factor_authentication.login_options_title')
end

it 'supplies a cancel link when there is an account reset token' do
it 'supplies a cancel link when the token is valid' do
allow_any_instance_of(TwoFactorLoginOptionsPresenter).to \
receive(:account_reset_token_valid?).and_return(true)

allow_any_instance_of(TwoFactorLoginOptionsPresenter).to \
receive(:account_reset_token).and_return('foo')

expect(presenter.account_reset_or_cancel_link).to eq \
t('devise.two_factor_authentication.account_reset.pending_html',
cancel_link: view.link_to(
Expand All @@ -30,9 +34,10 @@
))
end

it 'supplies a reset link when there is no account reset token' do
it 'supplies a reset link when the token is not valid' do
allow_any_instance_of(TwoFactorLoginOptionsPresenter).to \
receive(:account_reset_token).and_return(nil)
receive(:account_reset_token_valid?).and_return(false)

expect(presenter.account_reset_or_cancel_link).to eq \
t('devise.two_factor_authentication.account_reset.text_html',
link: view.link_to(
Expand Down