Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise: How to quickly reset all user passwords

I have a rake task which (among other things) clones my production database to my local machine and resets all the users passwords to password (or whatever).

My current implementation looks something like:

User.find_each do |user|
  user.password = 'password'
  user.save
end

And that works fine. But now that we have over 1000 users it's getting pretty slow, and it's sure to get worse.

EDIT

Okay. Here's a partial answer:

Devise.stretches = 1
User.find_each do |user|
  user.password = 'password'
  user.save
end
Devise.stretches = 10

This got me about a 5-10x speed increase. While it's still probably slow compared to a SQL-based solution, it's still a very nice improvement. This should scale to at least 10,000 users.

I may still mess around with a SQL solution, if I have time.

I'll leave this question open for a bit. If someone else has a better solution, please post.

Final Answer / Best Solution

As several comments have suggested, the fastest solution is to execute a mass update via SQL. Devise now allows you to set the encrypted_password directly:

sample_user = User.last
sample_user.password = "password"
encrypted_password = sample_user.encrypted_password
User.update_all(encrypted_password: encrypted_password)

Basically, we set the password on a single user, then we can use their encrypted_password to execute a mass update. This solution should scale to virtually any number of users.

Credit to @vladCovaliov for suggesting this solution in a comment below.

like image 580
Cory Schires Avatar asked Sep 11 '12 00:09

Cory Schires


1 Answers

Normally I would say write the sql you want, e.g.

ActiveRecord::Base.connection.execute(' update users set encrypted_password = 'password') 

However usually the password is encrypted and you directly encrypt it using MD5 or an authorization/authentication mechanism such as Devise or Authlogic. In that case you actually create or change a password by passing in password and password confirmation values (when creating the record in Rails) that must match. If they do match then the password is encrypted and actually stored in the database. For these reason, this has to be done one-by-one unless you use a hashing algorithm in your direct sql.

It may be as simple as

ActiveRecord::Base.connection.execute(' update users set password = md5('password'))
like image 181
Michael Durrant Avatar answered Sep 29 '22 12:09

Michael Durrant