Restrict Devise password recovery to only certain

2020-04-13 11:52发布

问题:

My app has a pre-subscription system to allow users to subscribe without password.

But malicious users who haven't finished their subscription (= don't have a password yet) could follow the password recovery process to set theirselves a password and brake the usual subscription process.

So I would like Devise to provide password recovery to only the users who are validated (namely users who finished their subscription).

If a non-validated user is entering his email to try to get a new password, I would like to show him the "email not found" error, as if he wasn't found at all.

I didn't find where to override Devise to add such a scope.

This method from the Recoverable seems to fit but I haven't been able to customize it:

# Attempt to find a user by its email. If a record is found, send new
# password instructions to it. If user is not found, returns a new user
# with an email not found error.
# Attributes must contain the user's email
def send_reset_password_instructions(attributes={})
  recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
  recoverable.send_reset_password_instructions if recoverable.persisted?
  recoverable
end

So for the moment I overrode the PasswordsController but this is not a clean solution.

class Users::PasswordsController < Devise::PasswordsController

  def create
    if resource_params[:email].present? && resource_class.registration_complete.where(email: resource_params[:email]).none?
      self.resource = resource_class.new
      self.resource.errors.add(:email, :not_found)
      render :new
    else
      super
    end
  end

end