clearance 1.0.1 → 1.1.0

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.

@@ -0,0 +1,19 @@
1
+ module Clearance
2
+ class SuccessStatus
3
+ def success?
4
+ true
5
+ end
6
+ end
7
+
8
+ class FailureStatus
9
+ attr_reader :failure_message
10
+
11
+ def initialize(failure_message)
12
+ @failure_message = failure_message
13
+ end
14
+
15
+ def success?
16
+ false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ require 'clearance/session_status'
2
+
3
+ module Clearance
4
+ class SignInGuard
5
+ def initialize(session, stack = [])
6
+ @session = session
7
+ @stack = stack
8
+ end
9
+
10
+ def success
11
+ SuccessStatus.new
12
+ end
13
+
14
+ def failure(message)
15
+ FailureStatus.new(message)
16
+ end
17
+
18
+ def next_guard
19
+ stack.call
20
+ end
21
+
22
+
23
+ private
24
+ attr_reader :stack, :session
25
+
26
+
27
+ def signed_in?
28
+ session.signed_in?
29
+ end
30
+
31
+ def current_user
32
+ session.current_user
33
+ end
34
+
35
+ end
36
+ end
@@ -28,6 +28,7 @@ module Clearance
28
28
 
29
29
  if Clearance::Testing.rails4?
30
30
  config.paths.add 'config/routes.rb', with: "#{APP_ROOT}/config/routes.rb"
31
+ config.secret_key_base = 'SECRET_KEY_BASE'
31
32
  else
32
33
  config.paths.add 'config/routes', with: "#{APP_ROOT}/config/routes.rb"
33
34
  end
@@ -36,7 +37,7 @@ module Clearance
36
37
  initialize!
37
38
  end
38
39
 
39
- def initialize!
40
+ def initialize!(&block)
40
41
  FileUtils.mkdir_p(Rails.root.join('db').to_s)
41
42
  super unless @initialized
42
43
  end
@@ -43,7 +43,7 @@ module Clearance
43
43
 
44
44
  included do
45
45
  validates :email,
46
- email: true,
46
+ email: { strict_mode: true },
47
47
  presence: true,
48
48
  uniqueness: { allow_blank: true },
49
49
  unless: :email_optional?
@@ -1,3 +1,3 @@
1
1
  module Clearance
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -17,7 +17,6 @@ describe Clearance::Session do
17
17
  end
18
18
 
19
19
  it 'returns nil for an unknown user' do
20
- user = create(:user)
21
20
  env = env_with_remember_token('bogus')
22
21
  session = Clearance::Session.new(env)
23
22
  session.should be_signed_out
@@ -38,6 +37,38 @@ describe Clearance::Session do
38
37
  expect(session.current_user).to eq user
39
38
  end
40
39
 
40
+ context 'with a block' do
41
+ it 'passes the success status to the block when sign in succeeds' do
42
+ success_status = stub_status(Clearance::SuccessStatus, true)
43
+ success_lambda = stub_callable
44
+
45
+ session.sign_in build(:user), &success_lambda
46
+
47
+ expect(success_lambda).to have_been_called.with(success_status)
48
+ end
49
+
50
+ it 'passes the failure status to the block when sign in fails' do
51
+ failure_status = stub_status(Clearance::FailureStatus, false)
52
+ failure_lambda = stub_callable
53
+
54
+ session.sign_in nil, &failure_lambda
55
+
56
+ expect(failure_lambda).to have_been_called.with(failure_status)
57
+ end
58
+
59
+ def stub_status(status_class, success)
60
+ stub('status', success?: success).tap do |status|
61
+ status_class.stubs(new: status)
62
+ end
63
+ end
64
+
65
+ def stub_callable
66
+ lambda {}.tap do |callable|
67
+ callable.stubs(:call)
68
+ end
69
+ end
70
+ end
71
+
41
72
  context 'with nil argument' do
42
73
  it 'assigns current_user' do
43
74
  session.sign_in nil
@@ -45,6 +76,57 @@ describe Clearance::Session do
45
76
  expect(session.current_user).to be_nil
46
77
  end
47
78
  end
