-
-
Notifications
You must be signed in to change notification settings - Fork 939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update PasswordsControllerTest to use modern Rails IntegrationTest #5291
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,10 +38,11 @@ def update | |
@user.reset_api_key! if reset_params[:reset_api_key] == "true" # singular | ||
@user.api_keys.expire_all! if reset_params[:reset_api_keys] == "true" # plural | ||
delete_password_reset_session | ||
flash[:notice] = t(".success") | ||
redirect_to signed_in? ? dashboard_path : sign_in_path | ||
else | ||
flash.now[:alert] = t(".failure") | ||
render :edit | ||
render :edit, status: :unprocessable_entity | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Send a code when rendering after post/put. |
||
end | ||
end | ||
|
||
|
@@ -65,6 +66,7 @@ def ensure_email_present | |
|
||
def validate_confirmation_token | ||
confirmation_token = params.permit(:token).fetch(:token, "").to_s | ||
return login_failure(t("passwords.edit.token_failure")) if confirmation_token.blank? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Being extra cautious about blank tokens just in case there's ever a blank token in the database. |
||
@user = User.find_by(confirmation_token:) | ||
return login_failure(t("passwords.edit.token_failure")) unless @user&.valid_confirmation_token? | ||
sign_out if signed_in? && @user != current_user | ||
|
@@ -82,7 +84,7 @@ def password_reset_session_verified | |
|
||
def validate_password_reset_session | ||
return login_failure(t("passwords.edit.token_failure")) if session[:password_reset_verified].nil? | ||
return login_failure(t("verification_expired")) if session[:password_reset_verified] < Time.current | ||
return login_failure(t("verification_expired")) if Time.current.after?(session[:password_reset_verified]) | ||
@user = User.find_by(id: session[:password_reset_verified_user]) | ||
login_failure(t("verification_expired")) unless @user | ||
end | ||
|
@@ -98,8 +100,7 @@ def reset_params | |
end | ||
|
||
def mfa_failure(message) | ||
flash.now.alert = message | ||
render template: "multifactor_auths/prompt", status: :unauthorized | ||
prompt_mfa(alert: message, status: :unauthorized) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fixes a bug that I found where the otp form/webauthn form would lose the token in its url after a failed OTP submit. |
||
end | ||
|
||
def login_failure(alert) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -212,12 +212,12 @@ def total_rubygems_count | |
|
||
def confirm_email! | ||
return false if unconfirmed_email && !update_email | ||
update!(email_confirmed: true, confirmation_token: nil) | ||
update!(email_confirmed: true, confirmation_token: nil, token_expires_at: Time.zone.now) | ||
end | ||
|
||
# confirmation token expires after 15 minutes | ||
# confirmation token expires after 3 hours | ||
def valid_confirmation_token? | ||
token_expires_at > Time.zone.now | ||
confirmation_token.present? && Time.zone.now.before?(token_expires_at) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seemed really strange that |
||
end | ||
|
||
def generate_confirmation_token(reset_unconfirmed_email: true) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
<div class="text_field"> | ||
<% if @user.totp_enabled? %> | ||
<%= label_tag :otp, t(".otp_or_recovery"), class: 'form__label' %> | ||
<%= text_field_tag :otp, '', class: 'form__input', autofocus: true, autocomplete: :off %> | ||
<%= text_field_tag :otp, '', class: 'form__input', autofocus: true, autocomplete: "one-time-code" %> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following 1Password's guidelines. |
||
<% elsif @user.webauthn_only_with_recovery? %> | ||
<%= text_field_tag :otp, | ||
'', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,10 @@ | |
end | ||
mfa_hashed_recovery_codes { mfa_recovery_codes.map { |code| BCrypt::Password.create(code) } } | ||
|
||
after :create do |user, evaluator| | ||
user.confirm_email! if evaluator.email_confirmed != false && evaluator.unconfirmed_email.blank? | ||
end | ||
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed the user factory was making users with "confirmed emails" that still had valid unexpired confirmation_tokens. This allowed some of the password tests to pass because the factory user was already in "password reset" state. Change the factory to use the standard process, making the factory user more like an live user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this for every test? Can we set the correct state and then specifically for the password/confirmation token tests, we set the state required there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that creating a user without a token doesn't work. If you pass in nil you always get a token due to user hooks. This confirmed state is the correct state for every other test. In the password tests we must run We could generate a factory user with email confirmed and no token (the standard user state for most other tests), but it would require preventing the "generate token" hook from running on factory created users. Instead, this seemed like the cleanest and most canonical solution. |
||
|
||
trait :unconfirmed do | ||
email_confirmed { false } | ||
unconfirmed_email { "#{SecureRandom.hex(8)}#{email}" } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a notice on success (though I have observed that it doesn't always display)