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.
- data/README.textile +17 -16
- data/Rakefile +8 -7
- data/TODO.textile +3 -3
- data/generators/clearance/clearance_generator.rb +1 -1
- data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +1 -1
- data/generators/clearance/templates/app/views/passwords/edit.html.erb +1 -1
- data/generators/clearance/templates/app/views/sessions/new.html.erb +2 -2
- data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +3 -3
- data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +14 -13
- data/generators/clearance/templates/test/factories/clearance.rb +16 -0
- data/lib/clearance/app/controllers/application_controller.rb +26 -14
- data/lib/clearance/app/controllers/confirmations_controller.rb +6 -3
- data/lib/clearance/app/controllers/passwords_controller.rb +15 -9
- data/lib/clearance/app/controllers/sessions_controller.rb +21 -17
- data/lib/clearance/app/controllers/users_controller.rb +4 -3
- data/lib/clearance/app/models/clearance_mailer.rb +1 -1
- data/lib/clearance/app/models/user.rb +15 -16
- data/lib/clearance/test/functional/confirmations_controller_test.rb +18 -30
- data/lib/clearance/test/functional/passwords_controller_test.rb +27 -45
- data/lib/clearance/test/functional/sessions_controller_test.rb +23 -27
- data/lib/clearance/test/functional/users_controller_test.rb +38 -28
- data/lib/clearance/test/test_helper.rb +7 -2
- data/lib/clearance/test/unit/clearance_mailer_test.rb +7 -5
- data/lib/clearance/test/unit/user_test.rb +107 -138
- data/shoulda_macros/clearance.rb +134 -6
- metadata +7 -3
- 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
|
-
|
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.
|
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"
|
@@ -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
|
-
|
28
|
+
encrypted_password == encrypt(password)
|
34
29
|
end
|
35
30
|
|
36
|
-
def encrypt(
|
37
|
-
Digest::SHA512.hexdigest
|
31
|
+
def encrypt(string)
|
32
|
+
Digest::SHA512.hexdigest("--#{salt}--#{string}--")
|
38
33
|
end
|
39
34
|
|
40
|
-
def
|
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("
|
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
|
60
|
-
self.update_attribute :
|
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 =
|
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.
|
68
|
+
self.encrypted_password = encrypt(password)
|
74
69
|
end
|
75
70
|
|
76
71
|
def password_required?
|
77
|
-
|
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(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
17
|
-
|
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 "
|
22
|
+
|
23
|
+
context "on GET to #new with incorrect salt" do
|
32
24
|
setup do
|
33
|
-
|
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(
|
7
|
-
|
6
|
+
def self.included(controller_test)
|
7
|
+
controller_test.class_eval do
|
8
8
|
|
9
|
-
should_route :get, '/users/1/password/edit',
|
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
|
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
|
-
|
39
|
+
should_redirect_to_url_after_create
|
39
40
|
end
|
40
41
|
|
41
|
-
context 'with a non-
|
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 :
|
55
|
-
assert_not_nil flash.now[:
|
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.
|
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.
|
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.
|
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
|
-
|
129
|
-
@encrypted_new_password
|
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.
|
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.
|
135
|
+
assert_equal @encrypted_new_password, @user.encrypted_password
|
145
136
|
end
|
146
137
|
|
147
|
-
|
148
|
-
|
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
|
-
|
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.
|
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.
|
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(
|
7
|
-
|
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
|
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
|
32
|
-
setup
|
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
|
54
|
-
setup { @user = Factory(:
|
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
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
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['
|
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['
|
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
|
-
|
159
|
+
should_redirect_to_url_after_destroy
|
165
160
|
end
|
166
161
|
end
|
167
162
|
|
168
|
-
|
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(/
|
173
|
-
|
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['
|
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['
|
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
|
|