79
+
80
+ context 'with a sign in stack' do
81
+
82
+ it 'runs the first guard' do
83
+ guard = stub_sign_in_guard(succeed: true)
84
+ user = build(:user)
85
+
86
+ session.sign_in user
87
+
88
+ expect(guard).to have_received(:call)
89
+ end
90
+
91
+ it 'will not sign in the user if the guard stack fails' do
92
+ stub_sign_in_guard(succeed: false)
93
+ user = build(:user)
94
+
95
+ session.sign_in user
96
+
97
+ expect(session.instance_variable_get("@cookies")).to be_nil
98
+ expect(session.current_user).to be_nil
99
+ end
100
+
101
+
102
+ def stub_sign_in_guard(options)
103
+ session_status = stub_status(options.fetch(:succeed))
104
+
105
+ stub('guard', call: session_status).tap do |guard|
106
+ Clearance.configuration.sign_in_guards << stub_guard_class(guard)
107
+ end
108
+ end
109
+
110
+ def stub_default_sign_in_guard
111
+ stub(:default_sign_in_guard).tap do |sign_in_guard|
112
+ Clearance::DefaultSignInGuard.stubs(:new).with(session).returns(sign_in_guard)
113
+ end
114
+ end
115
+
116
+ def stub_guard_class(guard)
117
+ stub(:guard_class).tap do |guard_class|
118
+ guard_class.stubs(:new).with(session, stub_default_sign_in_guard).returns(guard)
119
+ end
120
+ end
121
+
122
+ def stub_status(success)
123
+ stub('status', success?: success)
124
+ end
125
+
126
+ after do
127
+ Clearance.configuration.sign_in_guards = []
128
+ end
129
+ end
48
130
  end
49
131
 
50
132
  context 'if httponly is set' do
@@ -74,54 +156,139 @@ describe Clearance::Session do
74
156
  end
75
157
  end
76
158
 
77
- it 'sets a remember token cookie with a default expiration of 1 year from now' do
78
- user = create(:user)
79
- headers = {}
80
- session = Clearance::Session.new(env_without_remember_token)
81
- session.sign_in user
82
- session.add_cookie_to_headers headers
83
- headers.should set_cookie('remember_token', user.remember_token, 1.year.from_now)
84
- end
159
+ describe 'remember token cookie expiration' do
160
+ context 'default configuration' do
161
+ it 'is set to 1 year from now' do
162
+ user = stub('User', remember_token: '123abc')
163
+ headers = {}
164
+ session = Clearance::Session.new(env_without_remember_token)
165
+ session.sign_in user
166
+ session.add_cookie_to_headers headers
167
+ headers.should set_cookie('remember_token', user.remember_token, 1.year.from_now)
168
+ end
169
+ end
85
170
 
86
- it 'sets a remember token cookie with a custom expiration' do
87
- custom_expiration = 1.day.from_now
171
+ context 'configured with lambda taking no arguments' do
172
+ it 'logs a deprecation warning' do
173
+ expiration = -> { Time.now }
174
+ with_custom_expiration expiration do
175
+ session = Clearance::Session.new(env_without_remember_token)
176
+ session.stubs(:warn)
177
+ session.add_cookie_to_headers headers
178
+ expect(session).to have_received(:warn).once
179
+ end
180
+ end
88
181
 
89
- with_custom_expiration 1.day.from_now do
90
- user = create(:user)
91
- headers = {}
92
- session = Clearance::Session.new(env_without_remember_token)
93
- session.sign_in user
94
- session.add_cookie_to_headers headers
95
- headers.should set_cookie('remember_token', user.remember_token, 1.day.from_now)
96
- Clearance.configuration.cookie_expiration.call.should be_within(100).
97
- of(1.year.from_now)
182
+ it 'is set to the value of the evaluated lambda' do
183
+ expires_at = -> { 1.day.from_now }
184
+ with_custom_expiration expires_at do
185
+ user = stub('User', remember_token: '123abc')
186
+ headers = {}
187
+ session = Clearance::Session.new(env_without_remember_token)
188
+ session.sign_in user
189
+ session.stubs(:warn)
190
+ session.add_cookie_to_headers headers
191
+ headers.should set_cookie('remember_token', user.remember_token, expires_at.call)
192
+ end
193
+ end
194
+ end
195
+
196
+ context 'configured with lambda taking one argument' do
197
+ it 'it can use other cookies to set the value of the expires token' do
198
+ remembered_expires = 12.hours.from_now
199
+ expires_at = ->(cookies) { cookies['remember_me'] ? remembered_expires : nil }
200
+ with_custom_expiration expires_at do
201
+ user = stub('User', remember_token: '123abc')
202
+ headers = {}
203
+ session = Clearance::Session.new(env_with_cookies(remember_me: 'true'))
204
+ session.sign_in user
205
+ session.add_cookie_to_headers headers
206
+ headers.should set_cookie('remember_token', user.remember_token, remembered_expires)
207
+ end
208
+ end
98
209
  end
99
210
  end
100
211
 
