Seeding users with Devise in Ruby on Rails
Asked Answered
R

15

36

In my development and test environments, I want to seed the database with a bunch of users. I'm using Ruby on Rails v3.2.8 and the latest Devise. So I added this line in my db/seeds.rb file:

User.create(email: '[email protected]', encrypted_password: '#$taawktljasktlw4aaglj')

However, when I run rake db:setup, I get the following error:

rake aborted! Can't mass-assign protected attributes: encrypted_password

What is the proper way to seed users?

Riojas answered 14/9, 2012 at 5:22 Comment(0)
S
51

You have to do like this:

user = User.new
user.email = '[email protected]'
user.encrypted_password = '#$taawktljasktlw4aaglj'
user.save!

Read this guide to understand what mass-assignment is: http://guides.rubyonrails.org/security.html

I am wondering why do have to directly set the encrypted password. You could do this:

user.password = 'valid_password'
user.password_confirmation = 'valid_password'
Siva answered 14/9, 2012 at 5:29 Comment(2)
If you were seeding a bunch of real users, and you had their email addresses which you were also seeding, would you also seed their password like that and let them change it once they sign on? or how would you do it?Endocrinology
The idea of storing the encrypted password there is that other developers do not know the actual password. It is a (weak) form of protection against accounts being compromised after the project's source code would be leaked.Brno
M
31

Arun is right. It's easier just to do this in your seeds.rb

user = User.create! :name => 'John Doe', :email => '[email protected]', :password => 'topsecret', :password_confirmation => 'topsecret'
Mf answered 14/9, 2012 at 7:13 Comment(1)
if you were seeding a bunch of real users, and you had their email addresses, would you also use that password and let them change it once and if they log on?Endocrinology
G
16

The skip_confirmation method will only work if you have confirmable module in your user model, otherwise remove it.

  user = User.new(
      :email                 => "[email protected]",
      :password              => "123456",
      :password_confirmation => "123456"
  )
  user.skip_confirmation!
  user.save!
Gardenia answered 14/9, 2012 at 7:21 Comment(0)
J
8

This is an old question but here is an example with an admin user (from cancancan):

