devise 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

@@ -1,3 +1,12 @@
1
+ == 1.0.6
2
+
3
+ * bug fix
4
+ * Do not allow unlockable strategies based on time to access a controller.
5
+ * Do not send unlockable email several times.
6
+ * Allow controller to upstram custom! failures to Warden.
7
+
8
+ == 1.0.5
9
+
1
10
  * bug fix
2
11
  * Use prepend_before_filter in require_no_authentication.
3
12
  * require_no_authentication on unlockable.
data/Rakefile CHANGED
@@ -44,10 +44,10 @@ begin
44
44
  s.description = "Flexible authentication solution for Rails with Warden"
45
45
  s.authors = ['José Valim', 'Carlos Antônio']
46
46
  s.files = FileList["[A-Z]*", "{app,config,generators,lib}/**/*", "rails/init.rb"]
47
- s.add_dependency("warden", "~> 0.10.2")
47
+ s.add_dependency("warden", "~> 0.10.3")
48
48
  end
49
49
 
50
50
  Jeweler::GemcutterTasks.new
51
51
  rescue LoadError
52
- puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
52
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
53
53
  end
@@ -19,6 +19,8 @@ class SessionsController < ApplicationController
19
19
  if resource = authenticate(resource_name)
20
20
  set_flash_message :notice, :signed_in
21
21
  sign_in_and_redirect(resource_name, resource, true)
22
+ elsif [:custom, :redirect].include?(warden.result)
23
+ throw :warden, :scope => resource_name
22
24
  else
23
25
  set_now_flash_message :alert, (warden.message || :invalid)
24
26
  clean_up_passwords(build_resource)
@@ -1,4 +1,5 @@
1
1
  class UnlocksController < ApplicationController
2
+ prepend_before_filter :ensure_email_as_unlock_strategy
2
3
  prepend_before_filter :require_no_authentication
3
4
  include Devise::Controllers::InternalHelpers
4
5
 
@@ -31,4 +32,10 @@ class UnlocksController < ApplicationController
31
32
  render_with_scope :new
32
33
  end
33
34
  end
35
+
36
+ protected
37
+
38
+ def ensure_email_as_unlock_strategy
39
+ raise ActionController::UnknownAction unless resource_class.unlock_strategy_enabled?(:email)
40
+ end
34
41
  end
@@ -1,7 +1,7 @@
1
1
  class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table(:<%= table_name %>) do |t|
4
- t.authenticatable :encryptor => :sha1, :null => false
4
+ t.database_authenticatable :null => false
5
5
  t.confirmable
6
6
  t.recoverable
7
7
  t.rememberable
@@ -29,7 +29,7 @@ module Devise
29
29
  ALL = []
30
30
 
31
31
  # Authentication ones first
32
- ALL.push :authenticatable, :http_authenticatable, :token_authenticatable, :rememberable
32
+ ALL.push :database_authenticatable, :http_authenticatable, :token_authenticatable, :rememberable
33
33
 
34
34
  # Misc after
35
35
  ALL.push :recoverable, :registerable, :validatable
@@ -42,7 +42,7 @@ module Devise
42
42
 
43
43
  # Maps controller names to devise modules.
