devise 3.2.4 → 4.0.0

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.

Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +33 -17
  4. data/CHANGELOG.md +57 -1033
  5. data/CODE_OF_CONDUCT.md +22 -0
  6. data/CONTRIBUTING.md +2 -0
  7. data/Gemfile +5 -5
  8. data/Gemfile.lock +138 -115
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +124 -65
  11. data/Rakefile +2 -1
  12. data/app/controllers/devise/confirmations_controller.rb +7 -3
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +8 -4
  14. data/app/controllers/devise/passwords_controller.rb +16 -6
  15. data/app/controllers/devise/registrations_controller.rb +22 -10
  16. data/app/controllers/devise/sessions_controller.rb +42 -14
  17. data/app/controllers/devise/unlocks_controller.rb +5 -2
  18. data/app/controllers/devise_controller.rb +63 -29
  19. data/app/mailers/devise/mailer.rb +4 -0
  20. data/app/views/devise/confirmations/new.html.erb +7 -3
  21. data/app/views/devise/mailer/password_change.html.erb +3 -0
  22. data/app/views/devise/passwords/edit.html.erb +14 -5
  23. data/app/views/devise/passwords/new.html.erb +7 -3
  24. data/app/views/devise/registrations/edit.html.erb +19 -9
  25. data/app/views/devise/registrations/new.html.erb +18 -7
  26. data/app/views/devise/sessions/new.html.erb +16 -7
  27. data/app/views/devise/shared/{_links.erb → _links.html.erb} +2 -2
  28. data/app/views/devise/unlocks/new.html.erb +7 -3
  29. data/bin/test +13 -0
  30. data/config/locales/en.yml +19 -16
  31. data/devise.gemspec +3 -4
  32. data/gemfiles/{Gemfile.rails-3.2-stable → Gemfile.rails-4.1-stable} +6 -6
  33. data/gemfiles/Gemfile.rails-4.1-stable.lock +167 -0
  34. data/gemfiles/{Gemfile.rails-head → Gemfile.rails-4.2-stable} +6 -6
  35. data/gemfiles/Gemfile.rails-4.2-stable.lock +189 -0
  36. data/gemfiles/Gemfile.rails-5.0-beta +37 -0
  37. data/gemfiles/Gemfile.rails-5.0-beta.lock +199 -0
  38. data/lib/devise/controllers/helpers.rb +94 -27
  39. data/lib/devise/controllers/rememberable.rb +9 -2
  40. data/lib/devise/controllers/sign_in_out.rb +2 -9
  41. data/lib/devise/controllers/store_location.rb +11 -3
  42. data/lib/devise/controllers/url_helpers.rb +7 -7
  43. data/lib/devise/encryptor.rb +22 -0
  44. data/lib/devise/failure_app.rb +72 -23
  45. data/lib/devise/hooks/activatable.rb +3 -4
  46. data/lib/devise/hooks/csrf_cleaner.rb +3 -1
  47. data/lib/devise/hooks/timeoutable.rb +13 -8
  48. data/lib/devise/mailers/helpers.rb +1 -1
  49. data/lib/devise/mapping.rb +6 -2
  50. data/lib/devise/models/authenticatable.rb +32 -28
  51. data/lib/devise/models/confirmable.rb +55 -22
  52. data/lib/devise/models/database_authenticatable.rb +32 -19
  53. data/lib/devise/models/lockable.rb +5 -5
  54. data/lib/devise/models/recoverable.rb +44 -20
  55. data/lib/devise/models/rememberable.rb +54 -27
  56. data/lib/devise/models/timeoutable.rb +0 -6
  57. data/lib/devise/models/trackable.rb +5 -3
  58. data/lib/devise/models/validatable.rb +3 -3
  59. data/lib/devise/models.rb +1 -1
  60. data/lib/devise/omniauth/url_helpers.rb +62 -4
  61. data/lib/devise/parameter_sanitizer.rb +176 -61
  62. data/lib/devise/rails/routes.rb +76 -59
  63. data/lib/devise/rails/warden_compat.rb +1 -10
  64. data/lib/devise/rails.rb +2 -11
  65. data/lib/devise/strategies/authenticatable.rb +15 -6
  66. data/lib/devise/strategies/database_authenticatable.rb +5 -4
  67. data/lib/devise/strategies/rememberable.rb +13 -3
  68. data/lib/devise/test_helpers.rb +12 -7
  69. data/lib/devise/token_generator.rb +1 -41
  70. data/lib/devise/version.rb +1 -1
  71. data/lib/devise.rb +150 -58
  72. data/lib/generators/active_record/devise_generator.rb +28 -4
  73. data/lib/generators/active_record/templates/migration.rb +3 -3
  74. data/lib/generators/active_record/templates/migration_existing.rb +3 -3
  75. data/lib/generators/devise/controllers_generator.rb +44 -0
  76. data/lib/generators/devise/install_generator.rb +15 -0
  77. data/lib/generators/devise/orm_helpers.rb +1 -18
  78. data/lib/generators/devise/views_generator.rb +14 -3
  79. data/lib/generators/templates/README +1 -1
  80. data/lib/generators/templates/controllers/README +14 -0
  81. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  82. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  83. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  84. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  85. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  86. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  87. data/lib/generators/templates/devise.rb +36 -28
  88. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  89. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  90. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  91. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  92. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  93. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  94. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +2 -2
  95. data/test/controllers/custom_registrations_controller_test.rb +40 -0
  96. data/test/controllers/custom_strategy_test.rb +7 -5
  97. data/test/controllers/helper_methods_test.rb +22 -0
  98. data/test/controllers/helpers_test.rb +41 -1
  99. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  100. data/test/controllers/internal_helpers_test.rb +19 -15
  101. data/test/controllers/load_hooks_controller_test.rb +19 -0
  102. data/test/controllers/passwords_controller_test.rb +5 -4
  103. data/test/controllers/sessions_controller_test.rb +24 -21
  104. data/test/controllers/url_helpers_test.rb +7 -1
  105. data/test/devise_test.rb +48 -8
  106. data/test/failure_app_test.rb +107 -19
  107. data/test/generators/active_record_generator_test.rb +6 -26
  108. data/test/generators/controllers_generator_test.rb +48 -0
  109. data/test/generators/install_generator_test.rb +14 -3
  110. data/test/generators/views_generator_test.rb +8 -1
  111. data/test/helpers/devise_helper_test.rb +10 -12
  112. data/test/integration/authenticatable_test.rb +37 -21
  113. data/test/integration/confirmable_test.rb +54 -14
  114. data/test/integration/database_authenticatable_test.rb +12 -1
  115. data/test/integration/http_authenticatable_test.rb +4 -5
  116. data/test/integration/lockable_test.rb +10 -9
  117. data/test/integration/omniauthable_test.rb +13 -11
  118. data/test/integration/recoverable_test.rb +28 -15
  119. data/test/integration/registerable_test.rb +41 -33
  120. data/test/integration/rememberable_test.rb +51 -7
  121. data/test/integration/timeoutable_test.rb +23 -22
  122. data/test/integration/trackable_test.rb +3 -3
  123. data/test/mailers/confirmation_instructions_test.rb +10 -10
  124. data/test/mailers/reset_password_instructions_test.rb +8 -8
  125. data/test/mailers/unlock_instructions_test.rb +8 -8
  126. data/test/mapping_test.rb +7 -0
  127. data/test/models/authenticatable_test.rb +11 -1
  128. data/test/models/confirmable_test.rb +91 -42
  129. data/test/models/database_authenticatable_test.rb +26 -6
  130. data/test/models/lockable_test.rb +29 -17
  131. data/test/models/recoverable_test.rb +74 -7
  132. data/test/models/rememberable_test.rb +68 -94
  133. data/test/models/trackable_test.rb +28 -0
  134. data/test/models/validatable_test.rb +9 -17
  135. data/test/models_test.rb +15 -6
  136. data/test/omniauth/url_helpers_test.rb +4 -7
  137. data/test/orm/active_record.rb +6 -1
  138. data/test/parameter_sanitizer_test.rb +103 -53
  139. data/test/rails_app/app/active_record/user.rb +1 -0
  140. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  141. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  142. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  143. data/test/rails_app/app/controllers/admins_controller.rb +1 -6
  144. data/test/rails_app/app/controllers/application_controller.rb +5 -2
  145. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  146. data/test/rails_app/app/controllers/custom/registrations_controller.rb +31 -0
  147. data/test/rails_app/app/controllers/home_controller.rb +5 -1
  148. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +3 -3
  149. data/test/rails_app/app/controllers/users_controller.rb +6 -6
  150. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  151. data/test/rails_app/app/mailers/users/mailer.rb +0 -9
  152. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  153. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  154. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  155. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  156. data/test/rails_app/config/application.rb +3 -3
  157. data/test/rails_app/config/boot.rb +4 -4
  158. data/test/rails_app/config/environments/production.rb +6 -2
  159. data/test/rails_app/config/environments/test.rb +13 -3
  160. data/test/rails_app/config/initializers/devise.rb +15 -16
  161. data/test/rails_app/config/initializers/secret_token.rb +1 -6
  162. data/test/rails_app/config/routes.rb +23 -3
  163. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -2
  164. data/test/rails_app/lib/shared_user.rb +1 -1
  165. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  166. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  167. data/test/rails_test.rb +9 -0
  168. data/test/routes_test.rb +33 -16
  169. data/test/support/assertions.rb +2 -3
  170. data/test/support/helpers.rb +13 -6
  171. data/test/support/http_method_compatibility.rb +51 -0
  172. data/test/support/integration.rb +4 -4
  173. data/test/support/webrat/integrations/rails.rb +9 -0
  174. data/test/test_helper.rb +7 -0
  175. data/test/test_helpers_test.rb +43 -38
  176. data/test/test_models.rb +3 -3
  177. metadata +77 -23
  178. data/gemfiles/Gemfile.rails-4.0-stable +0 -29