User.create!([
  {email: "[email protected]", password: "testadminuser", password_confirmation: "testadminuser", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:02:10", last_sign_in_at: "2015-02-06 14:02:10", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: true},
  {email: "[email protected]", password: "testuseraccount", password_confirmation: "testuseraccount", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:03:01", last_sign_in_at: "2015-02-06 14:03:01", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: false},
  {email: "[email protected]", password: "testcustomeruser", password_confirmation: "testcustomeruser", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:03:44", last_sign_in_at: "2015-02-06 14:03:44", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: false}
])
Jongjongleur answered 6/2, 2015 at 14:17 Comment(0)
A
8

If you're using the devise confirmable module you need to do something like:

user = User.new(
  email: '[email protected]', 
  password: '123456789', 
  password_confirmation: '123456789'
)
user.skip_confirmation!
user.save!

The skip_confirmation! call just tell to devise that you don't need to confirm this account.
Other option is just set the confirmed_at user attribute as Time.now.utc before save.

Afloat answered 15/4, 2016 at 12:35 Comment(0)
A
4

To seed the users table:

User.create(
        email: "[email protected]",
        password: "12345678"
    )

With devise installed, the :password will be automatically hashed and saved to :encrypted_password

Ainsworth answered 5/2, 2016 at 2:47 Comment(0)
A
4

I don't know if it may help but actually I'm doing this to create a default Admin user in my Rails 5 app but without sharing the password in plain text in my GitHub repository.

Basically the logic for this is:

  • Generate a secure random password for the default user when seeded.
  • Go to ".../admins/sign_in" and click on "Forgot your password?" link to RESET it.
  • Get the reset password link in that default email account.
  • Set a new password.

So in the db/seeds.rb append this:

randomPassword = Devise.friendly_token.first(8)
mainAdminUser = Admin.create!(email: "[email protected]", password: randomPassword, name: "Username")

And if you are using devise confirmable feature just skip confirmable option by doing this:

mainAdminUser = Admin.new(
    email: "[email protected]",
    password: randomPassword,
    password_confirmation: randomPassword,
    name: "Username"
)
mainAdminUser.skip_confirmation!
mainAdminUser.save!

And your good to go!

Now you have a default user but you are not sharing a default password! I hope it could be useful for somebody.

Arthro answered 4/2, 2017 at 23:20 Comment(0)
D
2

Don't try create the encrypted password, devise handles that for you. This will work, just make sure the password is a minimum 6 characters long.

User.create(
        email: "[email protected]",
        password: "123456"
    )

Even better, in your terminal:

$bundle add faker

Then:

User.create(
            email: [email protected],
            password: "123456"
        )
10.times do
  User.create(
              email: Faker::Internet.email,
              password: "123456"
           )
end

Just make sure you set at least one email in your seeds that you can remember. Hence retaining the 'test' email.

Dewittdewlap answered 1/5, 2020 at 9:8 Comment(0)
H
1

Use your db/seeds.rb file to initiate your first user:

User.create!(email: '[email protected]', 
             password: '123456789', 
             password_confirmation: '123456789')
Hemline answered 14/8, 2014 at 16:35 Comment(0)
P
1

For devise users in seeds.rb file, what worked for me was to use a generic password upon saving the new user. Then update the encrypted password and save the model again. This was a hacky way.

user = User.new(
    :email                 => "[email protected]",
    :password              => "fat12345",
    :password_confirmation => "fat12345"
)
user.save!
user.encrypted_password="ENCRYPT.MY.ASS!!!KJASOPJ090923ULXCIULSH.IXJ!S920"
user.save

UPDATE others have posted and this is better way to do it:

user = User.new(
    email: "[email protected]", 
    password: "foob1234", 
    password_confirmation: "foob1234"
)
user.skip_confirmation! #only if using confirmable in devise settings in user model.
user.save!
Philipphilipa answered 8/11, 2015 at 19:20 Comment(0)
P
0

I Did something same in one of my requirements so just pasting my snippet

def triggerSeedUsers
      p "Starting Seeding Users..."
      p   "Deleting all users"..
      User.destroy_all
      normal_users = [{:email => '[email protected]', :login => "abc_demo", :name => 'abc Demo'}]
      admin_users = [{:email => '[email protected]', :login => 'abc_admin', :name => 'abc Admin'}]

      [normal_users,admin_users].each do |user_type|
        user_type.each do |user|
          User.create!(:name => user[:name],
            :login => user[:login],
            :email => user[:email],
            :first_login => false,
            :password => 'P@ssw0rd',
            :password_confirmation => 'P@ssw0rd'
            )
        end
      end
      User.where('name LIKE ?', '%demo%').update_all(:is_admin => 0)
      User.where('name LIKE ?', '%admin%').update_all(:is_admin => 1)
     end
Paste answered 14/9, 2012 at 7:20 Comment(0)
I
0

with email confirmating in db:seed :

User.create!( name: 'John', email:'[email protected]', password: '123456', password_confirmation: '123456',confirmed_at: '2018-08-04 04:51:43', current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1")
Inadvertence answered 4/8, 2018 at 4:57 Comment(0)
N
0

Just add :password attribute rest, devise will do password_encrypt for you

user = User.new({ email: '[email protected]', password: 'EnterYourPassword'})
user.save!
flash[:notice] = 'User Created'

#or for extra logic

        #if user.save
          #ExtraCredentialsOrLogic

        #elsif user.errors.any?
          #user.errors.full_messages.each do |msg|
            #puts msg
          #end
        #else
          #puts "****NOT VALID****"
    #end

and now run 'rake db:seed'

Necrotomy answered 26/12, 2018 at 13:1 Comment(0)
S
0

This allows you to run a seed multiple times without errors:

User.where(email: "[email protected]").first_or_create.update_attributes(nome: "Your Name",
    email: "[email protected]",
    password:              "password#123",
    password_confirmation: "password#123")
Shady answered 26/1, 2019 at 22:8 Comment(0)
T
0

In a Rails 3 User model I have, there are several more required fields. Combining other advice here and elsewhere, I built an export rake task that creates a seeds.rb that works with devise on the receiving side in Rails 5. It first lets Devise do its thing encrypting a bogus password, then saves the user's original encrypted password. Note the methods parameter to .serializable_hash, without which these fields don't get serialized.

namespace :export do
  desc "Export users"
  task :seeds => :environment do
    # Dependent models loaded first
    User.all.each do |user|
      excluded_keys = ['invitation_sent_at', 'invitation_accepted_at', 'invitation_created_at']
      serialized = user
                    .serializable_hash(methods: [:encrypted_password, :sign_in_count])
                     .delete_if{|key,value| excluded_keys.include?(key)}
      serialized['password'] = '123456789ABCDefg%'
      serialized['password_confirmation'] = '123456789ABCDefg%'
      puts "user = User.new(#{serialized})"
      puts "user.save!"
      puts "user.encrypted_password = '#{user.encrypted_password}'"
      puts "user.save!"
    end
  end
end

I ran that with rake export:seeds. I also had to change user.rb to bypass some serialization that Devise is doing on dates. I didn't bother doing this with the invitation dates because they were nullable and the bypass wasn't working. I took the 'serialize' lines back out after generating the seeds.rb, since I wasn't sure what the consequences might be. Relevant lines here:

class User < ActiveRecord::Base 
  devise :timeoutable, :timeout_in => 6.hours
  devise :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  serialize :created_at, DateTime
  serialize :updated_at, DateTime
Taction answered 3/2 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.