devise 3.2.0 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +260 -949
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +383 -100
  5. data/app/controllers/devise/confirmations_controller.rb +13 -5
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
  7. data/app/controllers/devise/passwords_controller.rb +23 -8
  8. data/app/controllers/devise/registrations_controller.rb +60 -24
  9. data/app/controllers/devise/sessions_controller.rb +48 -16
  10. data/app/controllers/devise/unlocks_controller.rb +11 -4
  11. data/app/controllers/devise_controller.rb +67 -31
  12. data/app/helpers/devise_helper.rb +12 -19
  13. data/app/mailers/devise/mailer.rb +10 -0
  14. data/app/views/devise/confirmations/new.html.erb +9 -5
  15. data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
  16. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  17. data/app/views/devise/mailer/password_change.html.erb +3 -0
  18. data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
  19. data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
  20. data/app/views/devise/passwords/edit.html.erb +16 -7
  21. data/app/views/devise/passwords/new.html.erb +9 -5
  22. data/app/views/devise/registrations/edit.html.erb +29 -15
  23. data/app/views/devise/registrations/new.html.erb +20 -9
  24. data/app/views/devise/sessions/new.html.erb +19 -10
  25. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  26. data/app/views/devise/shared/{_links.erb → _links.html.erb} +9 -9
  27. data/app/views/devise/unlocks/new.html.erb +9 -5
  28. data/config/locales/en.yml +23 -17
  29. data/lib/devise/controllers/helpers.rb +113 -49
  30. data/lib/devise/controllers/rememberable.rb +15 -6
  31. data/lib/devise/controllers/scoped_views.rb +3 -1
  32. data/lib/devise/controllers/sign_in_out.rb +42 -26
  33. data/lib/devise/controllers/store_location.rb +76 -0
  34. data/lib/devise/controllers/url_helpers.rb +9 -7
  35. data/lib/devise/delegator.rb +2 -0
  36. data/lib/devise/encryptor.rb +24 -0
  37. data/lib/devise/failure_app.rb +122 -40
  38. data/lib/devise/hooks/activatable.rb +7 -6
  39. data/lib/devise/hooks/csrf_cleaner.rb +5 -1
  40. data/lib/devise/hooks/forgetable.rb +2 -0
  41. data/lib/devise/hooks/lockable.rb +7 -2
  42. data/lib/devise/hooks/proxy.rb +4 -2
  43. data/lib/devise/hooks/rememberable.rb +4 -2
  44. data/lib/devise/hooks/timeoutable.rb +16 -9
  45. data/lib/devise/hooks/trackable.rb +3 -1
  46. data/lib/devise/mailers/helpers.rb +15 -12
  47. data/lib/devise/mapping.rb +8 -2
  48. data/lib/devise/models/authenticatable.rb +81 -56
  49. data/lib/devise/models/confirmable.rb +137 -42
  50. data/lib/devise/models/database_authenticatable.rb +114 -28
  51. data/lib/devise/models/lockable.rb +30 -17
  52. data/lib/devise/models/omniauthable.rb +3 -1
  53. data/lib/devise/models/recoverable.rb +62 -26
  54. data/lib/devise/models/registerable.rb +4 -0
  55. data/lib/devise/models/rememberable.rb +62 -33
  56. data/lib/devise/models/timeoutable.rb +4 -8
  57. data/lib/devise/models/trackable.rb +20 -4
  58. data/lib/devise/models/validatable.rb +16 -9
  59. data/lib/devise/models.rb +3 -1
  60. data/lib/devise/modules.rb +12 -10
  61. data/lib/devise/omniauth/config.rb +2 -0
  62. data/lib/devise/omniauth/url_helpers.rb +14 -5
  63. data/lib/devise/omniauth.rb +2 -0
  64. data/lib/devise/orm/active_record.rb +5 -1
  65. data/lib/devise/orm/mongoid.rb +6 -2
  66. data/lib/devise/parameter_filter.rb +4 -0
  67. data/lib/devise/parameter_sanitizer.rb +139 -65
  68. data/lib/devise/rails/routes.rb +150 -104
  69. data/lib/devise/rails/warden_compat.rb +3 -10
  70. data/lib/devise/rails.rb +10 -13
  71. data/lib/devise/secret_key_finder.rb +27 -0
  72. data/lib/devise/strategies/authenticatable.rb +21 -10
  73. data/lib/devise/strategies/base.rb +3 -1
  74. data/lib/devise/strategies/database_authenticatable.rb +15 -4
  75. data/lib/devise/strategies/rememberable.rb +15 -3
  76. data/lib/devise/test/controller_helpers.rb +165 -0
  77. data/lib/devise/test/integration_helpers.rb +63 -0
  78. data/lib/devise/test_helpers.rb +7 -124
  79. data/lib/devise/time_inflector.rb +4 -2
  80. data/lib/devise/token_generator.rb +3 -41
  81. data/lib/devise/version.rb +3 -1
  82. data/lib/devise.rb +111 -83
  83. data/lib/generators/active_record/devise_generator.rb +49 -12
  84. data/lib/generators/active_record/templates/migration.rb +9 -7
  85. data/lib/generators/active_record/templates/migration_existing.rb +9 -7
  86. data/lib/generators/devise/controllers_generator.rb +46 -0
  87. data/lib/generators/devise/devise_generator.rb +9 -5
  88. data/lib/generators/devise/install_generator.rb +22 -0
  89. data/lib/generators/devise/orm_helpers.rb +10 -21
  90. data/lib/generators/devise/views_generator.rb +51 -28
  91. data/lib/generators/mongoid/devise_generator.rb +22 -19
  92. data/lib/generators/templates/README +5 -12
  93. data/lib/generators/templates/controllers/README +14 -0
  94. data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
  95. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
  96. data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
  97. data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
  98. data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
  99. data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
  100. data/lib/generators/templates/devise.rb +81 -36
  101. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  102. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  103. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  104. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  105. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  106. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +6 -2
  107. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +12 -4
  108. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +5 -2
  109. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +14 -6
  110. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +12 -4
  111. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +11 -6
  112. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +5 -2
  113. metadata +46 -280
  114. data/.gitignore +0 -10
  115. data/.travis.yml +0 -20
  116. data/.yardopts +0 -9
  117. data/CONTRIBUTING.md +0 -14
  118. data/Gemfile +0 -31
  119. data/Gemfile.lock +0 -160
  120. data/Rakefile +0 -35
  121. data/devise.gemspec +0 -27
  122. data/devise.png +0 -0
  123. data/gemfiles/Gemfile.rails-3.2.x +0 -31
  124. data/gemfiles/Gemfile.rails-3.2.x.lock +0 -159
  125. data/test/controllers/custom_strategy_test.rb +0 -62
  126. data/test/controllers/helpers_test.rb +0 -253
  127. data/test/controllers/internal_helpers_test.rb +0 -120
  128. data/test/controllers/passwords_controller_test.rb +0 -31
  129. data/test/controllers/sessions_controller_test.rb +0 -99
  130. data/test/controllers/url_helpers_test.rb +0 -59
  131. data/test/delegator_test.rb +0 -19
  132. data/test/devise_test.rb +0 -94
  133. data/test/failure_app_test.rb +0 -232
  134. data/test/generators/active_record_generator_test.rb +0 -103
  135. data/test/generators/devise_generator_test.rb +0 -39
  136. data/test/generators/install_generator_test.rb +0 -13
  137. data/test/generators/mongoid_generator_test.rb +0 -23
  138. data/test/generators/views_generator_test.rb +0 -67
  139. data/test/helpers/devise_helper_test.rb +0 -51
  140. data/test/integration/authenticatable_test.rb +0 -713
  141. data/test/integration/confirmable_test.rb +0 -284
  142. data/test/integration/database_authenticatable_test.rb +0 -84
  143. data/test/integration/http_authenticatable_test.rb +0 -105
  144. data/test/integration/lockable_test.rb +0 -239
  145. data/test/integration/omniauthable_test.rb +0 -133
  146. data/test/integration/recoverable_test.rb +0 -334
  147. data/test/integration/registerable_test.rb +0 -349
  148. data/test/integration/rememberable_test.rb +0 -167
  149. data/test/integration/timeoutable_test.rb +0 -178
  150. data/test/integration/trackable_test.rb +0 -92
  151. data/test/mailers/confirmation_instructions_test.rb +0 -115
  152. data/test/mailers/reset_password_instructions_test.rb +0 -96
  153. data/test/mailers/unlock_instructions_test.rb +0 -91
  154. data/test/mapping_test.rb +0 -127
  155. data/test/models/authenticatable_test.rb +0 -13
  156. data/test/models/confirmable_test.rb +0 -454
  157. data/test/models/database_authenticatable_test.rb +0 -244
  158. data/test/models/lockable_test.rb +0 -298
  159. data/test/models/omniauthable_test.rb +0 -7
  160. data/test/models/recoverable_test.rb +0 -184
  161. data/test/models/registerable_test.rb +0 -7
  162. data/test/models/rememberable_test.rb +0 -183
  163. data/test/models/serializable_test.rb +0 -49
  164. data/test/models/timeoutable_test.rb +0 -51
  165. data/test/models/trackable_test.rb +0 -13
  166. data/test/models/validatable_test.rb +0 -127
  167. data/test/models_test.rb +0 -144
  168. data/test/omniauth/config_test.rb +0 -57
  169. data/test/omniauth/url_helpers_test.rb +0 -54
  170. data/test/orm/active_record.rb +0 -10
  171. data/test/orm/mongoid.rb +0 -13
  172. data/test/parameter_sanitizer_test.rb +0 -81
  173. data/test/rails_app/Rakefile +0 -6
  174. data/test/rails_app/app/active_record/admin.rb +0 -6
  175. data/test/rails_app/app/active_record/shim.rb +0 -2
  176. data/test/rails_app/app/active_record/user.rb +0 -6
  177. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  178. data/test/rails_app/app/controllers/admins_controller.rb +0 -11
  179. data/test/rails_app/app/controllers/application_controller.rb +0 -9
  180. data/test/rails_app/app/controllers/home_controller.rb +0 -25
  181. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  182. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  183. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  184. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  185. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  186. data/test/rails_app/app/mailers/users/mailer.rb +0 -12
  187. data/test/rails_app/app/mongoid/admin.rb +0 -29
  188. data/test/rails_app/app/mongoid/shim.rb +0 -23
  189. data/test/rails_app/app/mongoid/user.rb +0 -39
  190. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  191. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  192. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  193. data/test/rails_app/app/views/home/index.html.erb +0 -1
  194. data/test/rails_app/app/views/home/join.html.erb +0 -1
  195. data/test/rails_app/app/views/home/private.html.erb +0 -1
  196. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  197. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  198. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  199. data/test/rails_app/app/views/users/index.html.erb +0 -1
  200. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  201. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  202. data/test/rails_app/bin/bundle +0 -3
  203. data/test/rails_app/bin/rails +0 -4
  204. data/test/rails_app/bin/rake +0 -4
  205. data/test/rails_app/config/application.rb +0 -40
  206. data/test/rails_app/config/boot.rb +0 -8
  207. data/test/rails_app/config/database.yml +0 -18
  208. data/test/rails_app/config/environment.rb +0 -5
  209. data/test/rails_app/config/environments/development.rb +0 -34
  210. data/test/rails_app/config/environments/production.rb +0 -84
  211. data/test/rails_app/config/environments/test.rb +0 -36
  212. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  213. data/test/rails_app/config/initializers/devise.rb +0 -181
  214. data/test/rails_app/config/initializers/inflections.rb +0 -2
  215. data/test/rails_app/config/initializers/secret_token.rb +0 -8
  216. data/test/rails_app/config/initializers/session_store.rb +0 -1
  217. data/test/rails_app/config/routes.rb +0 -104
  218. data/test/rails_app/config.ru +0 -4
  219. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
  220. data/test/rails_app/db/schema.rb +0 -51
  221. data/test/rails_app/lib/shared_admin.rb +0 -17
  222. data/test/rails_app/lib/shared_user.rb +0 -29
  223. data/test/rails_app/public/404.html +0 -26
  224. data/test/rails_app/public/422.html +0 -26
  225. data/test/rails_app/public/500.html +0 -26
  226. data/test/rails_app/public/favicon.ico +0 -0
  227. data/test/routes_test.rb +0 -250
  228. data/test/support/assertions.rb +0 -40
  229. data/test/support/helpers.rb +0 -70
  230. data/test/support/integration.rb +0 -92
  231. data/test/support/locale/en.yml +0 -8
  232. data/test/support/webrat/integrations/rails.rb +0 -24
  233. data/test/test_helper.rb +0 -34
  234. data/test/test_helpers_test.rb +0 -173
  235. data/test/test_models.rb +0 -26