@@ -16,21 +16,24 @@ module Devise
16
16
  # Override process to consider warden.
17
17
  def process(*)
18
18
  # Make sure we always return @response, a la ActionController::TestCase::Behaviour#process, even if warden interrupts
19
- _catch_warden { super } || @response
19
+ _catch_warden { super } # || @response # _catch_warden will setup the @response object
20
+
21
+ # process needs to return the ActionDispath::TestResponse object
22
+ @response
20
23
  end
21
24
 
22
- # We need to setup the environment variables and the response in the controller.
25
+ # We need to set up the environment variables and the response in the controller.
23
26
  def setup_controller_for_warden #:nodoc:
24
27
  @request.env['action_controller.instance'] = @controller
25
28
  end
26
29
 
27
30
  # Quick access to Warden::Proxy.
28
31
  def warden #:nodoc:
29
- @warden ||= begin
32
+ @request.env['warden'] ||= begin
30
33
  manager = Warden::Manager.new(nil) do |config|
31
34
  config.merge! Devise.warden_config
32
35
  end
33
- @request.env['warden'] = Warden::Proxy.new(@request.env, manager)
36
+ Warden::Proxy.new(@request.env, manager)
34
37
  end
35
38
  end
36
39
 
@@ -109,8 +112,9 @@ module Devise
109
112
 
