Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

Commit

Permalink
Added password_reset_token column to user
Browse files Browse the repository at this point in the history
  • Loading branch information
nbibler committed Mar 4, 2010
1 parent 4528f8a commit 6d2570a
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 131 deletions.
6 changes: 3 additions & 3 deletions app/controllers/blue_light_special/passwords_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ def create
end

def edit
@user = ::User.find_by_id_and_confirmation_token(
@user = ::User.find_by_id_and_password_reset_token(
params[:user_id], params[:token])
render :template => 'passwords/edit'
end

def update
@user = ::User.find_by_id_and_confirmation_token(
@user = ::User.find_by_id_and_password_reset_token(
params[:user_id], params[:token])

if @user.update_password(params[:user][:password],
Expand All @@ -51,7 +51,7 @@ def forbid_missing_token
end

def forbid_non_existent_user
unless ::User.find_by_id_and_confirmation_token(
unless ::User.find_by_id_and_password_reset_token(
params[:user_id], params[:token])
raise ActionController::Forbidden, "non-existent user"
end
Expand Down
12 changes: 3 additions & 9 deletions app/controllers/blue_light_special/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,9 @@ def create
flash_failure_after_create
render :template => 'sessions/new', :status => :unauthorized
else
if @user.email_confirmed?
sign_in(@user)
flash_success_after_create
redirect_back_or(url_after_create)
else
::BlueLightSpecialMailer.deliver_confirmation(@user)
flash_notice_after_create
redirect_to(sign_in_url)
end
sign_in(@user)
flash_success_after_create
redirect_back_or(url_after_create)
end
end

Expand Down
9 changes: 9 additions & 0 deletions app/views/blue_light_special_mailer/change_password.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Someone, hopefully you, has requested that we send you a link to change your password.

Here's the link:

<%= edit_user_password_url(@user,
:token => @user.password_reset_token,
:escape => false) %>

If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed.
2 changes: 1 addition & 1 deletion app/views/passwords/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<%= error_messages_for :user %>
<% form_for(:user,
:url => user_password_path(@user, :token => @user.confirmation_token),
:url => user_password_path(@user, :token => @user.password_reset_token),
:html => { :method => :put }) do |form| %>
<div class="password_field">
<%= form.label :password, "Choose password" %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ class BlueLightSpecialCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.string :email
t.string :encrypted_password, :limit => 128
t.string :salt, :limit => 128
t.string :remember_token, :limit => 128
t.string :facebook_uid, :limit => 50
t.string :encrypted_password, :limit => 128
t.string :salt, :limit => 128
t.string :remember_token, :limit => 128
t.string :facebook_uid, :limit => 50
t.string :password_reset_token, :limit => 128
t.timestamps
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ def self.up
<%
existing_columns = ActiveRecord::Base.connection.columns(:users).collect { |each| each.name }
columns = [
[:email, 't.string :email'],
[:encrypted_password, 't.string :encrypted_password, :limit => 128'],
[:salt, 't.string :salt, :limit => 128'],
[:remember_token, 't.string :remember_token, :limit => 128'],
[:facebook_uid, 't.string :facebook_uid, :limit => 50']
[:email, 't.string :email'],
[:encrypted_password, 't.string :encrypted_password, :limit => 128'],
[:salt, 't.string :salt, :limit => 128'],
[:remember_token, 't.string :remember_token, :limit => 128'],
[:facebook_uid, 't.string :facebook_uid, :limit => 50'],
[:password_reset_token, 't.string :password_reset_token, :limit => 128']
].delete_if {|c| existing_columns.include?(c.first.to_s)}
-%>
change_table(:users) do |t|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class PasswordResetTest < ActionController::IntegrationTest
sent = ActionMailer::Base.deliveries.last
assert_equal @user.email, sent.recipients
assert_match /password/i, sent.subject
assert !@user.confirmation_token.blank?
assert_match /#{@user.confirmation_token}/, sent.body[:url]
assert !@user.password_reset_token.blank?
assert_match /#{@user.password_reset_token}/, sent.body[:url]
end

end
Expand Down Expand Up @@ -118,7 +118,7 @@ def change_password(user, options = {})
options[:confirm] ||= options[:password]

visit edit_user_password_path(:user_id => user,
:token => user.confirmation_token)
:token => user.password_reset_token)
fill_in "New password", :with => options[:password]
fill_in "New password again", :with => options[:confirm]
click_button "Reset!"
Expand Down
1 change: 0 additions & 1 deletion lib/blue_light_special/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ def find_facebook_session
flash.now[:error] = "You have logged out of Facebook"
facebook_sign_out
rescue NoMethodError
flash[:error] = "Unable to connect to Facebook"
facebook_sign_out
redirect_to sign_in_path
end
Expand Down
10 changes: 9 additions & 1 deletion lib/blue_light_special/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def reset_remember_token!
# @example
# user.forgot_password!
def forgot_password!
generate_password_reset_token
save(false)
end

Expand All @@ -117,6 +118,9 @@ def forgot_password!
def update_password(new_password, new_password_confirmation)
self.password = new_password
self.password_confirmation = new_password_confirmation
if valid?
self.password_reset_token = nil
end
save
end

Expand All @@ -140,7 +144,11 @@ def encrypt_password
def encrypt(string)
generate_hash("--#{salt}--#{string}--")
end


def generate_password_reset_token
self.password_reset_token = encrypt("--#{Time.now.utc}--#{password}--#{rand}--")
end

def generate_remember_token
self.remember_token = encrypt("--#{Time.now.utc}--#{encrypted_password}--#{id}--#{rand}--")
end
Expand Down
17 changes: 2 additions & 15 deletions shoulda_macros/blue_light_special.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@ def should_be_signed_in_as(&block)
end
end

def should_be_signed_in_and_email_confirmed_as(&block)
warn "[DEPRECATION] should_be_signed_in_and_email_confirmed_as: questionable usefulness"
should_be_signed_in_as &block

should "have confirmed email" do
user = block.bind(self).call

assert_not_nil user
assert_equal user, assigns(:user)
assert assigns(:user).email_confirmed?
end
end

def should_not_be_signed_in
warn "[DEPRECATION] should_not_be_signed_in is no longer a valid test since we now store a remember_token in cookies, not user_id in session"
should "not be signed in" do
Expand Down Expand Up @@ -177,7 +164,7 @@ def should_display_a_password_update_form
warn "[DEPRECATION] should_display_a_password_update_form: not meant to be public, no longer used internally"
should "have a form for the user's token, password, and password confirm" do
update_path = ERB::Util.h(
user_password_path(@user, :token => @user.confirmation_token)
user_password_path(@user, :token => @user.password_reset_token)
)

assert_select 'form[action=?]', update_path do
Expand Down Expand Up @@ -231,7 +218,7 @@ def sign_in_as(user)
end

def sign_in
sign_in_as Factory(:email_confirmed_user)
sign_in_as Factory(:user)
end

def sign_out
Expand Down
20 changes: 10 additions & 10 deletions test/controllers/passwords_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class PasswordsControllerTest < ActionController::TestCase
end

should "generate a token for the change your password email" do
assert_not_nil @user.reload.confirmation_token
assert_not_nil @user.reload.password_reset_token
end

should "send the change your password email" do
Expand All @@ -45,15 +45,15 @@ class PasswordsControllerTest < ActionController::TestCase
email = "user1@example.com"
assert ! ::User.exists?(['email = ?', email])
ActionMailer::Base.deliveries.clear
assert_equal @user.confirmation_token,
@user.reload.confirmation_token
assert_equal @user.password_reset_token,
@user.reload.password_reset_token

post :create, :password => { :email => email }
end

should "not generate a token for the change your password email" do
assert_equal @user.confirmation_token,
@user.reload.confirmation_token
assert_equal @user.password_reset_token,
@user.reload.password_reset_token
end

should "not send a password reminder email" do
Expand All @@ -78,7 +78,7 @@ class PasswordsControllerTest < ActionController::TestCase
context "on GET to #edit with correct id and token" do
setup do
get :edit, :user_id => @user.to_param,
:token => @user.confirmation_token
:token => @user.password_reset_token
end

should "find the user" do
Expand Down Expand Up @@ -106,7 +106,7 @@ class PasswordsControllerTest < ActionController::TestCase

put(:update,
:user_id => @user,
:token => @user.confirmation_token,
:token => @user.password_reset_token,
:user => {
:password => new_password,
:password_confirmation => new_password
Expand All @@ -120,7 +120,7 @@ class PasswordsControllerTest < ActionController::TestCase
end

should "clear confirmation token" do
assert_nil @user.confirmation_token
assert_nil @user.password_reset_token
end

should "set remember token" do
Expand All @@ -138,7 +138,7 @@ class PasswordsControllerTest < ActionController::TestCase

put(:update,
:user_id => @user.to_param,
:token => @user.confirmation_token,
:token => @user.password_reset_token,
:user => {
:password => new_password,
:password_confirmation => ''
Expand All @@ -152,7 +152,7 @@ class PasswordsControllerTest < ActionController::TestCase
end

should "not clear token" do
assert_not_nil @user.confirmation_token
assert_not_nil @user.password_reset_token
end

should_not_be_signed_in
Expand Down
27 changes: 5 additions & 22 deletions test/controllers/sessions_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,9 @@ class SessionsControllerTest < ActionController::TestCase
should_display_a_sign_in_form
end

context "on POST to #create with unconfirmed credentials" do
setup do
@user = Factory(:user)
ActionMailer::Base.deliveries.clear
post :create, :session => {
:email => @user.email,
:password => @user.password }
end

should_deny_access(:flash => /User has not confirmed email. Confirmation email will be resent./i)

should "send the confirmation email" do
assert_not_nil email = ActionMailer::Base.deliveries[0]
assert_match /account confirmation/i, email.subject
end
end

context "on POST to #create with good credentials" do
setup do
@user = Factory(:email_confirmed_user)
@user = Factory(:user)
@user.update_attribute(:remember_token, "old-token")
post :create, :session => {
:email => @user.email,
Expand All @@ -55,7 +38,7 @@ class SessionsControllerTest < ActionController::TestCase

context "on POST to #create with good credentials and a session return url" do
setup do
@user = Factory(:email_confirmed_user)
@user = Factory(:user)
@return_url = '/url_in_the_session'
@request.session[:return_to] = @return_url
post :create, :session => {
Expand All @@ -68,7 +51,7 @@ class SessionsControllerTest < ActionController::TestCase

context "on POST to #create with good credentials and a request return url" do
setup do
@user = Factory(:email_confirmed_user)
@user = Factory(:user)
@return_url = '/url_in_the_request'
post :create, :session => {
:email => @user.email,
Expand All @@ -81,7 +64,7 @@ class SessionsControllerTest < ActionController::TestCase

context "on POST to #create with good credentials and a session return url and request return url" do
setup do
@user = Factory(:email_confirmed_user)
@user = Factory(:user)
@return_url = '/url_in_the_session'
@request.session[:return_to] = @return_url
post :create, :session => {
Expand Down Expand Up @@ -121,7 +104,7 @@ class SessionsControllerTest < ActionController::TestCase

context "on DELETE to #destroy with a cookie" do
setup do
@user = Factory(:email_confirmed_user)
@user = Factory(:user)
@user.update_attribute(:remember_token, "old-token")
@request.cookies["remember_token"] = "old-token"
delete :destroy
Expand Down
28 changes: 2 additions & 26 deletions test/models/blue_light_special_mailer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class BlueLightSpecialMailerTest < ActiveSupport::TestCase
context "A change password email" do
setup do
@user = Factory(:user)
@user.forgot_password!
@email = BlueLightSpecialMailer.create_change_password @user
end

Expand All @@ -18,7 +19,7 @@ class BlueLightSpecialMailerTest < ActiveSupport::TestCase

should "contain a link to edit the user's password" do
host = ActionMailer::Base.default_url_options[:host]
regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?token=#{@user.confirmation_token}}
regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?token=#{@user.password_reset_token}}
assert_match regexp, @email.body
end

Expand All @@ -27,29 +28,4 @@ class BlueLightSpecialMailerTest < ActiveSupport::TestCase
end
end

context "A confirmation email" do
setup do
@user = Factory(:user)
@email = BlueLightSpecialMailer.create_confirmation @user
end

should "be from DO_NOT_REPLY" do
assert_match /#{@email.from[0]}/i, BlueLightSpecial.configuration.mailer_sender
end

should "be sent to user" do
assert_match /#{@user.email}/i, @email.to.first
end

should "set its subject" do
assert_match /Account confirmation/, @email.subject
end

should "contain a link to confirm the user's account" do
host = ActionMailer::Base.default_url_options[:host]
regexp = %r{http://#{host}/users/#{@user.id}/confirmation/new\?token=#{@user.confirmation_token}}
assert_match regexp, @email.body
end
end

end

0 comments on commit 6d2570a

Please sign in to comment.