@@ -1,28 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_controller/metal"
2
4
 
3
5
  module Devise
4
6
  # Failure application that will be called every time :warden is thrown from
5
- # any strategy or hook. Responsible for redirect the user to the sign in
6
- # page based on current scope and mapping. If no scope is given, redirect
7
- # to the default_url.
7
+ # any strategy or hook. It is responsible for redirecting the user to the sign
8
+ # in page based on current scope and mapping. If no scope is given, it
9
+ # redirects to the default_url.
8
10
  class FailureApp < ActionController::Metal
9
- include ActionController::RackDelegation
10
11
  include ActionController::UrlFor
11
12
  include ActionController::Redirecting
12
13
 
13
14
  include Rails.application.routes.url_helpers
14
15
  include Rails.application.routes.mounted_helpers
15
16
 
16
- delegate :flash, :to => :request
17
+ include Devise::Controllers::StoreLocation
18
+
19
+ delegate :flash, to: :request
17
20
 
18
21
  def self.call(env)
19
22
  @respond ||= action(:respond)
20
23
  @respond.call(env)
21
24
  end
22
25
 
26
+ # Try retrieving the URL options from the parent controller (usually
27
+ # ApplicationController). Instance methods are not supported at the moment,
28
+ # so only the class-level attribute is used.
23
29
  def self.default_url_options(*args)