110
113
  status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
111
114
  @controller.response.headers.merge!(headers)
112
- @controller.send :render, status: status, text: response.body,
113
- content_type: headers["Content-Type"], location: headers["Location"]
115
+ r_opts = { status: status, content_type: headers["Content-Type"], location: headers["Location"] }
116
+ r_opts[Rails.version.start_with?('5') ? :body : :text] = response.body
117
+ @controller.send :render, r_opts
114
118
  nil # causes process return @response
115
119
  end
116
120
 
@@ -122,7 +126,8 @@ module Devise
122
126
  # ensure the controller response is set to our response.
123
127
  @controller.response ||= @response
124
128
  @response.status = ret.first
125
- @response.headers = ret.second
129
+ @response.headers.clear
130
+ ret.second.each { |k,v| @response[k] = v }
126
131
  @response.body = ret.third
127
132
  end
128
133
 
@@ -1,11 +1,8 @@
1
- # Deprecate: Copied verbatim from Rails source, remove once we move to Rails 4 only.
2
- require 'thread_safe'
3
1
  require 'openssl'
4
- require 'securerandom'
5
2
 
6
3
  module Devise
7
4
  class TokenGenerator
8
- def initialize(key_generator, digest="SHA256")
5
+ def initialize(key_generator, digest = "SHA256")
9
6
  @key_generator = key_generator
10
7
  @digest = digest
11
8
  end
@@ -30,41 +27,4 @@ module Devise
30
27
  @key_generator.generate_key("Devise #{column}")
31
28
  end
32
29
  end
33
-
34
- # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
35
- # It can be used to derive a number of keys for various purposes from a given secret.
36
- # This lets Rails applications have a single secure secret, but avoid reusing that
37
- # key in multiple incompatible contexts.
38
- class KeyGenerator
39
- def initialize(secret, options = {})
40
- @secret = secret
41
- # The default iterations are higher than required for our key derivation uses
42
- # on the off chance someone uses this for password storage
43
- @iterations = options[:iterations] || 2**16
44
- end
45
-
46
- # Returns a derived key suitable for use. The default key_size is chosen
47
- # to be compatible with the default settings of ActiveSupport::MessageVerifier.
48
- # i.e. OpenSSL::Digest::SHA1#block_length
49
- def generate_key(salt, key_size=64)
50
- OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
51
- end
52
- end
53
-
54
- # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
55
- # re-executing the key generation process when it's called using the same salt and
56
- # key_size
57
- class CachingKeyGenerator
58
- def initialize(key_generator)
59
- @key_generator = key_generator
60
- @cache_keys = ThreadSafe::Cache.new
61
- end
62
-
63
- # Returns a derived key suitable for use. The default key_size is chosen
64
- # to be compatible with the default settings of ActiveSupport::MessageVerifier.
65
- # i.e. OpenSSL::Digest::SHA1#block_length
66
- def generate_key(salt, key_size=64)
67
- @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
68
- end
69
- end
70
30
  end
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "3.2.4".freeze
2
+ VERSION = "4.0.0".freeze
3
3
  end
data/lib/devise.rb CHANGED
@@ -4,25 +4,26 @@ require 'active_support/dependencies'
4
4
  require 'orm_adapter'
5
5
  require 'set'
6
6
  require 'securerandom'
7
+ require 'responders'
7
8
 
8
9
  module Devise
9
10
  autoload :Delegator, 'devise/delegator'
11
+ autoload :Encryptor, 'devise/encryptor'
10
12
  autoload :FailureApp, 'devise/failure_app'
11
13
  autoload :OmniAuth, 'devise/omniauth'
12
14
  autoload :ParameterFilter, 'devise/parameter_filter'
13
- autoload :BaseSanitizer, 'devise/parameter_sanitizer'
14
15
  autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
15
16
  autoload :TestHelpers, 'devise/test_helpers'
16
17
  autoload :TimeInflector, 'devise/time_inflector'
17
18
  autoload :TokenGenerator, 'devise/token_generator'
18
19
 
19
20
  module Controllers
20
- autoload :Helpers, 'devise/controllers/helpers'
21
- autoload :Rememberable, 'devise/controllers/rememberable'
22
- autoload :ScopedViews, 'devise/controllers/scoped_views'
23
- autoload :SignInOut, 'devise/controllers/sign_in_out'
24
- autoload :StoreLocation, 'devise/controllers/store_location'
25
- autoload :UrlHelpers, 'devise/controllers/url_helpers'
21
+ autoload :Helpers, 'devise/controllers/helpers'
22
+ autoload :Rememberable, 'devise/controllers/rememberable'
23
+ autoload :ScopedViews, 'devise/controllers/scoped_views'
24
+ autoload :SignInOut, 'devise/controllers/sign_in_out'
25
+ autoload :StoreLocation, 'devise/controllers/store_location'
26
+ autoload :UrlHelpers, 'devise/controllers/url_helpers'
26
27
  end
27
28
 
28
29
  module Hooks
@@ -34,7 +35,7 @@ module Devise
34
35
  end
35
36
 
36
37
  module Strategies
37
- autoload :Base, 'devise/strategies/base'
38
+ autoload :Base, 'devise/strategies/base'
38
39
  autoload :Authenticatable, 'devise/strategies/authenticatable'
39
40
  end
40
41
 
@@ -52,33 +53,23 @@ module Devise
52
53
  # True values used to check params
53
54
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
54
55
 
56
+ # Track the configs that user explicit changed the default value. It is
57
+ # helpfull to not warn users about default values changing when they willing
58
+ # changed.
59
+ mattr_accessor :app_set_configs
60
+ @@app_set_configs = Set.new
61
+
55
62
  # Secret key used by the key generator
56
63
  mattr_accessor :secret_key
57
64
  @@secret_key = nil
58
65
 
59
- [ :allow_insecure_token_lookup,
60
- :allow_insecure_sign_in_after_confirmation,
61
- :token_authentication_key ].each do |method|
62
- class_eval <<-RUBY
63
- def self.#{method}
64
- ActiveSupport::Deprecation.warn "Devise.#{method} is deprecated " \
65
- "and has no effect"
66
- end
67
-
68
- def self.#{method}=(val)
69
- ActiveSupport::Deprecation.warn "Devise.#{method}= is deprecated " \
70
- "and has no effect"
71
- end
72
- RUBY
73
- end
74
-
75
66
  # Custom domain or key for cookies. Not set by default
76
67
  mattr_accessor :rememberable_options
77
68
  @@rememberable_options = {}
78
69
 
79
- # The number of times to encrypt password.
70
+ # The number of times to hash the password.
80
71
  mattr_accessor :stretches
81
- @@stretches = 10
72
+ @@stretches = 11
82
73
 
83
74
  # The default key used when authenticating over http auth.
84
75
  mattr_accessor :http_authentication_key
@@ -86,7 +77,7 @@ module Devise
86
77
 
87
78
  # Keys used when authenticating a user.
88
79
  mattr_accessor :authentication_keys
89
- @@authentication_keys = [ :email ]
80
+ @@authentication_keys = [:email]
90
81
 
91
82
  # Request keys used when authenticating a user.
92
83
  mattr_accessor :request_keys
@@ -94,12 +85,23 @@ module Devise
94
85
 
95
86
  # Keys that should be case-insensitive.
96
87
  mattr_accessor :case_insensitive_keys
97
- @@case_insensitive_keys = [ :email ]
88
+ @@case_insensitive_keys = [:email]
98
89
 
99
90
  # Keys that should have whitespace stripped.
100
- mattr_accessor :strip_whitespace_keys
91
+ # TODO: 4.1 Do: @@strip_whitespace_keys = [:email]
92
+ mattr_reader :strip_whitespace_keys
101
93
  @@strip_whitespace_keys = []
102
94
 
95
+ def self.strip_whitespace_keys=(strip_whitespace_keys)
96
+ app_set_configs << :strip_whitespace_keys
97
+ @@strip_whitespace_keys = strip_whitespace_keys
98
+ end
99
+
100
+ def strip_whitespace_keys=(strip_whitespace_keys)
101
+ app_set_configs << :strip_whitespace_keys
102
+ @@strip_whitespace_keys = strip_whitespace_keys
103
+ end
104
+
103
105
  # If http authentication is enabled by default.
104
106
  mattr_accessor :http_authenticatable
105
107
  @@http_authenticatable = false
@@ -119,8 +121,19 @@ module Devise
119
121
  # Email regex used to validate email formats. It simply asserts that
120
122
  # an one (and only one) @ exists in the given string. This is mainly
121
123
  # to give user feedback and not to assert the e-mail validity.
122
- mattr_accessor :email_regexp
123
- @@email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
124
+ # TODO: 4.1 Do: @@email_regexp = [/\A[^@\s]+@[^@\s]+\z/]
125
+ mattr_reader :email_regexp
126
+ @@email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\W]+\z/
127
+
128
+ def self.email_regexp=(email_regexp)
129
+ app_set_configs << :email_regexp
130
+ @@email_regexp = email_regexp
131
+ end
132
+
133
+ def email_regexp=(email_regexp)
134
+ app_set_configs << :email_regexp
135
+ @@email_regexp = email_regexp
136
+ end
124
137
 
125
138
  # Range validation for password length
126
139
  mattr_accessor :password_length
@@ -134,6 +147,10 @@ module Devise
134
147
  mattr_accessor :extend_remember_period
135
148
  @@extend_remember_period = false
136
149
 
150
+ # If true, all the remember me tokens are going to be invalidated when the user signs out.
151
+ mattr_accessor :expire_all_remember_me_on_sign_out
152
+ @@expire_all_remember_me_on_sign_out = true
153
+
137
154
  # Time interval you can access your account before confirming your account.
138
155
  # nil - allows unconfirmed access for unlimited time
139
156
  mattr_accessor :allow_unconfirmed_access_for
@@ -145,25 +162,36 @@ module Devise
145
162
 
146
163
  # Defines which key will be used when confirming an account.
147
164
  mattr_accessor :confirmation_keys
148
- @@confirmation_keys = [ :email ]
165
+ @@confirmation_keys = [:email]
149
166
 
150
167
  # Defines if email should be reconfirmable.
151
168
  # False by default for backwards compatibility.
152
- mattr_accessor :reconfirmable
169
+ # TODO: 4.1 Do: @@reconfirmable = true
170
+ mattr_reader :reconfirmable
153
171
  @@reconfirmable = false
154
172
 
173
+ def self.reconfirmable=(reconfirmable)
174
+ app_set_configs << :reconfirmable
175
+ @@reconfirmable = reconfirmable
176
+ end
177
+
178
+ def reconfirmable=(reconfirmable)
179
+ app_set_configs << :reconfirmable
180
+ @@reconfirmable = reconfirmable
181
+ end
182
+
155
183
  # Time interval to timeout the user session without activity.
156
184
  mattr_accessor :timeout_in
157
185
  @@timeout_in = 30.minutes
158
186
 
159
- # Authentication token expiration on timeout
160
- mattr_accessor :expire_auth_token_on_timeout
161
- @@expire_auth_token_on_timeout = false
162
-
163
- # Used to encrypt password. Please generate one with rake secret.
187
+ # Used to hash the password. Please generate one with rake secret.
164
188
  mattr_accessor :pepper
165
189
  @@pepper = nil
166
190
 
191
+ # Used to enable sending notification to user when their password is changed
192
+ mattr_accessor :send_password_change_notification
193
+ @@send_password_change_notification = false
194
+
167
195
  # Scoped views. Since it relies on fallbacks to render default views, it's
168
196
  # turned off by default.
169
197
  mattr_accessor :scoped_views
@@ -176,7 +204,7 @@ module Devise
176
204
 
177
205
  # Defines which key will be used when locking and unlocking an account
178
206
  mattr_accessor :unlock_keys
179
- @@unlock_keys = [ :email ]
207
+ @@unlock_keys = [:email]
180
208
 
181
209
  # Defines which strategy can be used to unlock an account.
182
210
  # Values: :email, :time, :both
@@ -193,12 +221,16 @@ module Devise
193
221
 
194
222
  # Defines which key will be used when recovering the password for an account
195
223
  mattr_accessor :reset_password_keys
196
- @@reset_password_keys = [ :email ]
224
+ @@reset_password_keys = [:email]
197
225
 
198
226
  # Time interval you can reset your password with a reset password key
199
227
  mattr_accessor :reset_password_within
200
228
  @@reset_password_within = 6.hours
201
229
 
230
+ # When set to false, resetting a password does not automatically sign in a user
231
+ mattr_accessor :sign_in_after_reset_password
232
+ @@sign_in_after_reset_password = true
233
+
202
234
  # The default scope which is used by warden.
203
235
  mattr_accessor :default_scope
204
236
  @@default_scope = nil
@@ -208,9 +240,20 @@ module Devise
208
240
  @@mailer_sender = nil
209
241
 
210
242
  # Skip session storage for the following strategies
211
- mattr_accessor :skip_session_storage
243
+ # TODO: 4.1 Do: @@skip_session_storage = [:http_auth]
244
+ mattr_reader :skip_session_storage
212
245
  @@skip_session_storage = []
213
246
 
247
+ def self.skip_session_storage=(skip_session_storage)
248
+ app_set_configs << :skip_session_storage
249
+ @@skip_session_storage = skip_session_storage
250
+ end
251
+
252
+ def skip_session_storage=(skip_session_storage)
253
+ app_set_configs << :skip_session_storage
254
+ @@skip_session_storage = skip_session_storage
255
+ end
256
+
214
257
  # Which formats should be treated as navigational.
215
258
  mattr_accessor :navigational_formats
216
259
  @@navigational_formats = ["*/*", :html]
@@ -220,9 +263,20 @@ module Devise
220
263
  @@sign_out_all_scopes = true
221
264
 
222
265
  # The default method used while signing out
223
- mattr_accessor :sign_out_via
266
+ # TODO: 4.1 Do: @@sign_out_via = :delete
267
+ mattr_reader :sign_out_via
224
268
  @@sign_out_via = :get
225
269
 
270
+ def self.sign_out_via=(sign_out_via)
271
+ app_set_configs << :sign_out_via
272
+ @@sign_out_via = sign_out_via
273
+ end
274
+
275
+ def sign_out_via=(sign_out_via)
276
+ app_set_configs << :sign_out_via
277
+ @@sign_out_via = sign_out_via
278
+ end
279
+
226
280
  # The parent controller all Devise controllers inherits from.
227
281
  # Defaults to ApplicationController. This should be set early
228
282
  # in the initialization process and should be set to a string.
@@ -241,7 +295,7 @@ module Devise
241
295
  mattr_accessor :router_name
242
296
  @@router_name = nil
243
297
 
244
- # Set the omniauth path prefix so it can be overridden when
298
+ # Set the OmniAuth path prefix so it can be overridden when
245
299
  # Devise is used in a mountable engine
246
300
  mattr_accessor :omniauth_path_prefix
247
301
  @@omniauth_path_prefix = nil
@@ -256,7 +310,7 @@ module Devise
256
310
  mattr_reader :mappings
257
311
  @@mappings = ActiveSupport::OrderedHash.new
258
312
 
259
- # Omniauth configurations.
313
+ # OmniAuth configurations.
260
314
  mattr_reader :omniauth_configs
261
315
  @@omniauth_configs = ActiveSupport::OrderedHash.new
262
316
 
@@ -268,7 +322,7 @@ module Devise
268
322
  # Private methods to interface with Warden.
269
323
  mattr_accessor :warden_config
270
324
  @@warden_config = nil
271
- @@warden_config_block = nil
325
+ @@warden_config_blocks = []
272
326
 
273
327
  # When true, enter in paranoid mode to avoid user enumeration.
274
328
  mattr_accessor :paranoid
@@ -276,16 +330,42 @@ module Devise
276
330
 
277
331
  # When true, warn user if they just used next-to-last attempt of authentication
278
332
  mattr_accessor :last_attempt_warning
279
- @@last_attempt_warning = false
333
+ @@last_attempt_warning = true
280
334
 
281
335
  # Stores the token generator
282
336
  mattr_accessor :token_generator
283
337
  @@token_generator = nil
284
338
 
285
- # Default way to setup Devise. Run rails generate devise_install to create
339
+ # Default way to set up Devise. Run rails generate devise_install to create
286
340
  # a fresh initializer with all configuration values.
287
341
  def self.setup
288
342
  yield self
343
+
344
+ warn_default_config_changed(:email_regexp, '/\A[^@\s]+@([^@\s]+\.)+[^@\W]+\z/', '/\A[^@\s]+@[^@\s]+\z/')
345
+ warn_default_config_changed(:reconfirmable, 'false', 'true')
346
+ warn_default_config_changed(:sign_out_via, ':get', ':delete')
347
+ warn_default_config_changed(:skip_session_storage, '[]', '[:http_auth]')
348
+ warn_default_config_changed(:strip_whitespace_keys, '[]', '[:email]')
349
+ end
350
+
351
+ def self.warn_default_config_changed(config, current_default, new_default)
352
+ unless app_set_configs.include?(config)
353
+ warn = <<-MESSAGE.strip_heredoc
354
+ [Devise] config.#{config} will have a new default on Devise 4.1
355
+ To keep the current behavior please set in your config/initializers/devise.rb the following:
356
+
357
+ Devise.setup do |config|
358
+ config.#{config} = #{current_default}
359
+ end
360
+
361
+ If you want to use the new default:
362
+
363
+ Devise.setup do |config|
364
+ config.#{config} = #{new_default}
365
+ end
366
+ MESSAGE
367
+ ActiveSupport::Deprecation.warn(warn)
368
+ end
289
369
  end
290
370
 
291
371
  class Getter
@@ -335,7 +415,12 @@ module Devise
335
415
  mapping
336
416
  end
337
417
 
338
- # Make Devise aware of an 3rd party Devise-module (like invitable). For convenience.
418
+ # Register available devise modules. For the standard modules that Devise provides, this method is
419
+ # called from lib/devise/modules.rb. Third-party modules need to be added explicitly using this method.
420
+ #
421
+ # Note that adding a module using this method does not cause it to be used in the authentication
422
+ # process. That requires that the module be listed in the arguments passed to the 'devise' method
423
+ # in the model class definition.
339
424
  #
340
425
  # == Options:
341
426
  #
@@ -343,6 +428,7 @@ module Devise
343
428
  # +controller+ - Symbol representing the name of an existing or custom *controller* for this module.
344
429
  # +route+ - Symbol representing the named *route* helper for this module.
345
430
  # +strategy+ - Symbol representing if this module got a custom *strategy*.
431
+ # +insert_at+ - Integer representing the order in which this module's model will be included
346
432
  #
347
433
  # All values, except :model, accept also a boolean and will have the same name as the given module
348
434
  # name.
@@ -352,10 +438,12 @@ module Devise
352
438
  # Devise.add_module(:party_module)
353
439
  # Devise.add_module(:party_module, strategy: true, controller: :sessions)
354
440
  # Devise.add_module(:party_module, model: 'party_module/model')
441
+ # Devise.add_module(:party_module, insert_at: 0)
355
442
  #
356
443
  def self.add_module(module_name, options = {})
357
- ALL << module_name
358
- options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input)
444
+ options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input, :insert_at)
445
+
446
+ ALL.insert (options[:insert_at] || -1), module_name
359
447
 
360
448
  if strategy = options[:strategy]
361
449
  strategy = (strategy == true ? module_name : strategy)
@@ -400,7 +488,7 @@ module Devise
400
488
  # Sets warden configuration using a block that will be invoked on warden
401
489
  # initialization.
402
490
  #
403
- # Devise.initialize do |config|
491
+ # Devise.setup do |config|
404
492
  # config.allow_unconfirmed_access_for = 2.days
405
493
  #
406
494
  # config.warden do |manager|
@@ -409,10 +497,10 @@ module Devise
409
497
  # end
410
498
  # end
411
499
  def self.warden(&block)
412
- @@warden_config_block = block
500
+ @@warden_config_blocks << block
413
501
  end
414
502
 
415
- # Specify an omniauth provider.
503
+ # Specify an OmniAuth provider.
416
504
  #
417
505
  # config.omniauth :github, APP_ID, APP_SECRET
418
506
  #
@@ -440,8 +528,8 @@ module Devise
440
528
  Devise::Controllers::UrlHelpers.generate_helpers!
441
529
  end
442
530
 
443
- # A method used internally to setup warden manager from the Rails initialize
444
- # block.
531
+ # A method used internally to complete the setup of warden manager after routes are loaded.
532
+ # See lib/devise/rails/routes.rb - ActionDispatch::Routing::RouteSet#finalize_with_devise!
445
533
  def self.configure_warden! #:nodoc:
446
534
  @@warden_configured ||= begin
447
535
  warden_config.failure_app = Devise::Delegator.new
@@ -463,14 +551,18 @@ module Devise
463
551
  end
464
552
  end
465
553
 
466
- @@warden_config_block.try :call, Devise.warden_config
554
+ @@warden_config_blocks.map { |block| block.call Devise.warden_config }
467
555
  true
468
556
  end
469
557
  end
470
558
 
471
559
  # Generate a friendly string randomly to be used as token.
472
- def self.friendly_token
473
- SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
560
+ # By default, length is 20 characters.
561
+ def self.friendly_token(length = 20)
562
+ # To calculate real characters, we must perform this operation.
563
+ # See SecureRandom.urlsafe_base64
564
+ rlength = (length * 3) / 4
565
+ SecureRandom.urlsafe_base64(rlength).tr('lIO0', 'sxyz')
474
566
  end
475
567
 
476
568
  # constant-time comparison algorithm to prevent timing attacks
@@ -11,9 +11,9 @@ module ActiveRecord
11
11
 
