thoughtbot-clearance 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. data/README.textile +17 -16
  2. data/Rakefile +8 -7
  3. data/TODO.textile +3 -3
  4. data/generators/clearance/clearance_generator.rb +1 -1
  5. data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +1 -1
  6. data/generators/clearance/templates/app/views/passwords/edit.html.erb +1 -1
  7. data/generators/clearance/templates/app/views/sessions/new.html.erb +2 -2
  8. data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +3 -3
  9. data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +14 -13
  10. data/generators/clearance/templates/test/factories/clearance.rb +16 -0
  11. data/lib/clearance/app/controllers/application_controller.rb +26 -14
  12. data/lib/clearance/app/controllers/confirmations_controller.rb +6 -3
  13. data/lib/clearance/app/controllers/passwords_controller.rb +15 -9
  14. data/lib/clearance/app/controllers/sessions_controller.rb +21 -17
  15. data/lib/clearance/app/controllers/users_controller.rb +4 -3
  16. data/lib/clearance/app/models/clearance_mailer.rb +1 -1
  17. data/lib/clearance/app/models/user.rb +15 -16
  18. data/lib/clearance/test/functional/confirmations_controller_test.rb +18 -30
  19. data/lib/clearance/test/functional/passwords_controller_test.rb +27 -45
  20. data/lib/clearance/test/functional/sessions_controller_test.rb +23 -27
  21. data/lib/clearance/test/functional/users_controller_test.rb +38 -28
  22. data/lib/clearance/test/test_helper.rb +7 -2
  23. data/lib/clearance/test/unit/clearance_mailer_test.rb +7 -5
  24. data/lib/clearance/test/unit/user_test.rb +107 -138
  25. data/shoulda_macros/clearance.rb +134 -6
  26. metadata +7 -3
  27. data/generators/clearance/templates/test/factories/clearance_user.rb +0 -9
@@ -5,8 +5,8 @@ module Clearance
5
5
 
6
6
  def self.included(controller)
7
7
  controller.class_eval do
8
- before_filter :redirect_to_root, :only => [:new, :create], :if => :logged_in?
9
-
8
+
9
+ before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
10
10
  filter_parameter_logging :password
11
11
 
12
12
  def new
@@ -17,7 +17,8 @@ module Clearance
17
17
  @user = User.new params[:user]
18
18
  if @user.save
19
19
  ClearanceMailer.deliver_confirmation @user
20
- flash[:notice] = "You will receive an email within the next few minutes. It contains instructions for you to confirm your account."
20
+ flash[:notice] = "You will receive an email within the next few minutes. " <<
21
+ "It contains instructions for you to confirm your account."
21
22
  redirect_to url_after_create
22
23
  else
23
24
  render :action => "new"
@@ -14,8 +14,8 @@ module Clearance
14
14
  end
15
15
 
16
16
  def confirmation(user)
17
- recipients user.email
18
17
  from DO_NOT_REPLY
18
+ recipients user.email
19
19
  subject "Account confirmation"
20
20
  body :user => user
21
21
  end
@@ -17,27 +17,22 @@ module Clearance
17
17
  validates_uniqueness_of :email, :case_sensitive => false
18
18
  validates_format_of :email, :with => %r{.+@.+\..+}
19
19
 
20
- before_save :initialize_salt, :encrypt_password
20
+ before_save :initialize_salt, :encrypt_password, :downcase_email
21
21
 
22
22
  def self.authenticate(email, password)
23
23
  user = find(:first, :conditions => ['LOWER(email) = ?', email.to_s.downcase])
24
24
  user && user.authenticated?(password) ? user : nil
25
25
  end
26
-
27
- def email=(value)
28
- value = value.to_s.downcase if value
29
- write_attribute(:email, value.to_s)
30
- end
31
26
 
32
27
  def authenticated?(password)
33
- crypted_password == encrypt(password)
28
+ encrypted_password == encrypt(password)
34
29
  end
35
30
 
36
- def encrypt(password)
37
- Digest::SHA512.hexdigest "--#{salt}--#{password}--"
31
+ def encrypt(string)
32
+ Digest::SHA512.hexdigest("--#{salt}--#{string}--")
38
33
  end
39
34
 
40
- def remember_token?
35
+ def remember?
41
36
  remember_token_expires_at && Time.now.utc < remember_token_expires_at
42
37
  end
43
38
 
@@ -48,7 +43,7 @@ module Clearance
48
43
  def remember_me_until(time)
49
44
  self.update_attribute :remember_token_expires_at, time
50
45
  self.update_attribute :remember_token,
51
- encrypt("#{email}--#{remember_token_expires_at}")
46
+ encrypt("--#{remember_token_expires_at}--#{password}--")
52
47
  end
53
48
 
54
49
  def forget_me!
@@ -56,25 +51,29 @@ module Clearance
56
51
  self.update_attribute :remember_token, nil