24
- if defined?(ApplicationController)
25
- ApplicationController.default_url_options(*args)
30
+ if defined?(Devise.parent_controller.constantize)
31
+ Devise.parent_controller.constantize.try(:default_url_options) || {}
26
32
  else
27
33
  {}
28
34
  end
@@ -46,18 +52,38 @@ module Devise
46
52
  end
47
53
 
48
54
  def recall
49
- env["PATH_INFO"] = attempted_path
50
- flash.now[:alert] = i18n_message(:invalid)
51
- self.response = recall_app(warden_options[:recall]).call(env)
55
+ header_info = if relative_url_root?
56
+ base_path = Pathname.new(relative_url_root)
57
+ full_path = Pathname.new(attempted_path)
58
+
59
+ { "SCRIPT_NAME" => relative_url_root,
60
+ "PATH_INFO" => '/' + full_path.relative_path_from(base_path).to_s }
61
+ else
62
+ { "PATH_INFO" => attempted_path }
63
+ end
64
+
65
+ header_info.each do | var, value|
66
+ if request.respond_to?(:set_header)
67
+ request.set_header(var, value)
68
+ else
69
+ request.env[var] = value
70
+ end
71
+ end
72
+
73
+ flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
74
+ # self.response = recall_app(warden_options[:recall]).call(env)
75
+ self.response = recall_app(warden_options[:recall]).call(request.env)
52
76
  end