44
44
  CONTROLLERS = {
45
- :sessions => [:authenticatable, :token_authenticatable],
45
+ :sessions => [:database_authenticatable, :token_authenticatable],
46
46
  :passwords => [:recoverable],
47
47
  :confirmations => [:confirmable],
48
48
  :registrations => [:registerable],
@@ -52,7 +52,7 @@ module Devise
52
52
  # Routes for generating url helpers.
53
53
  ROUTES = [:session, :password, :confirmation, :registration, :unlock]
54
54
 
55
- STRATEGIES = [:rememberable, :http_authenticatable, :token_authenticatable, :authenticatable]
55
+ STRATEGIES = [:rememberable, :http_authenticatable, :token_authenticatable, :database_authenticatable]
56
56
 
57
57
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
58
58
 
@@ -103,6 +103,10 @@ module Devise
103
103
  end
104
104
  end
105
105
 
106
+ def authenticatable?
107
+ @authenticatable ||= self.for.any? { |m| m.to_s =~ /authenticatable/ }
108
+ end
109
+
106
110
  # Create magic predicates for verifying what module is activated by this map.
107
111
  # Example:
108
112
  #
@@ -1,7 +1,7 @@
1
1
  module Devise
2
2
  module Models
3
3
  autoload :Activatable, 'devise/models/activatable'
4
- autoload :Authenticatable, 'devise/models/authenticatable'
4
+ autoload :DatabaseAuthenticatable, 'devise/models/database_authenticatable'
5
5
  autoload :Confirmable, 'devise/models/confirmable'
6
6
  autoload :Lockable, 'devise/models/lockable'
7
7
  autoload :Recoverable, 'devise/models/recoverable'
@@ -57,7 +57,12 @@ module Devise
57
57
  #
58
58
  def devise(*modules)
59
59
  raise "You need to give at least one Devise module" if modules.empty?
60
- options = modules.extract_options!
60
+ options = modules.extract_options!
61
+
62
+ if modules.delete(:authenticatable)
63
+ ActiveSupport::Deprecation.warn ":authenticatable as module is deprecated. Please give :database_authenticatable instead.", caller
64
+ modules << :database_authenticatable
65
+ end
61
66
 
62
67
  @devise_modules = Devise::ALL & modules.map(&:to_sym).uniq
63
68
 
@@ -60,15 +60,9 @@ module Devise
60
60
  ::DeviseMailer.deliver_confirmation_instructions(self)
61
61
  end
62
62
 
63
- # Remove confirmation date and send confirmation instructions, to ensure
64
- # after sending these instructions the user won't be able to sign in without
65
- # confirming it's account
63
+ # Resend confirmation token. This method does not need to generate a new token.
66
64
  def resend_confirmation_token
67
- unless_confirmed do
68
- generate_confirmation_token
69
- save(false)
70
- send_confirmation_instructions
71
- end
65
+ unless_confirmed { send_confirmation_instructions }
72
66
  end
73
67
 
74
68
  # Overwrites active? from Devise::Models::Activatable for confirmation
@@ -1,4 +1,4 @@
1
- require 'devise/strategies/authenticatable'
1
+ require 'devise/strategies/database_authenticatable'
2
2
 
3
3
  module Devise
4
4
  module Models
@@ -26,7 +26,7 @@ module Devise
26
26
  # User.authenticate('email@test.com', 'password123') # returns authenticated user or nil
27
27
  # User.find(1).valid_password?('password123') # returns true/false
28
28
  #
29
- module Authenticatable
29
+ module DatabaseAuthenticatable
30
30
  def self.included(base)
31
31
  base.class_eval do
32
32
  extend ClassMethods
@@ -58,12 +58,6 @@ module Devise
58
58
  password_digest(incoming_password) == self.encrypted_password
59
59
  end
60
60
 
61
- # Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
62
- # is the user authentication token.
63
- def valid_authentication_token?(incoming_auth_token)
64
- incoming_auth_token == self.authentication_token
65
- end
66
-
67
61
  # Checks if a resource is valid upon authentication.
68
62
  def valid_for_authentication?(attributes)
69
63
  valid_password?(attributes[:password])
@@ -28,9 +28,10 @@ module Devise
28
28
 
29
29
  # Lock an user setting it's locked_at to actual time.
30
30
  def lock_access!
31
+ return true if access_locked?
31
32
  self.locked_at = Time.now
32
33
 
33
- if unlock_strategy_enabled?(:email)
34
+ if self.class.unlock_strategy_enabled?(:email)
34
35
  generate_unlock_token
35
36
  send_unlock_instructions
36
37
  end
@@ -60,11 +61,7 @@ module Devise
60
61
 
61
62
  # Resend the unlock instructions if the user is locked.
62
63
  def resend_unlock_token
63
- if_access_locked do
64
- generate_unlock_token unless unlock_token.present?
65
- save(false)
66
- send_unlock_instructions
67
- end
64
+ if_access_locked { send_unlock_instructions }
68
65
  end
69
66
 
70
67
  # Overwrites active? from Devise::Models::Activatable for locking purposes
@@ -87,10 +84,7 @@ module Devise
87
84
  self.failed_attempts = 0
88
85
  else
89
86
  self.failed_attempts += 1
90
- if failed_attempts > self.class.maximum_attempts
91
- lock_access!
92
- return false
93
- end
87
+ lock_access! if failed_attempts > self.class.maximum_attempts
94
88
  end
95
89
  save(false) if changed?
96
90
  result
@@ -105,7 +99,7 @@ module Devise
105
99
 
106
100
  # Tells if the lock is expired if :time unlock strategy is active
107
101
  def lock_expired?
108
- if unlock_strategy_enabled?(:time)
102
+ if self.class.unlock_strategy_enabled?(:time)
109
103
  locked_at && locked_at < self.class.unlock_in.ago
110
104
  else
111
105
  false
@@ -123,11 +117,6 @@ module Devise
123
117
  end
124
118
  end
125
119
 
126
- # Is the unlock enabled for the given unlock strategy?
127
- def unlock_strategy_enabled?(strategy)
128
- [:both, strategy].include?(self.class.unlock_strategy)
129
- end
130
-
131
120
  module ClassMethods
132
121
  # Attempt to find a user by it's email. If a record is found, send new
133
122
  # unlock instructions to it. If not user is found, returns a new user
@@ -149,6 +138,11 @@ module Devise
149
138
  lockable
150
139
  end
151
140
 
141
+ # Is the unlock enabled for the given unlock strategy?
142
+ def unlock_strategy_enabled?(strategy)
143
+ [:both, strategy].include?(self.unlock_strategy)
144
+ end
145
+
152
146
  Devise::Models.config(self, :maximum_attempts, :unlock_strategy, :unlock_in)
153
147
  end
154
148
  end
@@ -97,7 +97,7 @@ module ActionController::Routing
97
97
 
98
98
  protected
99
99
 
100
- def authenticatable(routes, mapping)
100
+ def database_authenticatable(routes, mapping)
101
101
  routes.with_options(:controller => 'sessions', :name_prefix => nil) do |session|
102
102
  session.send(:"new_#{mapping.name}_session", mapping.path_names[:sign_in], :action => 'new', :conditions => { :method => :get })
103
103
  session.send(:"#{mapping.name}_session", mapping.path_names[:sign_in], :action => 'create', :conditions => { :method => :post })
@@ -3,41 +3,48 @@ module Devise
3
3
  # and overwrite the apply_schema method.
4
4
  module Schema
5
5
 
6
+ def authenticatable(*args)
7
+ ActiveSupport::Deprecation.warn "t.authenticatable in migrations is deprecated. Please use t.database_authenticatable instead.", caller
8
+ database_authenticatable(*args)
9
+ end
10
+
6
11
  # Creates email, encrypted_password and password_salt.
7
12
  #
8
13
  # == Options
9
14
  # * :null - When true, allow columns to be null.
10
- # * :encryptor - The encryptor going to be used, necessary for setting the proper encrypter password length.
11
- def authenticatable(options={})
12
- null = options[:null] || false
13
- default = options[:default]
14
- encryptor = options[:encryptor] || (respond_to?(:encryptor) ? self.encryptor : :sha1)
15
+ def database_authenticatable(options={})
16
+ null = options[:null] || false
17
+ default = options[:default] || ""
18
+
19
+ if options.delete(:encryptor)
20
+ ActiveSupport::Deprecation.warn ":encryptor as option is deprecated, simply remove it."
21
+ end
15
22
 
16
23
  apply_schema :email, String, :null => null, :default => default
17
- apply_schema :encrypted_password, String, :null => null, :default => default, :limit => Devise::ENCRYPTORS_LENGTH[encryptor]
24
+ apply_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
18
25
  apply_schema :password_salt, String, :null => null, :default => default
19
26
  end
20
27
 
21
28
  # Creates authentication_token.
22
29
  def token_authenticatable
23
- apply_schema :authentication_token, String, :limit => 20
30
+ apply_schema :authentication_token, String
24
31
  end
25
32
 
26
33
  # Creates confirmation_token, confirmed_at and confirmation_sent_at.
27
34
  def confirmable
28
- apply_schema :confirmation_token, String, :limit => 20
35
+ apply_schema :confirmation_token, String
29
36
  apply_schema :confirmed_at, DateTime
30
37
  apply_schema :confirmation_sent_at, DateTime
31
38
  end
32
39
 
33
40
  # Creates reset_password_token.
34
41
  def recoverable
35
- apply_schema :reset_password_token, String, :limit => 20
42
+ apply_schema :reset_password_token, String
36
43
  end
37
44
 
38
45
  # Creates remember_token and remember_created_at.
39
46
  def rememberable
40
- apply_schema :remember_token, String, :limit => 20
47
+ apply_schema :remember_token, String
41
48
  apply_schema :remember_created_at, DateTime
42
49
  end
43
50
 
@@ -54,7 +61,7 @@ module Devise
54
61
  # Creates failed_attempts, unlock_token and locked_at
55
62
  def lockable
56
63
  apply_schema :failed_attempts, Integer, :default => 0
57
- apply_schema :unlock_token, String, :limit => 20
64
+ apply_schema :unlock_token, String
58
65
  apply_schema :locked_at, DateTime
59
66
  end
60
67
 
@@ -4,7 +4,7 @@ module Devise
4
4
  module Strategies
5
5
  # Default strategy for signing in a user, based on his email and password.
6
6
  # Redirects to sign_in page if it's not authenticated
7
- class Authenticatable < Base
7
+ class DatabaseAuthenticatable < Base
8
8
  def valid?
9
9
  valid_controller? && valid_params? && mapping.to.respond_to?(:authenticate)
10
10
  end
@@ -16,7 +16,7 @@ module Devise
16
16
  if resource = mapping.to.authenticate(params[scope])
17
17
  success!(resource)
18
18
  else
19
- fail!(:invalid)
19
+ fail(:invalid)
20
20
  end
21
21
  end
22
22
 
@@ -33,4 +33,4 @@ module Devise
33
33
  end
34
34
  end
35
35
 
36
- Warden::Strategies.add(:authenticatable, Devise::Strategies::Authenticatable)
36
+ Warden::Strategies.add(:database_authenticatable, Devise::Strategies::DatabaseAuthenticatable)
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "1.0.5".freeze
2
+ VERSION = "1.0.6".freeze
3
3
  end
@@ -25,7 +25,7 @@ class DeviseTest < ActiveSupport::TestCase
25
25
  Devise.configure_warden(config)
26
26
 
27
27
  assert_equal Devise::FailureApp, config.failure_app
28
- assert_equal [:rememberable, :http_authenticatable, :token_authenticatable, :authenticatable], config.default_strategies
28
+ assert_equal [:rememberable, :http_authenticatable, :token_authenticatable, :database_authenticatable], config.default_strategies
29
29
  assert_equal :user, config.default_scope
30
30
  assert config.silence_missing_strategies?
31
31
  end
@@ -36,6 +36,16 @@ class LockTest < ActionController::IntegrationTest
36
36
  assert_equal 0, ActionMailer::Base.deliveries.size
37
37
  end
38
38
 
39
+ test 'unlocked pages should not be available if email strategy is disabled' do
40
+ visit new_user_unlock_path
41
+ assert_response :success
42
+
43
+ swap Devise, :unlock_strategy => :time do
44
+ visit new_user_unlock_path
45
+ assert_response :not_found
46
+ end
47
+ end
48
+
39
49
  test 'user with invalid unlock token should not be able to unlock an account' do
40
50
  visit_user_unlock_with_token('invalid_token')
41
51
 
@@ -60,7 +70,6 @@ class LockTest < ActionController::IntegrationTest
60
70
  test "sign in user automatically after unlocking it's account" do
61
71
  user = create_user(:locked => true)
62
72
  visit_user_unlock_with_token(user.unlock_token)
63
-
64
73
  assert warden.authenticated?(:user)
65
74
  end
66
75
 
@@ -71,6 +80,16 @@ class LockTest < ActionController::IntegrationTest
71
80
  assert_not warden.authenticated?(:user)
72
81
  end
73
82
 
83
+ test "user should not send a new e-mail if already locked" do
84
+ user = create_user(:locked => true)
85
+ user.update_attribute(:failed_attempts, User.maximum_attempts + 1)
86
+ ActionMailer::Base.deliveries.clear
87
+
88
+ sign_in_as_user(:password => "invalid")
89
+ assert_contain 'Invalid email or password.'
90
+ assert ActionMailer::Base.deliveries.empty?
91
+ end
92
+
74
93
  test 'error message is configurable by resource name' do
75
94
  store_translations :en, :devise => {
76
95
  :sessions => { :admin => { :locked => "You are locked!" } }
@@ -0,0 +1,47 @@
1
+ require "test/test_helper"
2
+ require "rack/test"
3
+
4
+ class RackMiddlewareTest < Test::Unit::TestCase
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ ActionController::Dispatcher.new
9
+ end
10
+
11
+ def warden
12
+ last_request.env['warden']
13
+ end
14
+
15
+ def with_custom_strategy
16
+ get '/'
17
+
18
+ Warden::Strategies.add(:custom_test) do
19
+ def valid?
20
+ true
21
+ end
22
+
23
+ def authenticate!
24
+ custom! [599, {
25
+ "X-Custom-Response" => "Custom response test",
26
+ "Content-type" => "text/plain"
27
+ }, "Custom response test"]
28
+ end
29
+ end
30
+
31
+ #ActionController::Dispatcher.middleware.use CustomStrategyInterceptor
32
+ default_strategies = warden.manager.config.default_strategies
33
+ warden.manager.config.default_strategies :custom_test
34
+ yield
35
+ warden.manager.config.default_strategies default_strategies
36
+ end
37
+
38
+ def test_custom_strategy_response
39
+ with_custom_strategy do
40
+ post('/users/sign_in')
41
+
42
+ assert_equal 599, last_response.status
43
+ assert_equal "Custom response test", last_response.body
44
+ assert_equal "Custom response test", last_response.headers["X-Custom-Response"]
45
+ end
46
+ end
47
+ end
@@ -11,15 +11,6 @@ class ConfirmableTest < ActiveSupport::TestCase
11
11
  assert_not_nil create_user.confirmation_token
12
12
  end
13
13
 
14
- test 'should regenerate confirmation token each time' do
15
- user = create_user
16
- 3.times do
17
- token = user.confirmation_token
18
- user.resend_confirmation_token
19
- assert_not_equal token, user.confirmation_token
20
- end
21
- end
22
-
23
14
  test 'should never generate the same confirmation token for different users' do
24
15
  confirmation_tokens = []
25
16
  3.times do
@@ -137,13 +128,6 @@ class ConfirmableTest < ActiveSupport::TestCase
137
128
  assert_equal 'not found', confirmation_user.errors[:email]
138
129
  end
139
130
 
140
- test 'should generate a confirmation token before send the confirmation instructions email' do
141
- user = create_user
142
- token = user.confirmation_token
143
- confirmation_user = User.send_confirmation_instructions(:email => user.email)
144
- assert_not_equal token, user.reload.confirmation_token
145
- end
146
-
147
131
  test 'should send email instructions for the user confirm it\'s email' do
148
132
  user = create_user
149
133
  assert_email_sent do
@@ -36,7 +36,7 @@ class LockableTest < ActiveSupport::TestCase
36
36
  assert_equal 0, user.reload.failed_attempts
37
37
  end
38
38
 
39
- test "should verify wheter a user is locked or not" do
39
+ test "should verify whether a user is locked or not" do
40
40
  user = create_user
41
41
  assert_not user.access_locked?
42
42
  user.lock_access!
@@ -63,6 +63,14 @@ class LockableTest < ActiveSupport::TestCase
63
63
  assert 0, user.reload.failed_attempts
64
64
  end
65
65
 
66
+ test "should not lock a locked account" do
67
+ user = create_user
68
+ user.lock_access!
69
+ assert_no_difference "ActionMailer::Base.deliveries.size" do
70
+ user.lock_access!
71
+ end
72
+ end
73
+
66
74
  test 'should not unlock an unlocked user' do
67
75
  user = create_user
68
76
 
@@ -101,16 +109,6 @@ class LockableTest < ActiveSupport::TestCase
101
109
  assert_not_nil user.unlock_token
102
110
  end
103
111
 
104
- test 'should not regenerate unlock token if it already exists' do
105
- user = create_user
106
- user.lock!
107
- 3.times do
108
- token = user.unlock_token
109
- user.resend_unlock_token
110
- assert_equal token, user.unlock_token
111
- end
112
- end
113
-
114
112
  test "should never generate the same unlock token for different users" do
115
113
  unlock_tokens = []
116
114
  3.times do
@@ -23,12 +23,12 @@ class ActiveRecordTest < ActiveSupport::TestCase
23
23
  end
24
24
 
25
25
  test 'add modules cherry pick' do
26
- assert_include_modules Admin, :authenticatable, :registerable, :timeoutable
26
+ assert_include_modules Admin, :database_authenticatable, :registerable, :timeoutable
27
27
  end
28
28
 
29
29
  test 'order of module inclusion' do
30
- correct_module_order = [:authenticatable, :registerable, :timeoutable]
31
- incorrect_module_order = [:authenticatable, :timeoutable, :registerable]
30
+ correct_module_order = [:database_authenticatable, :registerable, :timeoutable]
31
+ incorrect_module_order = [:database_authenticatable, :timeoutable, :registerable]
32
32
 
33
33
  assert_include_modules Admin, *incorrect_module_order
34
34
 
@@ -32,7 +32,7 @@ class ActionController::IntegrationTest
32
32
  user = create_user(options)
33
33
  visit new_user_session_path unless options[:visit] == false
34
34
  fill_in 'email', :with => 'user@test.com'
35
- fill_in 'password', :with => '123456'
35
+ fill_in 'password', :with => options[:password] || '123456'
36
36
  check 'remember me' if options[:remember_me] == true
37
37
  yield if block_given?
38
38
  click_button 'Sign In'
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 5
9
- version: 1.0.5
8
+ - 6
9
+ version: 1.0.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Jos\xC3\xA9 Valim"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-03-26 00:00:00 +01:00
18
+ date: 2010-04-03 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -28,8 +28,8 @@ dependencies:
28
28
  segments:
29
29
  - 0
30
30
  - 10
31
- - 2
32
- version: 0.10.2
31
+ - 3
32
+ version: 0.10.3
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  description: Flexible authentication solution for Rails with Warden
@@ -95,8 +95,8 @@ files:
95
95
  - lib/devise/mapping.rb
96
96
  - lib/devise/models.rb
97
97
  - lib/devise/models/activatable.rb
98
- - lib/devise/models/authenticatable.rb
99
98
  - lib/devise/models/confirmable.rb
99
+ - lib/devise/models/database_authenticatable.rb
100
100
  - lib/devise/models/http_authenticatable.rb
101
101
  - lib/devise/models/lockable.rb
102
102
  - lib/devise/models/recoverable.rb
@@ -113,8 +113,8 @@ files:
113
113
  - lib/devise/rails/routes.rb
114
114
  - lib/devise/rails/warden_compat.rb
115
115
  - lib/devise/schema.rb
116
- - lib/devise/strategies/authenticatable.rb
117
116
  - lib/devise/strategies/base.rb
117
+ - lib/devise/strategies/database_authenticatable.rb
118
118
  - lib/devise/strategies/http_authenticatable.rb
119
119
  - lib/devise/strategies/rememberable.rb
120
120
  - lib/devise/strategies/token_authenticatable.rb
@@ -162,6 +162,7 @@ test_files:
162
162
  - test/integration/confirmable_test.rb
163
163
  - test/integration/http_authenticatable_test.rb
164
164
  - test/integration/lockable_test.rb
165
+ - test/integration/rack_middleware_test.rb
165
166
  - test/integration/recoverable_test.rb
166
167
  - test/integration/registerable_test.rb
167
168
  - test/integration/rememberable_test.rb