57
52
  end
58
53
 
59
- def confirm!
60
- self.update_attribute :confirmed, true
54
+ def confirm_email!
55
+ self.update_attribute :email_confirmed, true
61
56
  end
62
57
 
63
58
  protected
64
59
 
65
60
  def initialize_salt
66
61
  if new_record?
67
- self.salt = Digest::SHA512.hexdigest("--#{Time.now.to_s}--#{email}--")
62
+ self.salt = encrypt("--#{Time.now.utc.to_s}--#{password}--")
68
63
  end
69
64
  end
70
65
 
71
66
  def encrypt_password
72
67
  return if password.blank?
73
- self.crypted_password = encrypt(password)
68
+ self.encrypted_password = encrypt(password)
74
69
  end
75
70
 
76
71
  def password_required?
77
- crypted_password.blank? || !password.blank?
72
+ encrypted_password.blank? || !password.blank?
73
+ end
74
+
75
+ def downcase_email
76
+ self.email = email.to_s.downcase
78
77
  end
79
78
 
80
79
  end
@@ -3,48 +3,36 @@ module Clearance
3
3
  module Functional
4
4
  module ConfirmationsControllerTest
5
5
 
6
- def self.included(base)
7
- base.class_eval do
8
-
9
- context 'A GET to #new' do
10
- context "with the User with the given id's salt" do
6
+ def self.included(controller_test)
7
+ controller_test.class_eval do
8
+
9
+ should_filter_params :salt
10
+
11
+ context "Given a user whose email has not been confirmed" do
12
+ setup { @user = Factory(:registered_user) }
13
+
14
+ context "on GET to #new with correct id and salt" do
11
15
  setup do
12
- @user = Factory :clearance_user
13
16
  get :new, :user_id => @user.to_param, :salt => @user.salt
14
17
  end
15
18
 
16
- should 'find the User record with the given id and salt' do
17
- assert_equal @user, assigns(:user)
18
- end
19
-
20
- should 'confirm the User record with the given id' do
21
- assert assigns(:user).confirmed?
22
- end
23
-
24
- should 'log the User in' do
25
- assert_equal @user.id, session[:user_id]
26
- end
27
-
28
- should_redirect_to "@controller.send(:url_after_create)"
19
+ should_be_signed_in_and_email_confirmed_as { @user }
20
+ should_redirect_to_url_after_create
29
21
  end
30
-
31
- context "without the User with the given id's salt" do
22
+
23
+ context "on GET to #new with incorrect salt" do
32
24
  setup do
33
- user = Factory :clearance_user
34
- salt = ''
35
- assert_not_equal salt, user.salt
25
+ salt = ""
26
+ assert_not_equal salt, @user.salt
36
27
 
37
- get :new, :user_id => user.to_param, :salt => ''
28
+ get :new, :user_id => @user.to_param, :salt => salt
38
29
  end
39
30
 
40
31
  should_respond_with :not_found
41
-
42
- should 'render nothing' do
43
- assert @response.body.blank?
44
- end
32
+ should_render_nothing
45
33
  end
46
34
  end
47
-
35
+
48
36
  end
49
37
  end
50
38
 
@@ -3,13 +3,14 @@ module Clearance
3
3
  module Functional
4
4
  module PasswordsControllerTest
5
5
 
6
- def self.included(base)
7
- base.class_eval do
6
+ def self.included(controller_test)
7
+ controller_test.class_eval do
8
8
 
9
- should_route :get, '/users/1/password/edit', :action => 'edit', :user_id => '1'
9
+ should_route :get, '/users/1/password/edit',
10
+ :action => 'edit', :user_id => '1'
10
11
 
11
12
  context 'with a user' do
12
- setup { @user = Factory :clearance_user }
13
+ setup { @user = Factory(:registered_user) }
13
14
 
14
15
  context 'A GET to #new' do
15
16
  setup { get :new, :user_id => @user.to_param }
@@ -35,10 +36,10 @@ module Clearance
35
36
  assert_match /#{@user.email}/, flash[:notice]
36
37
  end
37
38
 
38
- should_redirect_to "@controller.send(:url_after_create)"
39
+ should_redirect_to_url_after_create
39
40
  end
40
41
 
41
- context 'with a non-existing email address' do
42
+ context 'with a non-existent email address' do
42
43
  setup do
43
44
  email = 'user1@example.com'
44
45
  assert ! User.exists?(['email = ?', email])
@@ -51,8 +52,8 @@ module Clearance
51
52
  assert ActionMailer::Base.deliveries.empty?
52
53
  end
53
54
 
54
- should 'set a :warning flash' do
55
- assert_not_nil flash.now[:warning]
55
+ should 'set a :notice flash' do
56
+ assert_not_nil flash.now[:notice]
56
57
  end
57
58
 
