Skip to content

Commit

Permalink
Added authentication methods
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmaclear committed Mar 1, 2011
1 parent 6b30651 commit 2c23d8f
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 3 deletions.
39 changes: 38 additions & 1 deletion app/models/user.rb
Expand Up @@ -9,9 +9,11 @@
# created_at :datetime
# updated_at :datetime
#
require 'digest'

class User < ActiveRecord::Base
attr_accessible :name, :email
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation

email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

Expand All @@ -22,4 +24,39 @@ class User < ActiveRecord::Base
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }

validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }

before_save :encrypt_password

def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end

def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end

private

def encrypt_password
self.salt = make_salt if new_record?
self.encrypted_password = encrypt(password)
end

def encrypt(string)
secure_hash("#{salt}--#{string}")
end

def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end

def secure_hash(string)
Digest::SHA2.hexdigest(string)
end

end
9 changes: 9 additions & 0 deletions db/migrate/20110301070758_add_password_to_users.rb
@@ -0,0 +1,9 @@
class AddPasswordToUsers < ActiveRecord::Migration
def self.up
add_column :users, :encrypted_password, :string
end

def self.down
remove_column :users, :encrypted_password
end
end
9 changes: 9 additions & 0 deletions db/migrate/20110301074852_add_salt_to_users.rb
@@ -0,0 +1,9 @@
class AddSaltToUsers < ActiveRecord::Migration
def self.up
add_column :users, :salt, :string
end

def self.down
remove_column :users, :salt
end
end
4 changes: 3 additions & 1 deletion db/schema.rb
Expand Up @@ -10,13 +10,15 @@
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 20110228131804) do
ActiveRecord::Schema.define(:version => 20110301074852) do

create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
t.string "encrypted_password"
t.string "salt"
end

add_index "users", ["email"], :name => "index_users_on_email", :unique => true
Expand Down
67 changes: 66 additions & 1 deletion spec/models/user_spec.rb
Expand Up @@ -2,7 +2,10 @@

describe User do
before(:each) do
@attr = { :name => "Example User", :email => "user@example.com" }
@attr = { :name => "Example User",
:email => "user@example.com",
:password => "foobar",
:password_confirmation => "foobar" }
end

it "should create a new instance givien valid attributes" do
Expand Down Expand Up @@ -59,4 +62,66 @@
user_with_duplicate_email_address.should_not be_valid
end

describe "password validations" do
it "should require a pssword" do
User.new(@attr.merge(:password => "", :password_confirmation => "")).should_not be_valid
end

it "should require a matching password confirmation" do
User.new(@attr.merge(:password_confirmation => "invalid")).should_not be_valid
end

it "should reject short passwords" do
short = "a" * 5
hash = @attr.merge(:password => short, :password_confirmation => short)
User.new(hash).should_not be_valid
end

it "should reject long passwords" do
long = "a" * 41
hash = @attr.merge(:password => long, :password_confirmation => long)
User.new(hash).should_not be_valid
end
end

describe "password encryption" do
before(:each) do
@user = User.create!(@attr)
end

it "should have an encryted password attribute" do
@user.should respond_to(:encrypted_password)
end

it "should set the encrypted password" do
@user.encrypted_password.should_not be_blank
end

describe "has_password? method" do
it "should be true if the passwords match" do
@user.has_password?(@attr[:password]).should be_true
end

it "sould be false if passwords do not match" do
@user.has_password?("invalid").should be_false
end
end

describe "authenticate method" do
it "should return nil on email/password mismatch" do
wrong_password_user = User.authenticate(@attr[:email], "wrongpass")
wrong_password_user.should be_nil
end

it "should return nil on for an email address with no user" do
not_found_user = User.authenticate("bar@foo.com", @attr[:password])
not_found_user.should be_nil
end

it "should return the user on email/password match" do
matching_user = User.authenticate(@attr[:email], @attr[:password])
matching_user.should == @user
end
end
end
end

0 comments on commit 2c23d8f

Please sign in to comment.