53
77
 
54
78
  def redirect
55
79
  store_location!
56
- if flash[:timedout] && flash[:alert]
57
- flash.keep(:timedout)
58
- flash.keep(:alert)
59
- else
60
- flash[:alert] = i18n_message
80
+ if is_flashing_format?
81
+ if flash[:timedout] && flash[:alert]
82
+ flash.keep(:timedout)
83
+ flash.keep(:alert)
84
+ else
85
+ flash[:alert] = i18n_message
86
+ end
61
87
  end
62
88
  redirect_to redirect_url
63
89
  end
@@ -76,6 +102,9 @@ module Devise
76
102
  options[:resource_name] = scope
77
103
  options[:scope] = "devise.failure"
78
104
  options[:default] = [message]
105
+ auth_keys = scope_class.authentication_keys
106
+ keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| scope_class.human_attribute_name(key) }
107
+ options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
79
108
  options = i18n_options(options)
80
109
 
81
110
  I18n.t(:"#{scope}.#{message}", options)
@@ -86,7 +115,7 @@ module Devise
86
115
 
87
116
  def redirect_url
88
117
  if warden_message == :timeout
89
- flash[:timedout] = true
118
+ flash[:timedout] = true if is_flashing_format?
90
119
 
91
120
  path = if request.get?
