Skip to content

Instantly share code, notes, and snippets.

@namelessjon
Created June 21, 2011 22:14
Show Gist options
  • Save namelessjon/1039058 to your computer and use it in GitHub Desktop.
Save namelessjon/1039058 to your computer and use it in GitHub Desktop.
Example user with a BCrypt password
require 'bcrypt'
class User
include DataMapper::Resource
attr_accessor :password, :password_confirmation
timestamps :at
property :id, Serial
property :username, String, :length => 4..30, :unique => true, :required => true
property :crypted_pass, String, :length => 60..60, :required => true, :writer => :protected
property :email, String, :length => 5..200, :required => true,
:format => :email_address
validates_presence_of :password, :password_confirmation, :if => :password_required?
validates_confirmation_of :password, :if => :password_required?
before :valid?, :crypt_password
# check validity of password if we have a new resource, or there is a plaintext password provided
def password_required?
new? or password
end
def reset_password(password, confirmation)
update(:password => password, :password_confirmation => confirmation)
end
# Hash the password using BCrypt
#
# BCrypt is a lot more secure than a hash made for speed such as the SHA algorithm. BCrypt also
# takes care of adding a salt before hashing. The whole thing is encoded in a string 60 bytes long.
def crypt_password
self.crypted_pass = BCrypt::Password.create(password) if password
end
# Prepare a BCrypt hash from the stored password, overriding the default reader
#
# return the `:no_password` symbol if the property has no content. This is for
# the safety of the authenticate method. It's easy to pass a nil password to
# that method, but passing a specific symbol takes effort.
def crypted_pass
pass = super
if pass
BCrypt::Password.new(pass)
else
:no_password
end
end
def authenticate(password)
crypted_pass == password
end
def self.authenticate(username, password)
un = username.to_s.downcase
u = first(:conditions => ['lower(email) = ? OR lower(username) = ?', un, un])
if u && u.authenticate(password)
u
else
nil
end
end
end
@dkubb
Copy link

dkubb commented Aug 14, 2011

@namelessjon I think you're right on all counts :)

If you want to write up something for the DM site that would be awesome. I know I've had to write this kind code lots of times before, and I bet it comes up fairly often.

@mcansky
Copy link

mcansky commented Sep 6, 2011

for some reason the reset password method didn't work like that for me, so here is what I did :

  def reset_password(password, confirmation)
    if (password == confirmation)
      self.password_reset = true
      self.password = password
      self.password_confirmation = confirmation
      self.crypt_password
    end
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment