clearance 0.13.2 → 0.14.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.

data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ 0.14.0
2
+ -------------------
3
+
4
+ * Support clearance session management from the Rack environment (Joe Ferris)
5
+
6
+ 0.13.2
7
+ -------------------
8
+
9
+ * Fixed the denies_access matcher (Chad Pytel, Joe Ferris)
10
+
1
11
  0.13.0
2
12
  -------------------
3
13
 
data/CONTRIBUTING.md CHANGED
@@ -3,8 +3,8 @@ We love pull requests. Here's a quick guide:
3
3
  1. Fork the repo.
4
4
 
5
5
  2. Run the tests. We only take pull requests with passing tests, and it's great
6
- to know that you have a clean slate: `bundle && rake`
7
-
6
+ to know that you have a clean slate: `bundle && rake db:migrate && rake`
7
+
8
8
  3. Add a test for your change. Only refactoring and documentation changes
9
9
  require no new tests. If you are adding functionality or fixing a bug, we need
10
10
  a test!
data/Gemfile.lock CHANGED
@@ -7,7 +7,7 @@ GIT
7
7
  PATH
8
8
  remote: .
9
9
  specs:
10
- clearance (0.12.0)
10
+ clearance (0.14.0)
11
11
  diesel (~> 0.1.5)
12
12
  rails (>= 3.0)
13
13
 
@@ -54,6 +54,8 @@ GEM
54
54
  rspec (>= 2.6.0)
55
55
  bcat (0.6.1)
56
56
  rack (~> 1.0)
57
+ bourne (1.0)
58
+ mocha (= 0.9.8)
57
59
  builder (2.1.2)
58
60
  capybara (1.0.1)
59
61
  mime-types (>= 1.16)
@@ -99,9 +101,10 @@ GEM
99
101
  mime-types (~> 1.16)
100
102
  treetop (~> 1.4.8)
101
103
  mime-types (1.16)
102
- mocha (0.9.12)
104
+ mocha (0.9.8)
105
+ rake
103
106
  nokogiri (1.5.0)
104
- polyglot (0.3.1)
107
+ polyglot (0.3.3)
105
108
  rack (1.2.3)
106
109
  rack-mount (0.6.14)
107
110
  rack (>= 1.0.0)
@@ -147,7 +150,9 @@ GEM
147
150
  sqlite3 (1.3.4)
148
151
  term-ansicolor (1.0.6)
149
152
  thor (0.14.6)
150
- treetop (1.4.9)
153
+ timecop (0.3.5)
154
+ treetop (1.4.10)
155
+ polyglot
151
156
  polyglot (>= 0.3.1)
152
157
  tzinfo (0.3.29)
153
158
  xpath (0.1.4)
@@ -159,6 +164,7 @@ PLATFORMS
159
164
  DEPENDENCIES
160
165
  appraisal (~> 0.3.8)
161
166
  aruba (~> 0.4.2)
167
+ bourne
162
168
  bundler (~> 1.0.0)
163
169
  capybara (~> 1.0.0)
164
170
  clearance!
@@ -166,7 +172,7 @@ DEPENDENCIES
166
172
  database_cleaner
167
173
  factory_girl_rails
168
174
  launchy
169
- mocha
170
175
  rspec-rails (~> 2.6.0)
171
176
  shoulda-matchers!
172
177
  sqlite3
178
+ timecop
data/README.md CHANGED
@@ -5,7 +5,7 @@ Rails authentication & authorization with email & password.
5
5
 
