HasDigest
Finding I was generating SHA1 digests in a bunch of places in my code, I spent Friday writing up a quick rails plugin (with tests and a helpful shoulda macro) to make things easier:
class User < ActiveRecord::Base
has_digest :encrypted_password, :depends => :password
has_digest :remember_me_token, :depends => [:login, :remember_me_token_expires_at]
has_digest :token
end
For comparison’s sake, here’s how the User
model used to look:
class User < ActiveRecord::Base
attr_accessor :password
before_save :write_salt
before_save :write_encrypted_password
before_save :write_token
def remember_me
self.remember_me_token_expires_at = 2.weeks.from_now
self.remember_me_token = encrypt("--#{login}--#{remember_me_token_expires_at}--")
end
private
def write_salt
self.salt = Digest::SHA1.hexdigest(random_string) if new_record?
end
def write_encrypted_password
self.encrypted_password = encrypt(password) unless password.blank?
end
def write_token
if token.blank? || requesting_new_token
self.requesting_new_token = false
self.token = encrypt(random_string)
end
end
def encrypt(password)
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
end
def random_string
Time.now.to_s.split(//).sort_by { rand }.join
end
end
I suppose this kind of thing is primarily useful if you’re (as I was, for the sake of learning) putting together your own authentication system, though it also comes in handy when you need a non-guessable token for, say, a reset password request or a store order number.
I would also be remiss not to point out that my test_helper
owes its existence entirely to its counterpart in the (wonderful!) Paperclip.
Have fun!