Skip to content

Commit

Permalink
Added BCryptHash custom type
Browse files Browse the repository at this point in the history
BCrypt is the password scheme used OpenBSD and features a variable cost.
This integrates BCryptHashes into DataMapper.  plain text passwords are
transparently converted to BCryptHashes for database storage and converted
back out to BCrypt Passwords on retrival.
  • Loading branch information
namelessjon committed Jul 20, 2008
1 parent 154265d commit e193130
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
1 change: 1 addition & 0 deletions dm-types/lib/dm-types.rb
Expand Up @@ -16,3 +16,4 @@
require dir / 'uri'
require dir / 'yaml'
require dir / 'serial'
require dir / 'bcrypt_hash'
31 changes: 31 additions & 0 deletions dm-types/lib/dm-types/bcrypt_hash.rb
@@ -0,0 +1,31 @@

require 'bcrypt'

module DataMapper
module Types
class BCryptHash < DataMapper::Type
primitive String
size 60

def self.load(value, property)
if value.nil?
nil
elsif value.is_a?(String)
BCrypt::Password.new(value)
else
raise ArgumentError.new("+value+ must be nil or a String")
end
end

def self.dump(value, property)
if value.nil?
nil
elsif value.is_a?(String)
BCrypt::Password.create(value)
else
raise ArgumentError.new("+value+ must be nil or a String")
end
end
end # class Yaml
end # module Types
end # module DataMapper
35 changes: 35 additions & 0 deletions dm-types/spec/integration/bcrypt_hash_spec.rb
@@ -0,0 +1,35 @@

require 'pathname'
require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'

describe DataMapper::Types::BCryptHash do
before(:each) do
class User
include DataMapper::Resource

property :id, Serial
property :password, BCryptHash
end
User.auto_migrate!
User.create!(:password => "DataMapper R0cks!")
end

it "should save a password to the DB on creation" do
repository(:default) do
User.create!(:password => "password1")
end
user = User.all
user[0].password.should == "DataMapper R0cks!"
user[1].password.should == "password1"
end

it "should change the password on attribute update" do
@user = User.first
@user.attribute_set(:password, "D@t@Mapper R0cks!")
@user.save
@user.password.should_not == "DataMapper R0cks!"
@user.password.should == "D@t@Mapper R0cks!"
end


end
38 changes: 38 additions & 0 deletions dm-types/spec/unit/bcrypt_hash_spec.rb
@@ -0,0 +1,38 @@
require 'pathname'
require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'

include DataMapper::Types

describe DataMapper::Types::BCryptHash do

before(:each) do
@clear_password = "DataMapper R0cks!"
@crypted_password = BCrypt::Password.create(@clear_password)
end

describe ".dump" do
it "should return a crypted hash as a BCrypt::Password" do
BCryptHash.dump(@clear_password, :property).should be_an_instance_of(BCrypt::Password)
end

it "should return a string that is 60 characters long" do
BCryptHash.dump(@clear_password, :property).should have(60).characters
end

it "should return nil if nil is passed" do
BCryptHash.dump(nil, :property).should be_nil
end

end

describe ".load" do
it "should return the password as the password" do
BCryptHash.load(@crypted_password, :property).should == @clear_password
end

it "should return nil if given nil" do
FilePath.load(nil, :property).should be_nil
end

end
end

0 comments on commit e193130

Please sign in to comment.