92
121
  attempted_path
@@ -94,26 +123,45 @@ module Devise
94
123
  request.referrer
95
124
  end
96
125
 
97
- path || scope_path
126
+ path || scope_url
98
127
  else
99
- scope_path
128
+ scope_url
100
129
  end
101
130
  end
102
131
 
103
- def scope_path
132
+ def route(scope)
133
+ :"new_#{scope}_session_url"
134
+ end
135
+
136
+ def scope_url
104
137
  opts = {}
105
- route = :"new_#{scope}_session_path"
138
+
139
+ # Initialize script_name with nil to prevent infinite loops in
140
+ # authenticated mounted engines in rails 4.2 and 5.0
141
+ opts[:script_name] = nil
142
+
143
+ route = route(scope)
144
+
106
145
  opts[:format] = request_format unless skip_format?
107
146
 
108
- config = Rails.application.config
109
- opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
147
+ router_name = Devise.mappings[scope].router_name || Devise.available_router_name
148
+ context = send(router_name)
110
149
 
111
- context = send(Devise.available_router_name)
150
+ if relative_url_root?
151
+ opts[:script_name] = relative_url_root
152
+
153
+ # We need to add the rootpath to `script_name` manually for applications that use a Rails
154
+ # version lower than 5.1. Otherwise, it is going to generate a wrong path for Engines
155
+ # that use Devise. Remove it when the support of Rails 5.0 is droped.
156
+ elsif root_path_defined?(context) && !rails_51_and_up?
157
+ rootpath = context.routes.url_helpers.root_path
158
+ opts[:script_name] = rootpath.chomp('/') if rootpath.length > 1
159
+ end
112
160
 
113
161
  if context.respond_to?(route)
114
162
  context.send(route, opts)
115
- elsif respond_to?(:root_path)
116
- root_path(opts)
163
+ elsif respond_to?(:root_url)
164
+ root_url(opts)
117
165
  else
118
166
  "/"
119
167
  end
