diff --git a/README.md b/README.md index 30dca97f..f951abb0 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ User.load_from_reset_password_token(token) @user.generate_reset_password_token! # if you want to send the email by youself @user.deliver_reset_password_instructions! # generates the token and sends the email @user.change_password!(new_password) +@user.reset_password_attempt_expired? # check if time between emails has not passed since last email ``` ### user activation diff --git a/lib/sorcery/model/submodules/reset_password.rb b/lib/sorcery/model/submodules/reset_password.rb index 00e8de48..b0a1f428 100644 --- a/lib/sorcery/model/submodules/reset_password.rb +++ b/lib/sorcery/model/submodules/reset_password.rb @@ -96,12 +96,13 @@ def generate_reset_password_token! # generates a reset code with expiration and sends an email to the user. def deliver_reset_password_instructions! mail = false - config = sorcery_config + # hammering protection - return false if config.reset_password_time_between_emails.present? && self.send(config.reset_password_email_sent_at_attribute_name) && self.send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.seconds.ago.utc + return false if reset_password_attempt_expired? + self.class.sorcery_adapter.transaction do generate_reset_password_token! - mail = send_reset_password_email! unless config.reset_password_mailer_disabled + mail = send_reset_password_email! unless sorcery_config.reset_password_mailer_disabled end mail end @@ -113,6 +114,13 @@ def change_password!(new_password) sorcery_adapter.save end + def reset_password_attempt_expired? + sorcery_config.reset_password_time_between_emails.present? && + self.send(sorcery_config.reset_password_email_sent_at_attribute_name) && + self.send(sorcery_config.reset_password_email_sent_at_attribute_name) > + sorcery_config.reset_password_time_between_emails.seconds.ago.utc + end + protected def send_reset_password_email! diff --git a/spec/shared_examples/user_reset_password_shared_examples.rb b/spec/shared_examples/user_reset_password_shared_examples.rb index 02a2b786..21c7b1e0 100644 --- a/spec/shared_examples/user_reset_password_shared_examples.rb +++ b/spec/shared_examples/user_reset_password_shared_examples.rb @@ -256,6 +256,13 @@ expect(user.deliver_reset_password_instructions!).to be false end + it "'reset_password_attempt_expired?' returns false if time between emails has not passed since last email" do + sorcery_model_property_set(:reset_password_time_between_emails, 10000) + user.deliver_reset_password_instructions! + + expect(user.reset_password_attempt_expired?).to be false + end + it "encrypts properly on reset" do user.deliver_reset_password_instructions! user.change_password!("blagu")