6
6
  [We have clearance, Clarence.](http://www.youtube.com/watch?v=fVq4_HhBK8Y)
7
7
 
8
- Clearance was extracted out of [Hoptoad](http://hoptoadapp.com).
8
+ Clearance was extracted out of [Airbrake](http://airbrakeapp.com/).
9
9
 
10
10
  Help
11
11
  ----
@@ -17,7 +17,7 @@ Help
17
17
  Installation
18
18
  ------------
19
19
 
20
- Clearance is a Rails engine for Rails 3. It is currently tested against Rails 3.0.9 and Rails 3.1.0.rc4.
20
+ Clearance is a Rails engine for Rails 3. It is currently tested against Rails 3.0.9 and Rails 3.1.0.
21
21
 
22
22
  Include the gem in your Gemfile:
23
23
 
@@ -86,6 +86,26 @@ Clearance will deliver one email on your app's behalf: when a user resets their
86
86
  config.mailer_sender = "me@example.com"
87
87
  end
88
88
 
89
+ Rack
90
+ ----
91
+
92
+ Clearance adds its session to the Rack environment hash so middleware and other
93
+ Rack applications can interact with it:
94
+
95
+ class Bubblegum::Middleware
96
+ def initialize(app)
97
+ @app = app
98
+ end
99
+
100
+ def call(env)
101
+ if env[:clearance].signed_in?
102
+ env[:clearance].current_user.bubble_gum
103
+ end
104
+ @app.call(env)
105
+ end
106
+ end
107
+
108
+
89
109
  Overriding defaults
90
110
  -------------------
91
111
 
@@ -214,16 +234,18 @@ Then run your tests!
214
234
 
215
235
  rake
216
236
 
217
- Optional test matchers
218
- ----------------------
237
+ Testing
238
+ -------
219
239
 
220
- Clearance comes with test matchers that are compatible with RSpec and Test::Unit.
240
+ If you want to write Rails functional tests or controller specs with Clearance,
241
+ you'll need to require the included test helpers and matchers.
221
242
 
222
- To use them, require the test matchers. For example, in spec/support/clearance.rb:
243
+ For example, in spec/support/clearance.rb or test/test_helper.rb:
223
244
 
224
245
  require 'clearance/testing'
225
246
 
226
- You'll then have access to methods like:
247
+ This will make Clearance::Authentication methods work in your controllers
248
+ during functional tests and provide access to helper methods like:
227
249
 
228
250
  sign_in
229
251
  sign_in_as(user)
data/Rakefile CHANGED
@@ -25,3 +25,5 @@ Cucumber::Rake::Task.new(:cucumber) do |t|
25
25
  t.fork = true
26
26
  t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
27
27
  end
28
+
29
+ Bundler::GemHelper.install_tasks
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.13.2
1
+ 0.14.0
data/clearance.gemspec CHANGED
@@ -30,7 +30,8 @@ Gem::Specification.new do |s|
30
30
  s.add_development_dependency('cucumber-rails', '~> 1.0.2')
31
31
  s.add_development_dependency('rspec-rails', '~> 2.6.0')
32
32
  s.add_development_dependency('sqlite3')
33
- s.add_development_dependency('mocha')
33
+ s.add_development_dependency('bourne')
34
+ s.add_development_dependency('timecop')
34
35
 
35
36
  if s.respond_to? :specification_version then
36
37
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -53,4 +53,3 @@ begin
53
53
  rescue NameError
54
54
  raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
55
55
  end
56
-
@@ -5,9 +5,9 @@ GIT
5
5
  shoulda-matchers (1.0.0.beta3)
6
6
 
7
7
  PATH
8
- remote: /Users/croaky/dev/clearance
8
+ remote: /Users/jferris/Source/clearance
9
9
  specs:
10
- clearance (0.12.0)
10
+ clearance (0.14.0)
11
11
  diesel (~> 0.1.5)
12
12
  rails (>= 3.0)
13
13
 
@@ -5,9 +5,9 @@ GIT
5
5
  shoulda-matchers (1.0.0.beta3)
6
6
 
7
7
  PATH
8
- remote: /Users/croaky/dev/clearance
8
+ remote: /Users/jferris/Source/clearance
9
9
  specs:
10
- clearance (0.12.0)
10
+ clearance (0.14.0)
11
11
  diesel (~> 0.1.5)
12
12
  rails (>= 3.0)
13
13
 
@@ -157,7 +157,7 @@ GEM
157
157
  sprockets (2.0.0)
158
158
  hike (~> 1.2)
159
159
  rack (~> 1.0)
160
- tilt (!= 1.3.0, ~> 1.1)
160
+ tilt (~> 1.1, != 1.3.0)
161
161
  spruz (0.2.13)
162
162
  sqlite3 (1.3.4)
163
163
  term-ansicolor (1.0.6)
data/lib/clearance.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'clearance/configuration'
2
+ require 'clearance/session'
3
+ require 'clearance/rack_session'
2
4
  require 'clearance/authentication'
3
5
  require 'clearance/user'
4
6
  require 'clearance/engine'
5
- require 'clearance/password_strategies'
7
+ require 'clearance/password_strategies'
@@ -10,32 +10,32 @@ module Clearance
10
10
  :authorize, :deny_access
11
11
  end
12
12
 
13
- # User in the current cookie
13
+ # Finds the user from the rack clearance session
14
14
  #
15
15
  # @return [User, nil]
16
16
  def current_user
17
- @_current_user ||= user_from_cookie
17
+ clearance_session.current_user
18
18
  end
19
19
 
20
20
  # Set the current user
21
21
  #
22
22
  # @param [User]
23
23
  def current_user=(user)
24
- @_current_user = user
24
+ clearance_session.sign_in user
25
25
  end
26
26
 
27
27
  # Is the current user signed in?
28
28
  #
29
29
  # @return [true, false]
30
30
  def signed_in?
31
- ! current_user.nil?
31
+ clearance_session.signed_in?
32
32
  end
33
33
 
34
34
  # Is the current user signed out?
35
35
  #
36
36
  # @return [true, false]
37
37
  def signed_out?
38
- current_user.nil?
38
+ !signed_in?
39
39
  end
40
40
 
41
41
  # Sign user in to cookie.
@@ -45,13 +45,7 @@ module Clearance
45
45
  # @example
46
46
  # sign_in(@user)
47
47
  def sign_in(user)
48
- if user
49
- cookies[:remember_token] = {
50
- :value => user.remember_token,
51
- :expires => Clearance.configuration.cookie_expiration.call
52
- }
53
- self.current_user = user
54
- end
48
+ clearance_session.sign_in user
55
49
  end
56
50
 
57
51
  # Sign user out of cookie.
@@ -59,9 +53,7 @@ module Clearance
59
53
  # @example
60
54
  # sign_out
61
55
  def sign_out
62
- current_user.reset_remember_token! if current_user
63
- cookies.delete(:remember_token)
64
- self.current_user = nil
56
+ clearance_session.sign_out
65
57
  end
66
58
 
67
59
  # Find the user by the given params or return nil.
@@ -107,10 +99,8 @@ module Clearance
107
99
 
108
100
  protected
109
101
 
110
- def user_from_cookie
111
- if token = cookies[:remember_token]
112
- ::User.find_by_remember_token(token)
113
- end
102
+ def clearance_session
103
+ request.env[:clearance]
114
104
  end
115
105
 
116
106
  def store_location
@@ -6,5 +6,7 @@ module Clearance
6
6
  initializer "clearance.filter" do |app|
7
7
  app.config.filter_parameters += [:token, :password]
8
8
  end
9
+
10
+ config.app_middleware.insert_after ActionDispatch::Cookies, Clearance::RackSession
9
11
  end
10
12
  end
@@ -0,0 +1,15 @@
1
+ module Clearance
2
+ class RackSession
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ session = Clearance::Session.new(env)
9
+ env[:clearance] = session
10
+ response = @app.call(env)
11
+ session.add_cookie_to_headers response[1]
12
+ response
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ module Clearance
2
+ class Session
3
+ REMEMBER_TOKEN_COOKIE = "remember_token".freeze
4
+
5
+ def initialize(env)
6
+ @env = env
7
+ end
8
+
9
+ def signed_in?
10
+ current_user.present?
11
+ end
12
+
13
+ def current_user
14
+ @current_user ||= with_remember_token do |token|
15
+ ::User.find_by_remember_token(token)
16
+ end
17
+ end
18
+
19
+ def sign_in(user)
20
+ @current_user = user
21
+ end
22
+
23
+ def sign_out
24
+ current_user.reset_remember_token! if signed_in?
25
+ @current_user = nil
26
+ cookies.delete(REMEMBER_TOKEN_COOKIE)
27
+ end
28
+
29
+ def add_cookie_to_headers(headers)
30
+ if signed_in?
31
+ Rack::Utils.set_cookie_header!(headers,
32
+ REMEMBER_TOKEN_COOKIE,
33
+ :value => current_user.remember_token,
34
+ :expires => Clearance.configuration.cookie_expiration.call,
35
+ :path => "/")
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def with_remember_token
42
+ if token = remember_token
43
+ yield token
44
+ end
45
+ end
46
+
47
+ def remember_token
48
+ cookies[REMEMBER_TOKEN_COOKIE]
49
+ end
50
+
51
+ def cookies
52
+ @cookies ||= Rack::Request.new(@env).cookies
53
+ end
54
+ end
55
+ end
@@ -13,6 +13,11 @@ module Clearance
13
13
  def sign_out
14
14
  @controller.current_user = nil
15
15
  end
16
+
17
+ def setup_controller_request_and_response
18
+ super
19
+ @request.env[:clearance] = Clearance::Session.new(@request.env)
20
+ end
16
21
  end
17
22
  end
18
23
  end
@@ -67,92 +67,94 @@ module Clearance
67
67
  end
68
68
  end
69
69
 
70
- # Set the remember token.
71
- #
72
- # @deprecated Use {#reset_remember_token!} instead
73
- def remember_me!
74
- warn "[DEPRECATION] remember_me!: use reset_remember_token! instead"
75
- reset_remember_token!
76
- end
70
+ module InstanceMethods
71
+ # Set the remember token.
72
+ #
73
+ # @deprecated Use {#reset_remember_token!} instead
74
+ def remember_me!
75
+ warn "[DEPRECATION] remember_me!: use reset_remember_token! instead"
76
+ reset_remember_token!
77
+ end
77
78
 
78
- # Reset the remember token.
79
- #
80
- # @example
81
- # user.reset_remember_token!
82
- def reset_remember_token!
83
- generate_remember_token
84
- save(:validate => false)
85
- end
79
+ # Reset the remember token.
80
+ #
81
+ # @example
82
+ # user.reset_remember_token!
83
+ def reset_remember_token!
84
+ generate_remember_token
85
+ save(:validate => false)
86
+ end
86
87
 
87
- # Mark my account as forgotten password.
88
- #
89
- # @example
90
- # user.forgot_password!
91
- def forgot_password!
92
- generate_confirmation_token
93
- save(:validate => false)
94
- end
88
+ # Mark my account as forgotten password.
89
+ #
90
+ # @example
91
+ # user.forgot_password!
92
+ def forgot_password!
93
+ generate_confirmation_token
94
+ save(:validate => false)
95
+ end
95
96
 
96
- # Update my password.
97
- #
98
- # @return [true, false] password was updated or not
99
- # @example
100
- # user.update_password('new-password')
101
- def update_password(new_password)
102
- self.password_changing = true
103
- self.password = new_password
104
- if valid?
105
- self.confirmation_token = nil
106
- generate_remember_token
97
+ # Update my password.
98
+ #
99
+ # @return [true, false] password was updated or not
100
+ # @example
101
+ # user.update_password('new-password')
102
+ def update_password(new_password)
103
+ self.password_changing = true
104
+ self.password = new_password
105
+ if valid?
106
+ self.confirmation_token = nil
107
+ generate_remember_token
108
+ end
109
+ save
107
110
  end
108
- save
109
- end
110
111
 
111
- def password=(unencrypted_password)
112
- @password = unencrypted_password
113
- encrypt_password
114
- end
112
+ def password=(unencrypted_password)
113
+ @password = unencrypted_password
114
+ encrypt_password
115
+ end
115
116
 
116
- protected
117
+ protected
117
118
 
118
- def generate_random_code(length = 20)
119
- if RUBY_VERSION >= '1.9'
120
- SecureRandom.hex(length).encode('UTF-8')
121
- else
122
- SecureRandom.hex(length)
119
+ def generate_random_code(length = 20)
120
+ if RUBY_VERSION >= '1.9'
121
+ SecureRandom.hex(length).encode('UTF-8')
122
+ else
123
+ SecureRandom.hex(length)
124
+ end
123
125
  end
124
- end
125
126
 
126
- def generate_remember_token
127
- self.remember_token = generate_random_code
128
- end
127
+ def generate_remember_token
128
+ self.remember_token = generate_random_code
129
+ end
129
130
 
130
- def generate_confirmation_token
131
- self.confirmation_token = generate_random_code
132
- end
131
+ def generate_confirmation_token
132
+ self.confirmation_token = generate_random_code
133
+ end
133
134
 
134
- # Always false. Override to allow other forms of authentication
135
- # (username, facebook, etc).
136
- # @return [Boolean] true if the email field be left blank for this user
137
- def email_optional?
138
- false
139
- end
135
+ # Always false. Override to allow other forms of authentication
136
+ # (username, facebook, etc).
137
+ # @return [Boolean] true if the email field be left blank for this user
138
+ def email_optional?
139
+ false
140
+ end
140
141
 
141
- # True if the password has been set and the password is not being
142
- # updated and we are not updating the password. Override to allow
143
- # other forms of authentication (username, facebook, etc).
144
- # @return [Boolean] true if the password field can be left blank for this user
145
- def password_optional?
146
- encrypted_password.present? && password.blank? && password_changing.blank?
147
- end
142
+ # True if the password has been set and the password is not being
143
+ # updated and we are not updating the password. Override to allow
144
+ # other forms of authentication (username, facebook, etc).
145
+ # @return [Boolean] true if the password field can be left blank for this user
146
+ def password_optional?
147
+ encrypted_password.present? && password.blank? && password_changing.blank?
148
+ end
148
149
 
149
- def password_required?
150
- # warn "[DEPRECATION] password_required?: use !password_optional? instead"
151
- !password_optional?
152
- end
150
+ def password_required?
151
+ # warn "[DEPRECATION] password_required?: use !password_optional? instead"
152
+ !password_optional?
153
+ end
153
154
 
154
- def downcase_email
155
- self.email = email.to_s.downcase
155
+ def downcase_email
156
+ self.email = email.to_s.downcase
157
+ end
156
158
  end
157
159
  end
158
160
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Clearance::RackSession do
4
+ it "injects a clearance session into the environment" do
5
+ expected_session = "the session"
6
+ expected_session.stubs(:add_cookie_to_headers)
7
+ Clearance::Session.stubs(:new => expected_session)
8
+ headers = { "X-Roaring-Lobster" => "Red" }
9
+
10
+ app = Rack::Builder.new do
11
+ use Clearance::RackSession
12
+ run lambda { |env| Rack::Response.new(env[:clearance], 200, headers).finish }
13
+ end
14
+
15
+ env = Rack::MockRequest.env_for("/")
16
+
17
+ response = Rack::MockResponse.new(*app.call(env))
18
+
19
+ Clearance::Session.should have_received(:new).with(env)
20
+ response.body.should == expected_session
21
+ expected_session.should have_received(:add_cookie_to_headers).with(has_entries(headers))
22
+ end
23
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe Clearance::Session do
4
+ before { Timecop.freeze }
5
+ after { Timecop.return }
6
+
7
+ it "finds a user from a cookie" do
8
+ user = Factory(:user)
9
+ env = env_with_remember_token(user.remember_token)
10
+
11
+ session = Clearance::Session.new(env)
12
+ session.should be_signed_in
13
+ session.current_user.should == user
14
+ end
15
+
16
+ it "returns nil for an unknown user" do
17
+ user = Factory(:user)
18
+ env = env_with_remember_token("bogus")
19
+
20
+ session = Clearance::Session.new(env)
21
+ session.should_not be_signed_in
22
+ session.current_user.should be_nil
23
+ end
24
+
25
+ it "returns nil without a remember token" do
26
+ env = env_without_remember_token
27
+ session = Clearance::Session.new(env)
28
+ session.should_not be_signed_in
29
+ session.current_user.should be_nil
30
+ end
31
+
32
+ it "signs in a given user" do
33
+ user = Factory(:user)
34
+ session = Clearance::Session.new(env_without_remember_token)
35
+ session.sign_in user
36
+ session.current_user.should == user
37
+ end
38
+
39
+ it "sets a remember token cookie with a default expiration of 1 year from now" do
40
+ user = Factory(:user)
41
+ headers = {}
42
+ session = Clearance::Session.new(env_without_remember_token)
43
+ session.sign_in user
44
+ session.add_cookie_to_headers headers
45
+ headers.should set_cookie("remember_token", user.remember_token, 1.year.from_now)
46
+ end
47
+
48
+ it "sets a remember token cookie with a custom expiration" do
49
+ custom_expiration = 1.day.from_now
50
+ with_custom_expiration 1.day.from_now do
51
+ user = Factory(:user)
52
+ headers = {}
53
+ session = Clearance::Session.new(env_without_remember_token)
54
+ session.sign_in user
55
+ session.add_cookie_to_headers headers
56
+ headers.should set_cookie("remember_token", user.remember_token, 1.day.from_now)
57
+ Clearance.configuration.cookie_expiration.call.should be_within(100).of(1.year.from_now)
58
+ end
59
+ end
60
+
61
+ it "doesn't set a remember token when signed out" do
62
+ headers = {}
63
+ session = Clearance::Session.new(env_without_remember_token)
64
+ session.add_cookie_to_headers headers
65
+ headers.should_not set_cookie("remember_token")
66
+ end
67
+
68
+ it "signs out a user" do
69
+ user = Factory(:user)
70
+ old_remember_token = user.remember_token
71
+ env = env_with_remember_token(old_remember_token)
72
+
73
+ session = Clearance::Session.new(env)
74
+ session.sign_out
75
+ session.current_user.should be_nil
76
+ user.reload.remember_token.should_not == old_remember_token
77
+ end
78
+
79
+ def env_with_remember_token(token)
80
+ env_with_cookies("remember_token" => token)
81
+ end
82
+
83
+ def env_without_remember_token
84
+ env_with_cookies({})
85
+ end
86
+
87
+ def env_with_cookies(cookies)
88
+ Rack::MockRequest.env_for("/", "HTTP_COOKIE" => serialize_cookies(cookies))
89
+ end
90
+
91
+ def serialize_cookies(hash)
92
+ header = {}
93
+ hash.each do |key, value|
94
+ Rack::Utils.set_cookie_header!(header, key, value)
95
+ end
96
+ header['Set-Cookie']
97
+ end
98
+
99
+ def with_custom_expiration(custom_duration)
100
+ Clearance.configuration.cookie_expiration = lambda { custom_duration }
101
+ ensure
102
+ restore_default_config
103
+ end
104
+
105
+ def restore_default_config
106
+ Clearance.configuration = nil
107
+ Clearance.configure {}
108
+ end
109
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ class FlashesController < ActionController::Base
4
+ include Clearance::Authentication
5
+
6
+ def set_flash
7
+ flash[:notice] = params[:message]
8
+ redirect_to view_flash_url
9
+ end
10
+
11
+ def view_flash
12
+ render :text => "<html><body>#{flash[:notice]}</body></html>"
13
+ end
14
+ end
15
+
16
+ describe FlashesController do
17
+ before do
18
+ Rails.application.routes.draw do
19
+ match "set_flash" => "flashes#set_flash"
20
+ match "view_flash" => "flashes#view_flash"
21
+ end
22
+ end
23
+
24
+ after do
25
+ Rails.application.reload_routes!
26
+ end
27
+
28
+ it "sets and views a flash" do
29
+ visit "/set_flash?message=hello"
30
+ page.should have_content("hello")
31
+ end
32
+ end
@@ -20,12 +20,8 @@ describe Clearance::SessionsController do
20
20
 
21
21
  it { should redirect_to_url_after_create }
22
22
 
23
- it "sets a remember token cookie" do
24
- should set_cookie("remember_token", "old-token", Clearance.configuration.cookie_expiration.call)
25
- end
26
-
27
- it "should have a default of 1 year from now" do
28
- Clearance.configuration.cookie_expiration.call.should be_within(100).of(1.year.from_now)
23
+ it "sets the user in the clearance session" do
24
+ controller.current_user.should == @user
29
25
  end
30
26
 
31
27
  it "should not change the remember token" do
@@ -33,50 +29,6 @@ describe Clearance::SessionsController do
33
29
  end
34
30
  end
35
31
 
36
- describe "on POST to #create with good credentials - cookie duration set to 2 weeks" do
37
- custom_duration = 2.weeks.from_now.utc
38
-
39
- before do
40
- Clearance.configuration.cookie_expiration = lambda { custom_duration }
41
- @user = Factory(:user)
42
- @user.update_attribute(:remember_token, "old-token2")
43
- post :create, :session => {
44
- :email => @user.email,
45
- :password => @user.password }
46
- end
47
-
48
- it "sets a remember token cookie" do
49
- should set_cookie("remember_token", "old-token2", custom_duration)
50
- end
51
-
52
- after do
53
- # restore default Clearance configuration
54
- Clearance.configuration = nil
55
- Clearance.configure {}
56
- end
57
- end
58
-
59
- describe "on POST to #create with good credentials - cookie expiration set to nil (session cookie)" do
60
- before do
61
- Clearance.configuration.cookie_expiration = lambda { nil }
62
- @user = Factory(:user)
63
- @user.update_attribute(:remember_token, "old-token3")
64
- post :create, :session => {
65
- :email => @user.email,
66
- :password => @user.password }
67
- end
68
-
69
- it "unsets a remember token cookie" do
70
- should set_cookie("remember_token", "old-token3", nil)
71
- end
72
-
73
- after do
74
- # restore default Clearance configuration
75
- Clearance.configuration = nil
76
- Clearance.configure {}
77
- end
78
- end
79
-
80
32
  describe "on POST to #create with good credentials and a session return url" do
81
33
  before do
82
34
  @user = Factory(:user)
@@ -141,10 +93,6 @@ describe Clearance::SessionsController do
141
93
 
142
94
  it { should redirect_to_url_after_destroy }
143
95
 
144
- it "should delete the cookie token" do
145
- cookies['remember_token'].should be_nil
146
- end
147
-
148
96
  it "should reset the remember token" do
149
97
  @user.reload.remember_token.should_not == "old-token"
150
98
  end
data/spec/spec_helper.rb CHANGED
@@ -10,6 +10,8 @@ Bundler.require
10
10
 
11
11
  require 'diesel/testing'
12
12
  require 'rspec/rails'
13
+ require 'bourne'
14
+ require 'timecop'
13
15
 
14
16
  require 'clearance/testing'
15
17
 
@@ -1,27 +1,29 @@
1
- RSpec::Matchers.define :set_cookie do |name, value, expected_expires_at|
1
+ RSpec::Matchers.define :set_cookie do |name, expected_value, expected_expires_at|
2
2
  match do |subject|
3
- @response = subject.response
4
- @name = name
5
- @value = value
3
+ @headers = subject
4
+ @expected_name = name
5
+ @expected_value = expected_value
6
6
  @expected_expires_at = expected_expires_at
7
7
 
8
8
  extract_cookies
9
9
  find_expected_cookie
10
10
  parse_expiration
11
+ parse_value
12
+ parse_path
11
13
 
12
14
  ensure_cookie_set
13
- ensure_value_correct
14
15
  ensure_expiration_correct
16
+ ensure_path_is_correct
15
17
  end
16
18
 
17
19
  def extract_cookies
18
- @cookie_headers = @response.headers['Set-Cookie'] || []
20
+ @cookie_headers = @headers['Set-Cookie'] || []
19
21
  @cookie_headers = [@cookie_headers] if @cookie_headers.respond_to?(:to_str)
20
22
  end
21
23
 
22
24
  def find_expected_cookie
23
25
  @cookie = @cookie_headers.detect do |header|
24
- header =~ /^#{@name}=[^;]*(;|$)/
26
+ header =~ /^#{@expected_name}=[^;]*(;|$)/
25
27
  end
26
28
  end
27
29
 
@@ -31,21 +33,29 @@ RSpec::Matchers.define :set_cookie do |name, value, expected_expires_at|
31
33
  end
32
34
  end
33
35
 
34
- def ensure_cookie_set
35
- @cookie.should_not be_nil
36
+ def parse_value
37
+ if @cookie && result = @cookie.match(/=(.*?)(?:;|$)/)
38
+ @value = result[1]
39
+ end
40
+ end
41
+
42
+ def parse_path
43
+ if @cookie && result = @cookie.match(/; path=(.*?)(;|$)/)
44
+ @path = result[1]
45
+ end
36
46
  end
37
47
 
38
- def ensure_value_correct
39
- @response.cookies[@name].should == @value
48
+ def ensure_cookie_set
49
+ @value.should == @expected_value
40
50
  end
41
51
 
42
52
  def ensure_expiration_correct
43
- if @expected_expires_at
44
- @expires_at.should_not be_nil
45
- @expires_at.should be_within(100).of(@expected_expires_at)
46
- else
47
- @expires_at.should be_nil
48
- end
53
+ @expires_at.should_not be_nil
54
+ @expires_at.should be_within(100).of(@expected_expires_at)
55
+ end
56
+
57
+ def ensure_path_is_correct
58
+ @path.should == "/"
49
59
  end
50
60
 
51
61
  failure_message do
@@ -53,20 +63,14 @@ RSpec::Matchers.define :set_cookie do |name, value, expected_expires_at|
53
63
  end
54
64
 
55
65
  def expectation
56
- base = "Expected a cookie named #{@name} with value #{@value.inspect} "
57
- if @expected_expires_at
58
- base << "expiring at #{@expected_expires_at.inspect}"
59
- else
60
- base << "with no expiration"
61
- end
62
- base
66
+ "a cookie named #{@expected_name} with value #{@expected_value.inspect} expiring at #{@expected_expires_at.inspect}"
63
67
  end
64
68
 
65
69
  def result
66
70
  if @cookie
67
- "value #{@value.inspect} expiring #{@expires_at.inspect}"
71
+ @cookie
68
72
  else
69
- "cookies #{@response.cookies.inspect}"
73
+ @cookie_headers.join("; ")
70
74
  end
71
75
  end
72
76
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clearance
3
3
  version: !ruby/object:Gem::Version
4
- hash: 47
4
+ hash: 39
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 13
9
- - 2
10
- version: 0.13.2
8
+ - 14
9
+ - 0
10
+ version: 0.14.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dan Croak
@@ -27,9 +27,7 @@ cert_chain: []
27
27
  date: 2012-01-13 00:00:00 Z
28
28
  dependencies:
29
29
  - !ruby/object:Gem::Dependency
30
- name: rails
31
- prerelease: false
32
- requirement: &id001 !ruby/object:Gem::Requirement
30
+ version_requirements: &id001 !ruby/object:Gem::Requirement
33
31
  none: false
34
32
  requirements:
35
33
  - - ">="
@@ -39,12 +37,12 @@ dependencies:
39
37
  - 3
40
38
  - 0
41
39
  version: "3.0"
40
+ requirement: *id001
42
41
  type: :runtime
43
- version_requirements: *id001
44
- - !ruby/object:Gem::Dependency
45
- name: diesel
46
42
  prerelease: false
47
- requirement: &id002 !ruby/object:Gem::Requirement
43
+ name: rails
44
+ - !ruby/object:Gem::Dependency
45
+ version_requirements: &id002 !ruby/object:Gem::Requirement
48
46
  none: false
49
47
  requirements:
50
48
  - - ~>
@@ -55,12 +53,12 @@ dependencies:
55
53
  - 1
56
54
  - 5
57
55
  version: 0.1.5
56
+ requirement: *id002
58
57
  type: :runtime
59
- version_requirements: *id002
60
- - !ruby/object:Gem::Dependency
61
- name: bundler
62
58
  prerelease: false
63
- requirement: &id003 !ruby/object:Gem::Requirement
59
+ name: diesel
60
+ - !ruby/object:Gem::Dependency
61
+ version_requirements: &id003 !ruby/object:Gem::Requirement
64
62
  none: false
65
63
  requirements:
66
64
  - - ~>
@@ -71,12 +69,12 @@ dependencies:
71
69
  - 0
72
70
  - 0
73
71
  version: 1.0.0
72
+ requirement: *id003
74
73
  type: :development
75
- version_requirements: *id003
76
- - !ruby/object:Gem::Dependency
77
- name: appraisal
78
74
  prerelease: false
79
- requirement: &id004 !ruby/object:Gem::Requirement
75
+ name: bundler
76
+ - !ruby/object:Gem::Dependency
77
+ version_requirements: &id004 !ruby/object:Gem::Requirement
80
78
  none: false
81
79
  requirements:
82
80
  - - ~>
@@ -87,12 +85,12 @@ dependencies:
87
85
  - 3
88
86
  - 8
89
87
  version: 0.3.8
88
+ requirement: *id004
90
89
  type: :development
91
- version_requirements: *id004
92
- - !ruby/object:Gem::Dependency
93
- name: cucumber-rails
94
90
  prerelease: false
95
- requirement: &id005 !ruby/object:Gem::Requirement
91
+ name: appraisal
92
+ - !ruby/object:Gem::Dependency
93
+ version_requirements: &id005 !ruby/object:Gem::Requirement
96
94
  none: false
97
95
  requirements:
98
96
  - - ~>
@@ -103,12 +101,12 @@ dependencies:
103
101
  - 0
104
102
  - 2
105
103
  version: 1.0.2
104
+ requirement: *id005
106
105
  type: :development
107
- version_requirements: *id005
108
- - !ruby/object:Gem::Dependency
109
- name: rspec-rails
110
106
  prerelease: false
111
- requirement: &id006 !ruby/object:Gem::Requirement
107
+ name: cucumber-rails
108
+ - !ruby/object:Gem::Dependency
109
+ version_requirements: &id006 !ruby/object:Gem::Requirement
112
110
  none: false
113
111
  requirements:
114
112
  - - ~>
@@ -119,12 +117,12 @@ dependencies:
119
117
  - 6
120
118
  - 0
121
119
  version: 2.6.0
120
+ requirement: *id006
122
121
  type: :development
123
- version_requirements: *id006
124
- - !ruby/object:Gem::Dependency
125
- name: sqlite3
126
122
  prerelease: false
127
- requirement: &id007 !ruby/object:Gem::Requirement
123
+ name: rspec-rails
124
+ - !ruby/object:Gem::Dependency
125
+ version_requirements: &id007 !ruby/object:Gem::Requirement
128
126
  none: false
129
127
  requirements:
130
128
  - - ">="
@@ -133,12 +131,26 @@ dependencies:
133
131
  segments:
134
132
  - 0
135
133
  version: "0"
134
+ requirement: *id007
136
135
  type: :development
137
- version_requirements: *id007
136
+ prerelease: false
137
+ name: sqlite3
138
138
  - !ruby/object:Gem::Dependency
139
- name: mocha
139
+ version_requirements: &id008 !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ hash: 3
145
+ segments:
146
+ - 0
147
+ version: "0"
148
+ requirement: *id008
149
+ type: :development
140
150
  prerelease: false
141
- requirement: &id008 !ruby/object:Gem::Requirement
151
+ name: bourne
152
+ - !ruby/object:Gem::Dependency
153
+ version_requirements: &id009 !ruby/object:Gem::Requirement
142
154
  none: false
143
155
  requirements:
144
156
  - - ">="
@@ -147,8 +159,10 @@ dependencies:
147
159
  segments:
148
160
  - 0
149
161
  version: "0"
162
+ requirement: *id009
150
163
  type: :development
151
- version_requirements: *id008
164
+ prerelease: false
165
+ name: timecop
152
166
  description: Rails authentication & authorization with email & password.
153
167
  email: support@thoughtbot.com
154
168
  executables: []
@@ -209,6 +223,8 @@ files:
209
223
  - lib/clearance/engine.rb
210
224
  - lib/clearance/password_strategies.rb
211
225
  - lib/clearance/password_strategies/sha1.rb
226
+ - lib/clearance/rack_session.rb
227
+ - lib/clearance/session.rb
212
228
  - lib/clearance/testing.rb
213
229
  - lib/clearance/testing/assertion_error.rb
214
230
  - lib/clearance/testing/deny_access_matcher.rb
@@ -221,7 +237,10 @@ files:
221
237
  - lib/generators/clearance/install/templates/db/migrate/upgrade_clearance_to_diesel.rb
222
238
  - lib/generators/clearance/install/templates/user.rb
223
239
  - lib/generators/clearance/views/views_generator.rb
240
+ - spec/clearance/rack_session_spec.rb
241
+ - spec/clearance/session_spec.rb
224
242
  - spec/controllers/denies_controller_spec.rb
243
+ - spec/controllers/flashes_controller_spec.rb
225
244
  - spec/controllers/forgeries_controller_spec.rb
226
245
  - spec/controllers/passwords_controller_spec.rb
227
246
  - spec/controllers/sessions_controller_spec.rb