@@ -123,12 +171,12 @@ module Devise
123
171
  %w(html */*).include? request_format.to_s
124
172
  end
125
173
 
126
- # Choose whether we should respond in a http authentication fashion,
174
+ # Choose whether we should respond in an HTTP authentication fashion,
127
175
  # including 401 and optional headers.
128
176
  #
129
- # This method allows the user to explicitly disable http authentication
130
- # on ajax requests in case they want to redirect on failures instead of
131
- # handling the errors on their own. This is useful in case your ajax API
177
+ # This method allows the user to explicitly disable HTTP authentication
178
+ # on AJAX requests in case they want to redirect on failures instead of
179
+ # handling the errors on their own. This is useful in case your AJAX API
132
180
  # is the same as your public API and uses a format like JSON (so you
133
181
  # cannot mark JSON as a navigational format).
134
182
  def http_auth?
@@ -139,19 +187,19 @@ module Devise
139
187
  end
140
188
  end
141
189
 
142
- # It does not make sense to send authenticate headers in ajax requests
190
+ # It doesn't make sense to send authenticate headers in AJAX requests
143
191
  # or if the user disabled them.
144
192
  def http_auth_header?
145
- Devise.mappings[scope].to.http_authenticatable && !request.xhr?
193
+ scope_class.http_authenticatable && !request.xhr?
146
194
  end
147
195
 
148
196
  def http_auth_body
149
197
  return i18n_message unless request_format
150
198
  method = "to_#{request_format}"
151
199
  if method == "to_xml"
152
- { :error => i18n_message }.to_xml(:root => "errors")
200
+ { error: i18n_message }.to_xml(root: "errors")
153
201
  elsif {}.respond_to?(method)
154
- { :error => i18n_message }.send(method)
202
+ { error: i18n_message }.send(method)
155
203
  else
156
204
  i18n_message
157
205
  end
@@ -165,11 +213,11 @@ module Devise
165
213
  end
166
214
 
167
215
  def warden
168
- env['warden']
216
+ request.respond_to?(:get_header) ? request.get_header("warden") : request.env["warden"]
169
217
  end
170
218
 
171
219
  def warden_options
172
- env['warden.options']
220
+ request.respond_to?(:get_header) ? request.get_header("warden.options") : request.env["warden.options"]
173
221
  end
174
222
 
175
223
  def warden_message
@@ -180,24 +228,58 @@ module Devise
180
228
  @scope ||= warden_options[:scope] || Devise.default_scope
181
229
  end
182
230
 
231
+ def scope_class
232
+ @scope_class ||= Devise.mappings[scope].to
233
+ end
234
+
183
235
  def attempted_path
184
236
  warden_options[:attempted_path]
185
237
  end
186
238
 
187
- # Stores requested uri to redirect the user after signing in. We cannot use
188
- # scoped session provided by warden here, since the user is not authenticated
189
- # yet, but we still need to store the uri based on scope, so different scopes
190
- # would never use the same uri to redirect.
239
+ # Stores requested URI to redirect the user after signing in. We can't use
240
+ # the scoped session provided by warden here, since the user is not
241
+ # authenticated yet, but we still need to store the URI based on scope, so
242
+ # different scopes would never use the same URI to redirect.
191
243
  def store_location!
192
- session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
244
+ store_location_for(scope, attempted_path) if request.get? && !http_auth?
193
245
  end
194
246
 
195
247
  def is_navigational_format?
196
248
  Devise.navigational_formats.include?(request_format)
197
249
  end
198
250
 
251
+ # Check if flash messages should be emitted. Default is to do it on
252
+ # navigational formats
253
+ def is_flashing_format?
254
+ request.respond_to?(:flash) && is_navigational_format?
255
+ end
256
+
199
257
  def request_format
200
258
  @request_format ||= request.format.try(:ref)
201
259
  end
260
+
261
+ def relative_url_root
262
+ @relative_url_root ||= begin
263
+ config = Rails.application.config
264
+
265
+ config.try(:relative_url_root) || config.action_controller.try(:relative_url_root)
266
+ end
267
+ end
268
+
269
+ def relative_url_root?
270
+ relative_url_root.present?
271
+ end
272
+
273
+ ActiveSupport.run_load_hooks(:devise_failure_app, self)
274
+
275
+ private
276
+
277
+ def root_path_defined?(context)
278
+ defined?(context.routes) && context.routes.url_helpers.respond_to?(:root_path)
279
+ end
280
+
281
+ def rails_51_and_up?
282
+ Rails.gem_version >= Gem::Version.new("5.1")
283
+ end
202
284
  end
203
285
  end
@@ -1,11 +1,12 @@
1
- # Deny user access whenever his account is not active yet. All strategies that inherits from
2
- # Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
3
- # before actively signing him in. However, we need this as hook to validate the user activity
4
- # in each request and in case the user is using other strategies beside Devise ones.
1
+ # frozen_string_literal: true
2
+
3
+ # Deny user access whenever their account is not active yet.
4
+ # We need this as hook to validate the user activity on each request
5
+ # and in case the user is using other strategies beside Devise ones.
5
6
  Warden::Manager.after_set_user do |record, warden, options|
6
7
  if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
7
8
  scope = options[:scope]
8
9
  warden.logout(scope)
9
- throw :warden, :scope => scope, :message => record.inactive_message
10
+ throw :warden, scope: scope, message: record.inactive_message
10
11
  end
11
- end
12
+ end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Warden::Manager.after_authentication do |record, warden, options|
2
- if Devise.clean_up_csrf_token_on_authentication
4
+ clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
5
+ warden.winning_strategy.clean_up_csrf?
6
+ if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
3
7
  warden.request.session.try(:delete, :_csrf_token)
4
8
  end
5
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Before logout hook to forget the user in the given scope, if it responds
2
4
  # to forget_me! Also clear remember token to ensure the user won't be
3
5
  # remembered again. Notice that we forget the user unless the record is not persisted.
@@ -1,7 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # After each sign in, if resource responds to failed_attempts, sets it to 0
2
4
  # This is only triggered when the user is explicitly set (with set_user)
3
- Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
5
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
4
6
  if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
5
- record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
7
+ unless record.failed_attempts.to_i.zero?
8
+ record.failed_attempts = 0
9
+ record.save(validate: false)
10
+ end
6
11
  end
7
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Hooks
3
5
  # A small warden proxy so we can remember, forget and
@@ -7,7 +9,7 @@ module Devise
7
9
  include Devise::Controllers::SignInOut
8
10
 
9
11
  attr_reader :warden
10
- delegate :cookies, :env, :to => :warden
12
+ delegate :cookies, :request, to: :warden
11
13
 
12
14
  def initialize(warden)
13
15
  @warden = warden
@@ -18,4 +20,4 @@ module Devise
18
20
  end
19
21
  end
20
22
  end
21
- end
23
+ end
@@ -1,7 +1,9 @@
1
- Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
1
+ # frozen_string_literal: true
2
+
3
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
2
4
  scope = options[:scope]
3
5
  if record.respond_to?(:remember_me) && options[:store] != false &&
4
6
  record.remember_me && warden.authenticated?(scope)
5
7
  Devise::Hooks::Proxy.new(warden).remember_me(record)
6
8
  end
7
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Each time a record is set we check whether its session has already timed out
2
4
  # or not, based on last request time. If so, the record is logged out and
3
5
  # redirected to the sign in page. Also, each time the request comes and the
@@ -7,22 +9,27 @@ Warden::Manager.after_set_user do |record, warden, options|
7
9
  scope = options[:scope]
8
10
  env = warden.request.env
9
11
 
10
- if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
12
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
13
+ options[:store] != false && !env['devise.skip_timeoutable']
11
14
  last_request_at = warden.session(scope)['last_request_at']
12
- proxy = Devise::Hooks::Proxy.new(warden)
13
15
 
14
- if record.timedout?(last_request_at) && !env['devise.skip_timeout']
15
- Devise.sign_out_all_scopes ? proxy.sign_out : sign_out(scope)
16
+ if last_request_at.is_a? Integer
17
+ last_request_at = Time.at(last_request_at).utc
18
+ elsif last_request_at.is_a? String
19
+ last_request_at = Time.parse(last_request_at)
20
+ end
16
21
 
17
- if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
18
- record.reset_authentication_token!
19
- end
22
+ proxy = Devise::Hooks::Proxy.new(warden)
20
23
 
21
- throw :warden, :scope => scope, :message => :timeout
24
+ if record.timedout?(last_request_at) &&
25
+ !env['devise.skip_timeout'] &&
26
+ !proxy.remember_me_is_active?(record)
27
+ Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
28
+ throw :warden, scope: scope, message: :timeout
22
29
  end
23
30
 
24
31
  unless env['devise.skip_trackable']
25
- warden.session(scope)['last_request_at'] = Time.now.utc
32
+ warden.session(scope)['last_request_at'] = Time.now.utc.to_i
26
33
  end
27
34
  end
28
35
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # After each sign in, update sign in time, sign in count and sign in IP.
2
4
  # This is only triggered when the user is explicitly set (with set_user)
3
5
  # and on authentication. Retrieving the user from session (:fetch) does
4
6
  # not trigger it.
5
- Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
7
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
6
8
  if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
7
9
  record.update_tracked_fields!(warden.request)
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Mailers
3
5
  module Helpers
@@ -5,15 +7,16 @@ module Devise
5
7
 
6
8
  included do
7
9
  include Devise::Controllers::ScopedViews
8
- attr_reader :scope_name, :resource
9
10
  end
10
11
 
11
12
  protected
12
13
 
14
+ attr_reader :scope_name, :resource
15
+
13
16
  # Configure default email options
14
- def devise_mail(record, action, opts={})
17
+ def devise_mail(record, action, opts = {}, &block)
15
18
  initialize_from_record(record)
16
- mail headers_for(action, opts)
19
+ mail headers_for(action, opts), &block
17
20
  end
18
21
 
19
22
  def initialize_from_record(record)
@@ -27,12 +30,12 @@ module Devise
27
30
 
28
31
  def headers_for(action, opts)
29
32
  headers = {
30
- :subject => subject_for(action),
31
- :to => resource.email,
32
- :from => mailer_sender(devise_mapping),
33
- :reply_to => mailer_reply_to(devise_mapping),
34
- :template_path => template_paths,
35
- :template_name => action
33
+ subject: subject_for(action),
34
+ to: resource.email,
35
+ from: mailer_sender(devise_mapping),
36
+ reply_to: mailer_reply_to(devise_mapping),
37
+ template_path: template_paths,
38
+ template_name: action
36
39
  }.merge(opts)
37
40
 
38
41
  @email = headers[:to]
@@ -64,7 +67,7 @@ module Devise
64
67
  template_path
65
68
  end
66
69
 
67
- # Setup a subject doing an I18n lookup. At first, it attempts to set a subject
70
+ # Set up a subject doing an I18n lookup. At first, it attempts to set a subject
68
71
  # based on the current mapping:
69
72
  #
70
73
  # en:
@@ -82,8 +85,8 @@ module Devise
82
85
  # subject: '...'
83
86
  #
84
87
  def subject_for(key)
85
- I18n.t(:"#{devise_mapping.name}_subject", :scope => [:devise, :mailer, key],
86
- :default => [:subject, key.to_s.humanize])
88
+ I18n.t(:"#{devise_mapping.name}_subject", scope: [:devise, :mailer, key],
89
+ default: [:subject, key.to_s.humanize])
87
90
  end
88
91
  end
89
92
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  # Responsible for handling devise mappings and routes configuration. Each
3
5
  # resource configured by devise_for in routes is actually creating a mapping
@@ -23,16 +25,18 @@ module Devise
23
25
  #
24
26
  class Mapping #:nodoc:
25
27
  attr_reader :singular, :scoped_path, :path, :controllers, :path_names,
26
- :class_name, :sign_out_via, :format, :used_routes, :used_helpers, :failure_app
28
+ :class_name, :sign_out_via, :format, :used_routes, :used_helpers,
29
+ :failure_app, :router_name
27
30
 
28
31
  alias :name :singular
29
32
 
30
33
  # Receives an object and find a scope for it. If a scope cannot be found,
31
34
  # raises an error. If a symbol is given, it's considered to be the scope.
32
35
  def self.find_scope!(obj)
36
+ obj = obj.devise_scope if obj.respond_to?(:devise_scope)
33
37
  case obj
34
38
  when String, Symbol
35
- return obj
39
+ return obj.to_sym
36
40
  when Class
37
41
  Devise.mappings.each_value { |m| return m.name if obj <= m.to }
38
42
  else
@@ -60,6 +64,8 @@ module Devise
60
64
  @sign_out_via = options[:sign_out_via] || Devise.sign_out_via
61
65
  @format = options[:format]
62
66
 
67
+ @router_name = options[:router_name]
68
+
63
69
  default_failure_app(options)
64
70
  default_controllers(options)
65
71
  default_path_names(options)