101
- context 'if secure_cookie is set' do
102
- before do
103
- Clearance.configuration.secure_cookie = true
104
- session.sign_in(user)
212
+ describe 'secure cookie option' do
213
+ context 'when not set' do
214
+ before do
215
+ session.sign_in(user)
216
+ end
217
+
218
+ it 'sets a standard cookie' do
219
+ session.add_cookie_to_headers(headers)
220
+
221
+ headers['Set-Cookie'].should_not =~ /remember_token=.+; secure/
222
+ end
105
223
  end
106
224
 
107
- it 'sets a secure cookie' do
108
- session.add_cookie_to_headers(headers)
225
+ context 'when set' do
226
+ before do
227
+ Clearance.configuration.secure_cookie = true
228
+ session.sign_in(user)
229
+ end
230
+
231
+ it 'sets a secure cookie' do
232
+ session.add_cookie_to_headers(headers)
233
+
234
+ headers['Set-Cookie'].should =~ /remember_token=.+; secure/
235
+ end
109
236
 
110
- headers['Set-Cookie'].should =~ /remember_token=.+; secure/
237
+ after { restore_default_config }
111
238
  end
239
+ end
112
240
 
113
- after { restore_default_config }
241
+ describe 'cookie domain option' do
242
+ context 'when set' do
243
+ before do
244
+ Clearance.configuration.cookie_domain = '.example.com'
245
+ session.sign_in(user)
246
+ end
247
+
248
+ it 'sets a standard cookie' do
249
+ session.add_cookie_to_headers(headers)
250
+
251
+ headers['Set-Cookie'].should =~ /domain=\.example\.com; path/
252
+ end
253
+
254
+ after { restore_default_config }
255
+ end
256
+
257
+ context 'when not set' do
258
+ before { session.sign_in(user) }
259
+
260
+ it 'sets a standard cookie' do
261
+ session.add_cookie_to_headers(headers)
262
+
263
+ headers['Set-Cookie'].should_not =~ /domain=.+; path/
264
+ end
265
+ end
114
266
  end
115
267
 
116
- context 'if secure_cookie is not set' do
117
- before do
118
- session.sign_in(user)
268
+ describe 'cookie path option' do
269
+ context 'when not set' do
270
+ before { session.sign_in(user) }
271
+
272
+ it 'sets a standard cookie' do
273
+ session.add_cookie_to_headers(headers)
274
+
275
+ headers['Set-Cookie'].should_not =~ /domain=.+; path/
276
+ end
119
277
  end
120
278
 
121
- it 'sets a standard cookie' do
122
- session.add_cookie_to_headers(headers)
279
+ context 'when set' do
280
+ before do
281
+ Clearance.configuration.cookie_path = '/user'
282
+ session.sign_in(user)
283
+ end
123
284
 
124
- headers['Set-Cookie'].should_not =~ /remember_token=.+; secure/
285
+ it 'sets a standard cookie' do
286
+ session.add_cookie_to_headers(headers)
287
+
288
+ headers['Set-Cookie'].should =~ /path=\/user; expires/
289
+ end
290
+
291
+ after { restore_default_config }
125
292
  end
126
293
  end
127
294
 
@@ -164,8 +331,13 @@ describe Clearance::Session do
164
331
  header['Set-Cookie']
165
332
  end
166
333
 
334
+ def have_been_called
335
+ have_received(:call)
336
+ end
337
+
167
338
  def with_custom_expiration(custom_duration)
168
- Clearance.configuration.cookie_expiration = lambda { custom_duration }
339
+ Clearance.configuration.cookie_expiration = custom_duration
340
+ yield
169
341
  ensure
170
342
  restore_default_config
171
343
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ module Clearance
4
+ describe SignInGuard do
5
+ it 'handles success' do
6
+ sign_in_guard = SignInGuard.new(stub('session'))
7
+ status = stub('status')
8
+ SuccessStatus.stubs(:new).returns(status)
9
+
10
+ expect(sign_in_guard.success).to eq(status)
11
+ end
12
+
13
+ it 'handles failure' do
14
+ sign_in_guard = SignInGuard.new(stub('session'))
15
+ status = stub('status')
16
+ failure_message = "Failed"
17
+ FailureStatus.stubs(:new).with(failure_message).returns(status)
18
+
19
+ expect(sign_in_guard.failure(failure_message)).to eq(status)
20
+ end
21
+
22
+ it 'can proceed to the next guard' do
23
+ guards = stub('guards', call: true)
24
+ sign_in_guard = SignInGuard.new(stub('session'), guards)
25
+ sign_in_guard.next_guard
26
+ expect(guards).to have_received(:call)
27
+ end
28
+ end
29
+ end
@@ -3,18 +3,18 @@ require 'spec_helper'
3
3
  describe Clearance::Configuration do