58
59
  should_render_template "new"
@@ -64,7 +65,7 @@ module Clearance
64
65
  setup do
65
66
  get :edit,
66
67
  :user_id => @user.to_param,
67
- :password => @user.crypted_password,
68
+ :password => @user.encrypted_password,
68
69
  :email => @user.email
69
70
  end
70
71
 
@@ -77,7 +78,7 @@ module Clearance
77
78
 
78
79
  should "have a form for the user's email, password, and password confirm" do
79
80
  update_path = ERB::Util.h(user_password_path(@user,
80
- :password => @user.crypted_password,
81
+ :password => @user.encrypted_password,
81
82
  :email => @user.email))
82
83
 
83
84
  assert_select 'form[action=?]', update_path do
@@ -94,10 +95,7 @@ module Clearance
94
95
  end
95
96
 
96
97
  should_respond_with :not_found
97
-
98
- should 'render an empty response' do
99
- assert @response.body.blank?
100
- end
98
+ should_render_nothing
101
99
  end
102
100
  end
103
101
 
@@ -108,31 +106,24 @@ module Clearance
108
106
  end
109
107
 
110
108
  should "not update the user's password" do
111
- assert_not_equal @encrypted_new_password, @user.crypted_password
112
- end
113
-
114
- should 'not log the user in' do
115
- assert_nil session[:user_id]
109
+ assert_not_equal @encrypted_new_password, @user.encrypted_password
116
110
  end
117
111
 
112
+ should_not_be_signed_in
118
113
  should_respond_with :not_found
119
-
120
- should 'render an empty response' do
121
- assert @response.body.blank?
122
- end
114
+ should_render_nothing
123
115
  end
124
116
 
125
117
  context 'with a matching password and password confirmation' do
126
118
  setup do
127
119
  new_password = 'new_password'
128
- encryption_format = "--#{@user.salt}--#{new_password}--"
129
- @encrypted_new_password = Digest::SHA512.hexdigest encryption_format
130
- assert_not_equal @encrypted_new_password, @user.crypted_password
120
+ @encrypted_new_password = @user.encrypt(new_password)
121
+ assert_not_equal @encrypted_new_password, @user.encrypted_password
131
122
 
