clearance 0.10.3.2 → 0.10.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of clearance might be problematic. Click here for more details.
- data/.rspec +2 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -5
- data/Gemfile.lock +2 -11
- data/README.md +5 -8
- data/Rakefile +5 -7
- data/VERSION +1 -1
- data/app/views/passwords/new.html.erb +1 -1
- data/app/views/sessions/new.html.erb +1 -1
- data/app/views/users/_form.html.erb +1 -1
- data/features/engine/visitor_resets_password.feature +11 -0
- data/features/engine/visitor_signs_in.feature +10 -0
- data/features/engine/visitor_signs_up.feature +6 -4
- data/features/integration.feature +1 -1
- data/features/step_definitions/engine/clearance_steps.rb +8 -0
- data/lib/clearance/shoulda_macros.rb +5 -3
- data/lib/clearance/user.rb +12 -4
- data/lib/generators/clearance/install/install_generator.rb +2 -2
- data/spec/controllers/passwords_controller_spec.rb +177 -0
- data/spec/controllers/sessions_controller_spec.rb +160 -0
- data/spec/controllers/users_controller_spec.rb +64 -0
- data/{test → spec}/factories.rb +0 -0
- data/spec/models/clearance_mailer_spec.rb +27 -0
- data/spec/models/user_spec.rb +260 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/support/authorization.rb +18 -0
- data/spec/support/clearance_redirects.rb +21 -0
- data/spec/support/cookies.rb +72 -0
- metadata +16 -27
- data/test/controllers/passwords_controller_test.rb +0 -198
- data/test/controllers/sessions_controller_test.rb +0 -150
- data/test/controllers/users_controller_test.rb +0 -64
- data/test/models/clearance_mailer_test.rb +0 -29
- data/test/models/user_test.rb +0 -244
- data/test/test_helper.rb +0 -59
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Clearance::SessionsController do
|
4
|
+
describe "on GET to /sessions/new" do
|
5
|
+
before { get :new }
|
6
|
+
|
7
|
+
it { should respond_with(:success) }
|
8
|
+
it { should render_template(:new) }
|
9
|
+
it { should_not set_the_flash }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "on POST to #create with good credentials" do
|
13
|
+
before do
|
14
|
+
@user = Factory(:user)
|
15
|
+
@user.update_attribute(:remember_token, "old-token")
|
16
|
+
post :create, :session => {
|
17
|
+
:email => @user.email,
|
18
|
+
:password => @user.password }
|
19
|
+
end
|
20
|
+
|
21
|
+
it { should set_the_flash.to(/signed in/i) }
|
22
|
+
it { should redirect_to_url_after_create }
|
23
|
+
|
24
|
+
it "sets a remember token cookie" do
|
25
|
+
should set_cookie("remember_token", "old-token", Clearance.configuration.cookie_expiration.call)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a default of 1 year from now" do
|
29
|
+
Clearance.configuration.cookie_expiration.call.should be_within(100).of(1.year.from_now)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not change the remember token" do
|
33
|
+
@user.reload.remember_token.should == "old-token"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "on POST to #create with good credentials - cookie duration set to 2 weeks" do
|
38
|
+
custom_duration = 2.weeks.from_now.utc
|
39
|
+
|
40
|
+
before do
|
41
|
+
Clearance.configuration.cookie_expiration = lambda { custom_duration }
|
42
|
+
@user = Factory(:user)
|
43
|
+
@user.update_attribute(:remember_token, "old-token2")
|
44
|
+
post :create, :session => {
|
45
|
+
:email => @user.email,
|
46
|
+
:password => @user.password }
|
47
|
+
end
|
48
|
+
|
49
|
+
it "sets a remember token cookie" do
|
50
|
+
should set_cookie("remember_token", "old-token2", custom_duration)
|
51
|
+
end
|
52
|
+
|
53
|
+
after do
|
54
|
+
# restore default Clearance configuration
|
55
|
+
Clearance.configuration = nil
|
56
|
+
Clearance.configure {}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "on POST to #create with good credentials - cookie expiration set to nil (session cookie)" do
|
61
|
+
before do
|
62
|
+
Clearance.configuration.cookie_expiration = lambda { nil }
|
63
|
+
@user = Factory(:user)
|
64
|
+
@user.update_attribute(:remember_token, "old-token3")
|
65
|
+
post :create, :session => {
|
66
|
+
:email => @user.email,
|
67
|
+
:password => @user.password }
|
68
|
+
end
|
69
|
+
|
70
|
+
it "unsets a remember token cookie" do
|
71
|
+
should set_cookie("remember_token", "old-token3", nil)
|
72
|
+
end
|
73
|
+
|
74
|
+
after do
|
75
|
+
# restore default Clearance configuration
|
76
|
+
Clearance.configuration = nil
|
77
|
+
Clearance.configure {}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "on POST to #create with good credentials and a session return url" do
|
82
|
+
before do
|
83
|
+
@user = Factory(:user)
|
84
|
+
@return_url = '/url_in_the_session'
|
85
|
+
@request.session[:return_to] = @return_url
|
86
|
+
post :create, :session => {
|
87
|
+
:email => @user.email,
|
88
|
+
:password => @user.password }
|
89
|
+
end
|
90
|
+
|
91
|
+
it "redirects to the return URL" do
|
92
|
+
should redirect_to(@return_url)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "on POST to #create with good credentials and a request return url" do
|
97
|
+
before do
|
98
|
+
@user = Factory(:user)
|
99
|
+
@return_url = '/url_in_the_request'
|
100
|
+
post :create, :session => {
|
101
|
+
:email => @user.email,
|
102
|
+
:password => @user.password },
|
103
|
+
:return_to => @return_url
|
104
|
+
end
|
105
|
+
|
106
|
+
it "redirects to the return URL" do
|
107
|
+
should redirect_to(@return_url)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "on POST to #create with good credentials and a session return url and request return url" do
|
112
|
+
before do
|
113
|
+
@user = Factory(:user)
|
114
|
+
@return_url = '/url_in_the_session'
|
115
|
+
@request.session[:return_to] = @return_url
|
116
|
+
post :create, :session => {
|
117
|
+
:email => @user.email,
|
118
|
+
:password => @user.password },
|
119
|
+
:return_to => '/url_in_the_request'
|
120
|
+
end
|
121
|
+
|
122
|
+
it "redirects to the return url" do
|
123
|
+
should redirect_to(@return_url)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "on DELETE to #destroy given a signed out user" do
|
128
|
+
before do
|
129
|
+
sign_out
|
130
|
+
delete :destroy
|
131
|
+
end
|
132
|
+
it { should set_the_flash.to(/signed out/i) }
|
133
|
+
it { should redirect_to_url_after_destroy }
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "on DELETE to #destroy with a cookie" do
|
137
|
+
before do
|
138
|
+
@user = Factory(:user)
|
139
|
+
@user.update_attribute(:remember_token, "old-token")
|
140
|
+
@request.cookies["remember_token"] = "old-token"
|
141
|
+
delete :destroy
|
142
|
+
end
|
143
|
+
|
144
|
+
it { should set_the_flash.to(/signed out/i) }
|
145
|
+
it { should redirect_to_url_after_destroy }
|
146
|
+
|
147
|
+
it "should delete the cookie token" do
|
148
|
+
cookies['remember_token'].should be_nil
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should reset the remember token" do
|
152
|
+
@user.reload.remember_token.should_not == "old-token"
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should unset the current user" do
|
156
|
+
@controller.current_user.should be_nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Clearance::UsersController do
|
4
|
+
describe "when signed out" do
|
5
|
+
before { sign_out }
|
6
|
+
|
7
|
+
describe "on GET to #new" do
|
8
|
+
before { get :new }
|
9
|
+
|
10
|
+
it { should respond_with(:success) }
|
11
|
+
it { should render_template(:new) }
|
12
|
+
it { should_not set_the_flash }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "on GET to #new with email" do
|
16
|
+
before do
|
17
|
+
@email = "a@example.com"
|
18
|
+
get :new, :user => { :email => @email }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set assigned user's email" do
|
22
|
+
assigns(:user).email.should == @email
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "on POST to #create with valid attributes" do
|
27
|
+
before do
|
28
|
+
user_attributes = Factory.attributes_for(:user)
|
29
|
+
@old_user_count = User.count
|
30
|
+
post :create, :user => user_attributes
|
31
|
+
end
|
32
|
+
|
33
|
+
it { should assign_to(:user) }
|
34
|
+
|
35
|
+
it "should create a new user" do
|
36
|
+
User.count.should == @old_user_count + 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it { should set_the_flash.to(/signed up/i) }
|
40
|
+
it { should redirect_to_url_after_create }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "A signed-in user" do
|
45
|
+
before do
|
46
|
+
@user = Factory(:user)
|
47
|
+
sign_in_as @user
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "GET to new" do
|
51
|
+
before { get :new }
|
52
|
+
it "redirects to the home page" do
|
53
|
+
should redirect_to(root_url)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "POST to create" do
|
58
|
+
before { post :create, :user => {} }
|
59
|
+
it "redirects to the home page" do
|
60
|
+
should redirect_to(root_url)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/{test → spec}/factories.rb
RENAMED
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ClearanceMailer do
|
4
|
+
before do
|
5
|
+
@user = Factory(:user)
|
6
|
+
@user.forgot_password!
|
7
|
+
@email = ClearanceMailer.change_password(@user)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be from DO_NOT_REPLY" do
|
11
|
+
Clearance.configuration.mailer_sender.should =~ /#{@email.from[0]}/i
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be sent to user" do
|
15
|
+
@email.to.first.should =~ /#{@user.email}/i
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should contain a link to edit the user's password" do
|
19
|
+
host = ActionMailer::Base.default_url_options[:host]
|
20
|
+
regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?token=#{@user.confirmation_token}}
|
21
|
+
@email.body.to_s.should =~ regexp
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set its subject" do
|
25
|
+
@email.subject.should =~ /Change your password/
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
|
5
|
+
# db
|
6
|
+
|
7
|
+
it { should have_db_index(:email) }
|
8
|
+
it { should have_db_index(:remember_token) }
|
9
|
+
|
10
|
+
# signing up
|
11
|
+
|
12
|
+
describe "When signing up" do
|
13
|
+
it { should validate_presence_of(:email) }
|
14
|
+
it { should validate_presence_of(:password) }
|
15
|
+
it { should allow_value("foo@example.co.uk").for(:email) }
|
16
|
+
it { should allow_value("foo@example.com").for(:email) }
|
17
|
+
it { should_not allow_value("foo@").for(:email) }
|
18
|
+
it { should_not allow_value("foo@example..com").for(:email) }
|
19
|
+
it { should_not allow_value("foo@.example.com").for(:email) }
|
20
|
+
it { should_not allow_value("foo").for(:email) }
|
21
|
+
it { should_not allow_value("example.com").for(:email) }
|
22
|
+
|
23
|
+
it "should require password confirmation on create" do
|
24
|
+
user = Factory.build(:user, :password => 'blah',
|
25
|
+
:password_confirmation => 'boogidy')
|
26
|
+
(user.save).should_not be
|
27
|
+
user.errors[:password].should be_any
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should require non blank password confirmation on create" do
|
31
|
+
user = Factory.build(:user, :password => 'blah',
|
32
|
+
:password_confirmation => '')
|
33
|
+
(user.save).should_not be
|
34
|
+
user.errors[:password].should be_any
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should initialize salt" do
|
38
|
+
Factory(:user).salt.should_not be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "encrypt password" do
|
42
|
+
before do
|
43
|
+
@salt = "salt"
|
44
|
+
@user = Factory.build(:user, :salt => @salt)
|
45
|
+
def @user.initialize_salt; end
|
46
|
+
@user.save!
|
47
|
+
@password = @user.password
|
48
|
+
|
49
|
+
@user.send(:encrypt, @password)
|
50
|
+
@expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should create an encrypted password using SHA1 encryption" do
|
54
|
+
@user.encrypted_password.should == @expected
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should store email in down case" do
|
59
|
+
user = Factory(:user, :email => "John.Doe@example.com")
|
60
|
+
user.email.should == "john.doe@example.com"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "When multiple users have signed up" do
|
65
|
+
before { Factory(:user) }
|
66
|
+
it { should validate_uniqueness_of(:email) }
|
67
|
+
end
|
68
|
+
|
69
|
+
# authenticating
|
70
|
+
|
71
|
+
describe "A user" do
|
72
|
+
before do
|
73
|
+
@user = Factory(:user)
|
74
|
+
@password = @user.password
|
75
|
+
end
|
76
|
+
|
77
|
+
it "is authenticated with correct email and password" do
|
78
|
+
(::User.authenticate(@user.email, @password)).should be
|
79
|
+
@user.should be_authenticated(@password)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "is authenticated with correct uppercased email and correct password" do
|
83
|
+
(::User.authenticate(@user.email.upcase, @password)).should be
|
84
|
+
@user.should be_authenticated(@password)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "is authenticated with incorrect credentials" do
|
88
|
+
(::User.authenticate(@user.email, 'bad_password')).should_not be
|
89
|
+
@user.should_not be_authenticated('bad password')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# resetting remember token
|
94
|
+
|
95
|
+
describe "When resetting authentication with reset_remember_token!" do
|
96
|
+
before do
|
97
|
+
@user = Factory(:user)
|
98
|
+
@user.remember_token = "old-token"
|
99
|
+
@user.reset_remember_token!
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should change the remember token" do
|
103
|
+
@user.remember_token.should_not == "old-token"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# updating password
|
108
|
+
|
109
|
+
describe "An email confirmed user" do
|
110
|
+
before do
|
111
|
+
@user = Factory(:user)
|
112
|
+
@old_encrypted_password = @user.encrypted_password
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "who updates password with confirmation" do
|
116
|
+
before do
|
117
|
+
@user.update_password("new_password", "new_password")
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should change encrypted password" do
|
121
|
+
@user.encrypted_password.should_not == @old_encrypted_password
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should not generate the same remember token for users with the same password at the same time" do
|
127
|
+
Time.stubs(:now => Time.now)
|
128
|
+
password = 'secret'
|
129
|
+
first_user = Factory(:user,
|
130
|
+
:password => password,
|
131
|
+
:password_confirmation => password)
|
132
|
+
second_user = Factory(:user,
|
133
|
+
:password => password,
|
134
|
+
:password_confirmation => password)
|
135
|
+
|
136
|
+
second_user.remember_token.should_not == first_user.remember_token
|
137
|
+
end
|
138
|
+
|
139
|
+
# recovering forgotten password
|
140
|
+
|
141
|
+
describe "An user" do
|
142
|
+
before do
|
143
|
+
@user = Factory(:user)
|
144
|
+
@old_encrypted_password = @user.encrypted_password
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "who requests password reminder" do
|
148
|
+
before do
|
149
|
+
@user.confirmation_token.should be_nil
|
150
|
+
@user.forgot_password!
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should generate confirmation token" do
|
154
|
+
@user.confirmation_token.should_not be_nil
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "and then updates password" do
|
158
|
+
describe 'with confirmation' do
|
159
|
+
before do
|
160
|
+
@user.update_password("new_password", "new_password")
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should change encrypted password" do
|
164
|
+
@user.encrypted_password.should_not == @old_encrypted_password
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should clear confirmation token" do
|
168
|
+
@user.confirmation_token.should be_nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe 'without confirmation' do
|
173
|
+
before do
|
174
|
+
@user.update_password("new_password", "")
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should not change encrypted password" do
|
178
|
+
@old_encrypted_password.should == @user.encrypted_password
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should not clear confirmation token" do
|
182
|
+
@user.confirmation_token.should_not be_nil
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'with blank password and confirmation' do
|
187
|
+
before do
|
188
|
+
@user.update_password("", "")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "does not change encrypted password" do
|
192
|
+
@user.encrypted_password.should == @old_encrypted_password
|
193
|
+
end
|
194
|
+
|
195
|
+
it "does not clear confirmation token" do
|
196
|
+
@user.confirmation_token.should_not be_nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
# optional email/password fields
|
205
|
+
describe "a user with an optional email" do
|
206
|
+
before do
|
207
|
+
@user = User.new
|
208
|
+
class << @user
|
209
|
+
def email_optional?
|
210
|
+
true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
subject { @user }
|
216
|
+
|
217
|
+
it { should allow_value(nil).for(:email) }
|
218
|
+
it { should allow_value("").for(:email) }
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "a user with an optional password" do
|
222
|
+
before do
|
223
|
+
@user = User.new
|
224
|
+
class << @user
|
225
|
+
def password_optional?
|
226
|
+
true
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
subject { @user }
|
232
|
+
|
233
|
+
it { should allow_value(nil).for(:password) }
|
234
|
+
it { should allow_value("").for(:password) }
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "user factory" do
|
238
|
+
it "should create a valid user with just an overridden password" do
|
239
|
+
Factory.build(:user, :password => "test").should be_valid
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "when user exists before Clearance was installed" do
|
244
|
+
before do
|
245
|
+
@user = Factory(:user)
|
246
|
+
sql = "update users set salt = NULL, encrypted_password = NULL, remember_token = NULL where id = #{@user.id}"
|
247
|
+
ActiveRecord::Base.connection.update(sql)
|
248
|
+
@user.reload.salt.should be_nil
|
249
|
+
@user.reload.encrypted_password.should be_nil
|
250
|
+
@user.reload.remember_token.should be_nil
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should initialize salt, generate remember token, and save encrypted password on update_password" do
|
254
|
+
@user.update_password('password', 'password')
|
255
|
+
@user.salt.should_not be_nil
|
256
|
+
@user.encrypted_password.should_not be_nil
|
257
|
+
@user.remember_token.should_not be_nil
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|