12
12
  def copy_devise_migration
13
13
  if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
14
- migration_template "migration_existing.rb", "db/migrate/add_devise_to_#{table_name}.rb"
14
+ migration_template "migration_existing.rb", "db/migrate/add_devise_to_#{table_name}.rb", migration_version: migration_version
15
15
  else
16
- migration_template "migration.rb", "db/migrate/devise_create_#{table_name}.rb"
16
+ migration_template "migration.rb", "db/migrate/devise_create_#{table_name}.rb", migration_version: migration_version
17
17
  end
18
18
  end
19
19
 
@@ -53,8 +53,8 @@ module ActiveRecord
53
53
  t.integer :sign_in_count, default: 0, null: false
54
54
  t.datetime :current_sign_in_at
55
55
  t.datetime :last_sign_in_at
56
- t.string :current_sign_in_ip
57
- t.string :last_sign_in_ip
56
+ t.#{ip_column} :current_sign_in_ip
57
+ t.#{ip_column} :last_sign_in_ip
58
58
 
59
59
  ## Confirmable
60
60
  # t.string :confirmation_token
@@ -68,6 +68,30 @@ module ActiveRecord
68
68
  # t.datetime :locked_at
69
69
  RUBY
70
70
  end
71
+
72
+ def ip_column
73
+ # Padded with spaces so it aligns nicely with the rest of the columns.
74
+ "%-8s" % (inet? ? "inet" : "string")
75
+ end
76
+
77
+ def inet?
78
+ postgresql?
79
+ end
80
+
81
+ def rails5?
82
+ Rails.version.start_with? '5'
83
+ end
84
+
85
+ def postgresql?
86
+ config = ActiveRecord::Base.configurations[Rails.env]
87
+ config && config['adapter'] == 'postgresql'
88
+ end
89
+
90
+ def migration_version
91
+ if rails5?
92
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
93
+ end
94
+ end
71
95
  end
72
96
  end
73
97
  end
@@ -1,13 +1,13 @@
1
- class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
1
+ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
- create_table(:<%= table_name %>) do |t|
3
+ create_table :<%= table_name %> do |t|
4
4
  <%= migration_data -%>
5
5
 
6
6
  <% attributes.each do |attribute| -%>
7
7
  t.<%= attribute.type %> :<%= attribute.name %>
8
8
  <% end -%>
9
9
 
10
- t.timestamps
10
+ t.timestamps null: false
11
11
  end
12
12
 
13
13
  add_index :<%= table_name %>, :email, unique: true
@@ -1,6 +1,6 @@
1
- class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
1
+ class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
- change_table(:<%= table_name %>) do |t|
3
+ change_table :<%= table_name %> do |t|
4
4
  <%= migration_data -%>
5
5
 
6
6
  <% attributes.each do |attribute| -%>
@@ -8,7 +8,7 @@ class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
8
8
  <% end -%>
9
9
 
10
10
  # Uncomment below if timestamps were not included in your original model.
11
- # t.timestamps
11
+ # t.timestamps null: false
12
12
  end
13
13
 
14
14
  add_index :<%= table_name %>, :email, unique: true
@@ -0,0 +1,44 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Devise
4
+ module Generators
5
+ class ControllersGenerator < Rails::Generators::Base
6
+ CONTROLLERS = %w(confirmations passwords registrations sessions unlocks omniauth_callbacks).freeze
7
+
8
+ desc <<-DESC.strip_heredoc
9
+ Create inherited Devise controllers in your app/controllers folder.
10
+
11
+ Use -c to specify which controller you want to overwrite.
12
+ If you do no specify a controller, all controllers will be created.
13
+ For example:
14
+
15
+ rails generate devise:controllers users -c=sessions
16
+
17
+ This will create a controller class at app/controllers/users/sessions_controller.rb like this:
18
+
19
+ class Users::ConfirmationsController < Devise::ConfirmationsController
20
+ content...
21
+ end
22
+ DESC
23
+
24
+ source_root File.expand_path("../../templates/controllers", __FILE__)
25
+ argument :scope, required: true,
26
+ desc: "The scope to create controllers in, e.g. users, admins"
27
+ class_option :controllers, aliases: "-c", type: :array,
28
+ desc: "Select specific controllers to generate (#{CONTROLLERS.join(', ')})"
29
+
30
+ def create_controllers
31
+ @scope_prefix = scope.blank? ? '' : (scope.camelize + '::')
32
+ controllers = options[:controllers] || CONTROLLERS
33
+ controllers.each do |name|
34
+ template "#{name}_controller.rb",
35
+ "app/controllers/#{scope}/#{name}_controller.rb"
36
+ end
37
+ end
38
+
39
+ def show_readme
40
+ readme "README" if behavior == :invoke
41
+ end
42
+ end
43
+ end
44
+ end