132
123
  put(:update,
133
124
  :user_id => @user,
134
125
  :email => @user.email,
135
- :password => @user.crypted_password,
126
+ :password => @user.encrypted_password,
136
127
  :user => {
137
128
  :password => new_password,
138
129
  :password_confirmation => new_password
@@ -141,25 +132,21 @@ module Clearance
141
132
  end
142
133
 
143
134
  should "update the user's password" do
144
- assert_equal @encrypted_new_password, @user.crypted_password
135
+ assert_equal @encrypted_new_password, @user.encrypted_password
145
136
  end
146
137
 
147
- should 'log the user in' do
148
- assert_equal session[:user_id], @user.id
149
- end
150
-
151
- should_redirect_to "user_path(@user)"
138
+ should_be_signed_in_as { @user }
139
+ should_redirect_to_url_after_update
152
140
  end
153
141
 
154
142
  context 'with password but blank password confirmation' do
155
143
  setup do
156
144
  new_password = 'new_password'
157
- encryption_format = "--#{@user.salt}--#{new_password}--"
158
- @encrypted_new_password = Digest::SHA512.hexdigest encryption_format
145
+ @encrypted_new_password = @user.encrypt(new_password)
159
146
 
160
147
  put(:update,
161
148
  :user_id => @user.to_param,
162
- :password => @user.crypted_password,
149
+ :password => @user.encrypted_password,
163
150
  :user => {
164
151
  :password => new_password,
165
152
  :password_confirmation => ''
@@ -168,21 +155,16 @@ module Clearance
168
155
  end
169
156
 
170
157
  should "not update the user's password" do
171
- assert_not_equal @encrypted_new_password, @user.crypted_password
172
- end
173
-
174
- should 'not log the user in' do
175
- assert_nil session[:user_id]
158
+ assert_not_equal @encrypted_new_password, @user.encrypted_password
176
159
  end
177
160
 
161
+ should_not_be_signed_in
178
162
  should_respond_with :not_found
179
-
180
- should 'render an empty response' do
181
- assert @response.body.blank?
182
- end
163
+ should_render_nothing
183
164
  end
184
165
  end
185
166
  end
167
+
186
168
  end
187
169
  end
188
170
 
@@ -3,8 +3,9 @@ module Clearance
3
3
  module Functional
4
4
  module SessionsControllerTest
5
5
 
6
- def self.included(base)
7
- base.class_eval do
6
+ def self.included(controller_test)
7
+ controller_test.class_eval do
8
+
8
9
  should_filter_params :password
9
10
 
10
11
  context "on GET to /sessions/new" do
@@ -13,9 +14,10 @@ module Clearance
13
14
  should_respond_with :success
14
15
  should_render_template :new
15
16
  should_not_set_the_flash
17
+
16
18
  should 'display a "sign in" form' do
17
19
  assert_select "form[action=#{session_path}][method=post]",
18
- true, "There must be a form to log in" do
20
+ true, "There must be a form to sign in" do
19
21
  assert_select "input[type=text][name=?]",
20
22
  "session[email]", true, "There must be an email field"
21
23
  assert_select "input[type=password][name=?]",
@@ -28,10 +30,8 @@ module Clearance
28
30
  end
29
31
  end
30
32
 
31
- context "Given an unconfirmed user" do
32
- setup do
33
- @user = Factory(:clearance_user, :confirmed => false)
34
- end
33
+ context "Given a registered user" do
34
+ setup { @user = Factory(:registered_user) }
35
35
 
36
36
  context "a POST to #create with good credentials" do
37
37
  setup do
@@ -42,16 +42,11 @@ module Clearance
42
42
  end
43
43
 
44
44
  should_deny_access(:flash => /confirm/i)
45
-
46
- should "send the confirmation email" do
47
- assert_not_nil email = ActionMailer::Base.deliveries[0]
48
- assert_match /account confirmation/i, email.subject
49
- end
50
45
  end
51
46
  end
52
47
 
53
- context "Given a confirmed user" do
54
- setup { @user = Factory(:clearance_user, :confirmed => true) }
48
+ context "Given an email confirmed user" do
49
+ setup { @user = Factory(:email_confirmed_user) }
55
50
 
56
51
  context "a POST to #create with good credentials" do
57
52
  setup do
@@ -61,8 +56,8 @@ module Clearance
61
56
  end
62
57
 
63
58
  should_set_the_flash_to /success/i
64
- should_redirect_to '@controller.send(:url_after_create)'
65
- should_return_from_session :user_id, "@user.id"
59
+ should_redirect_to_url_after_create
60
+ should_be_signed_in_as { @user }
66
61
  end
67
62
 
68
63
  context "a POST to #create with bad credentials" do
@@ -74,7 +69,7 @@ module Clearance
74
69
 
75
70
  should_set_the_flash_to /bad/i
76
71
  should_render_template :new
77
- should_return_from_session :user_id, "nil"
72
+ should_not_be_signed_in
78
73
  end
79
74
 
80
75
  context "a POST to #create with good credentials and remember me" do
@@ -86,11 +81,11 @@ module Clearance
86
81
  end
87
82
 
88
83
  should_set_the_flash_to /success/i
89
- should_redirect_to "@controller.send(:url_after_create)"
90
- should_return_from_session :user_id, "@user.id"
84
+ should_redirect_to_url_after_create
85
+ should_be_signed_in_as { @user }
91
86
 
92
87
  should 'set the cookie' do
93
- assert ! cookies['auth_token'].empty?
88
+ assert ! cookies['remember_token'].empty?
94
89
  end
95
90
 
96
91
  should 'set the remember me token in users table' do
@@ -112,7 +107,7 @@ module Clearance
112
107
  should_return_from_session :user_id, "nil"
113
108
 
114
109
  should 'not create the cookie' do
115
- assert_nil cookies['auth_token']
110
+ assert_nil cookies['remember_token']
116
111
  end
117
112
 
118
113
  should 'not set the remember me token in users table' do
@@ -161,26 +156,26 @@ module Clearance
161
156
  public_context do
162
157
  context "logging out again" do
163
158
  setup { delete :destroy }
164
- should_redirect_to '@controller.send(:url_after_destroy)'
159
+ should_redirect_to_url_after_destroy
165
160
  end
166
161
  end
167
162
 
168
- logged_in_user_context do
163
+ signed_in_user_context do
169
164
  context "a DELETE to #destroy without a cookie" do
170
165
  setup { delete :destroy }
171
166
 
172
- should_set_the_flash_to(/logged out/i)
173
- should_redirect_to '@controller.send(:url_after_destroy)'
167
+ should_set_the_flash_to(/signed out/i)
168
+ should_redirect_to_url_after_destroy
174
169
  end
175
170
 
176
171
  context 'a DELETE to #destroy with a cookie' do
177
172
  setup do
178
- cookies['auth_token'] = CGI::Cookie.new 'token', 'value'
173
+ cookies['remember_token'] = CGI::Cookie.new 'token', 'value'
179
174
  delete :destroy
180
175
  end
181
176
 
182
177
  should 'delete the cookie' do
183
- assert cookies['auth_token'].empty?
178
+ assert cookies['remember_token'].empty?
184
179
  end
185
180
 
186
181
  should 'delete the remember me token in users table' do
@@ -189,6 +184,7 @@ module Clearance
189
184
  end
190
185
  end
191
186
  end
187
+
192
188
  end
193
189
  end
194
190