Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to skip has_secure_password validations

Tags:

In my app, only admins can create new User records. The user is emailed an activation link where they set their password.

I'd like to use the has_secure_passord method (railscast):

class User < ActiveRecord::Base
  has_secure_password
  ...
end

Works great, but it automatically validates presence of password digest...so when the admin creates the record the validations fail. I there a way to skip just the automatically added password_digest validation without skipping the others I've added?

like image 622
tybro0103 Avatar asked May 04 '12 03:05

tybro0103


3 Answers

Since 4.X versions of rails, has_secure_password takes an option :validations. If you set it to false, it will not run validations.

The 3.X version of the gem does not support this parameter. However you can backport the activemodel/lib/active_model/secure_password.rb from latest 4.0.XRC code which supports this argument.

So with that, your code will look like this:

class User < ActiveRecord::Base
  has_secure_password :validations => false
  ...
end
like image 97
journeyer Avatar answered Sep 26 '22 07:09

journeyer


I decided to do my own custom authentication. The following solution will validate passwords but only when they are being set. This allows admins to create users without adding a password.

class User < ActiveRecord::Base
  include BCrypt

  attr_accessor :password, :password_confirmation

  validates :password, length: (6..32), confirmation: true, if: :setting_password?

  def password=(password)
    @password = password
    self.password_hash = Password.create(password)
  end

  def authenticate(password)
    password.present? && password_hash.present? && Password.new(password_hash) == password
  end

private

  def setting_password?
    password || password_confirmation
  end

end

If someone posts an answer that allows me to still use the has_secure_password method, I'll accept it instead.

like image 33
tybro0103 Avatar answered Sep 26 '22 07:09

tybro0103


There's no way to skip the validation, but it would be easy enough to write your own version of the method that allows you to pass an argument to determine whether or not to validate presence of the password_digest field.

Just extend ActiveModel the same way they do in the SecurePassword module (via ActiveSupport::Concern) and add your own secure password method.

i.e.

module ActiveModel
  module MySecurePassword
    extend ActiveSupport::Concern

    module ClassMethods
      def my_has_secure_password(validate_password_digest=true)
        # you custom logic
      end
    end
  end
end
like image 25
Chris Schmitz Avatar answered Sep 23 '22 07:09

Chris Schmitz