4
4
  after { restore_default_config }
5
5
 
6
- describe 'when no user_model_name is specified' do
6
+ context 'when no user_model_name is specified' do
7
7
  before do
8
8
  Clearance.configure do |config|
9
9
  end
10
10
  end
11
11
 
12
12
  it 'defaults to User' do
13
- Clearance.configuration.user_model.should == ::User
13
+ expect(Clearance.configuration.user_model).to eq ::User
14
14
  end
15
15
  end
16
16
 
17
- describe 'when a custom user_model_name is specified' do
17
+ context 'when a custom user_model_name is specified' do
18
18
  before do
19
19
  MyUser = Class.new
20
20
 
@@ -23,53 +23,41 @@ describe Clearance::Configuration do
23
23
  end
24
24
  end
25
25
 
26
- after do
27
- Clearance.configure do |config|
28
- config.user_model = ::User
29
- end
30
- end
31
-
32
26
  it 'is used instead of User' do
33
- Clearance.configuration.user_model.should == ::MyUser
27
+ expect(Clearance.configuration.user_model).to eq ::MyUser
34
28
  end
35
29
  end
36
30
 
37
- describe 'when secure_cookie is set to true' do
31
+ context 'when secure_cookie is set to true' do
38
32
  before do
39
33
  Clearance.configure do |config|
40
34
  config.secure_cookie = true
41
35
  end
42
36
  end
43
37
 
44
- after do
45
- Clearance.configure do |config|
46
- config.secure_cookie = false
47
- end
48
- end
49
-
50
38
  it 'returns true' do
51
- Clearance.configuration.secure_cookie.should be_true
39
+ expect(Clearance.configuration.secure_cookie).to be_true
52
40
  end
53
41
  end
54
42
 
55
- describe 'when secure_cookie is not specified' do
43
+ context 'when secure_cookie is not specified' do
56
44
  before do
57
45
  Clearance.configure do |config|
58
46
  end
59
47
  end
60
48
 
61
49
  it 'defaults to false' do
62
- Clearance.configuration.secure_cookie.should be_false
50
+ expect(Clearance.configuration.secure_cookie).to be_false
63
51
  end
64
52
  end
65
53
 
66
- describe 'when no redirect URL specified' do
54
+ context 'when no redirect URL specified' do
67
55
  it 'should return "/" as redirect URL' do
68
- Clearance::Configuration.new.redirect_url.should == '/'
56
+ expect(Clearance::Configuration.new.redirect_url).to eq '/'
69
57
  end
70
58
  end
71
59
 
72
- describe 'when redirect URL is specified' do
60
+ context 'when redirect URL is specified' do
73
61
  let(:new_redirect_url) { '/admin' }
74
62
 
75
63
  before do
@@ -78,14 +66,50 @@ describe Clearance::Configuration do
78
66
  end
79
67
  end
80
68
 
81
- after do
69
+ it 'should return new redirect URL' do
70
+ expect(Clearance.configuration.redirect_url).to eq new_redirect_url
71
+ end
72
+ end
73
+
74
+ context 'when specifying sign in guards' do
75
+ DummyGuard = Class.new
76
+
77
+ before do
82
78
  Clearance.configure do |config|
83
- config.redirect_url = '/'
79
+ config.sign_in_guards = [DummyGuard]
84
80
  end
85
81
  end
86
82
 
87
- it 'should return new redirect URL' do
88
- Clearance.configuration.redirect_url.should == new_redirect_url
83
+ it 'should return the stack with added guards' do
84
+ expect(Clearance.configuration.sign_in_guards).to eq [DummyGuard]
85
+ end
86
+ end
87
+
88
+ context 'when cookie domain is specified' do
89
+ let(:domain) { '.example.com' }
90
+
91
+ before do
92
+ Clearance.configure do |config|
93
+ config.cookie_domain = domain
94
+ end
95
+ end
96
+
97
+ it 'returns configured value' do
98
+ expect(Clearance.configuration.cookie_domain).to eq domain
99
+ end
100
+ end
101
+
102
+ context 'when cookie path is specified' do
103
+ let(:path) { '/user' }
104
+
105
+ before do
106
+ Clearance.configure do |config|
107
+ config.cookie_path = path
108
+ end
109
+ end
110
+
111
+ it 'returns configured value' do
112
+ expect(Clearance.configuration.cookie_path).to eq path
89
113
  end
90
114
  end
91
115
  end