Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added BCryptHash custom type

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...
commit e1931309a99e37bc34ff55f62361cf58e4ed0847 1 parent 154265d
@namelessjon namelessjon authored
View
1  dm-types/lib/dm-types.rb
@@ -16,3 +16,4 @@
require dir / 'uri'
require dir / 'yaml'
require dir / 'serial'
+require dir / 'bcrypt_hash'
View
31 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
View
35 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
View
38 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
Please sign in to comment.
Something went wrong with that request. Please try again.