devise 3.2.2 → 4.8.0

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 (236) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +281 -957
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +410 -120
  5. data/app/controllers/devise/confirmations_controller.rb +11 -5
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
  7. data/app/controllers/devise/passwords_controller.rb +21 -8
  8. data/app/controllers/devise/registrations_controller.rb +59 -26
  9. data/app/controllers/devise/sessions_controller.rb +47 -17
  10. data/app/controllers/devise/unlocks_controller.rb +9 -4
  11. data/app/controllers/devise_controller.rb +69 -33
  12. data/app/helpers/devise_helper.rb +23 -18
  13. data/app/mailers/devise/mailer.rb +13 -3
  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 +24 -18
  29. data/lib/devise/controllers/helpers.rb +113 -33
  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 +47 -29
  33. data/lib/devise/controllers/store_location.rb +31 -5
  34. data/lib/devise/controllers/url_helpers.rb +10 -8
  35. data/lib/devise/delegator.rb +2 -0
  36. data/lib/devise/encryptor.rb +24 -0
  37. data/lib/devise/failure_app.rb +119 -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 +5 -3
  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 +9 -3
  48. data/lib/devise/models/authenticatable.rb +91 -61
  49. data/lib/devise/models/confirmable.rb +138 -43
  50. data/lib/devise/models/database_authenticatable.rb +112 -31
  51. data/lib/devise/models/lockable.rb +39 -18
  52. data/lib/devise/models/omniauthable.rb +3 -1
  53. data/lib/devise/models/recoverable.rb +64 -28
  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 +4 -5
  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/deprecated_constant_accessor.rb +39 -0
  69. data/lib/devise/rails/routes.rb +151 -120
  70. data/lib/devise/rails/warden_compat.rb +3 -10
  71. data/lib/devise/rails.rb +10 -13
  72. data/lib/devise/secret_key_finder.rb +27 -0
  73. data/lib/devise/strategies/authenticatable.rb +21 -10
  74. data/lib/devise/strategies/base.rb +3 -1
  75. data/lib/devise/strategies/database_authenticatable.rb +14 -6
  76. data/lib/devise/strategies/rememberable.rb +15 -3
  77. data/lib/devise/test/controller_helpers.rb +167 -0
  78. data/lib/devise/test/integration_helpers.rb +63 -0
  79. data/lib/devise/test_helpers.rb +7 -124
  80. data/lib/devise/time_inflector.rb +4 -2
  81. data/lib/devise/token_generator.rb +3 -41
  82. data/lib/devise/version.rb +3 -1
  83. data/lib/devise.rb +107 -84
  84. data/lib/generators/active_record/devise_generator.rb +64 -12
  85. data/lib/generators/active_record/templates/migration.rb +9 -7
  86. data/lib/generators/active_record/templates/migration_existing.rb +9 -7
  87. data/lib/generators/devise/controllers_generator.rb +46 -0
  88. data/lib/generators/devise/devise_generator.rb +8 -6
  89. data/lib/generators/devise/install_generator.rb +18 -1
  90. data/lib/generators/devise/orm_helpers.rb +10 -21
  91. data/lib/generators/devise/views_generator.rb +49 -28
  92. data/lib/generators/mongoid/devise_generator.rb +21 -19
  93. data/lib/generators/templates/README +13 -12
  94. data/lib/generators/templates/controllers/README +14 -0
  95. data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
  96. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
  97. data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
  98. data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
  99. data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
  100. data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
  101. data/lib/generators/templates/devise.rb +94 -37
  102. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  103. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  104. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  105. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  106. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  107. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +6 -2
  108. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +12 -4
  109. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +5 -2
  110. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +14 -6
  111. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +12 -4
  112. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +11 -6
  113. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +5 -2
  114. metadata +50 -284
  115. data/.gitignore +0 -10
  116. data/.travis.yml +0 -20
  117. data/.yardopts +0 -9
  118. data/CONTRIBUTING.md +0 -14
  119. data/Gemfile +0 -31
  120. data/Gemfile.lock +0 -160
  121. data/Rakefile +0 -35
  122. data/devise.gemspec +0 -27
  123. data/devise.png +0 -0
  124. data/gemfiles/Gemfile.rails-3.2.x +0 -31
  125. data/gemfiles/Gemfile.rails-3.2.x.lock +0 -159
  126. data/test/controllers/custom_strategy_test.rb +0 -62
  127. data/test/controllers/helpers_test.rb +0 -276
  128. data/test/controllers/internal_helpers_test.rb +0 -120
  129. data/test/controllers/passwords_controller_test.rb +0 -31
  130. data/test/controllers/sessions_controller_test.rb +0 -99
  131. data/test/controllers/url_helpers_test.rb +0 -59
  132. data/test/delegator_test.rb +0 -19
  133. data/test/devise_test.rb +0 -94
  134. data/test/failure_app_test.rb +0 -232
  135. data/test/generators/active_record_generator_test.rb +0 -103
  136. data/test/generators/devise_generator_test.rb +0 -39
  137. data/test/generators/install_generator_test.rb +0 -13
  138. data/test/generators/mongoid_generator_test.rb +0 -23
  139. data/test/generators/views_generator_test.rb +0 -67
  140. data/test/helpers/devise_helper_test.rb +0 -51
  141. data/test/integration/authenticatable_test.rb +0 -713
  142. data/test/integration/confirmable_test.rb +0 -284
  143. data/test/integration/database_authenticatable_test.rb +0 -84
  144. data/test/integration/http_authenticatable_test.rb +0 -105
  145. data/test/integration/lockable_test.rb +0 -239
  146. data/test/integration/omniauthable_test.rb +0 -133
  147. data/test/integration/recoverable_test.rb +0 -334
  148. data/test/integration/registerable_test.rb +0 -349
  149. data/test/integration/rememberable_test.rb +0 -167
  150. data/test/integration/timeoutable_test.rb +0 -183
  151. data/test/integration/trackable_test.rb +0 -92
  152. data/test/mailers/confirmation_instructions_test.rb +0 -115
  153. data/test/mailers/reset_password_instructions_test.rb +0 -96
  154. data/test/mailers/unlock_instructions_test.rb +0 -91
  155. data/test/mapping_test.rb +0 -127
  156. data/test/models/authenticatable_test.rb +0 -13
  157. data/test/models/confirmable_test.rb +0 -454
  158. data/test/models/database_authenticatable_test.rb +0 -249
  159. data/test/models/lockable_test.rb +0 -298
  160. data/test/models/omniauthable_test.rb +0 -7
  161. data/test/models/recoverable_test.rb +0 -184
  162. data/test/models/registerable_test.rb +0 -7
  163. data/test/models/rememberable_test.rb +0 -183
  164. data/test/models/serializable_test.rb +0 -49
  165. data/test/models/timeoutable_test.rb +0 -51
  166. data/test/models/trackable_test.rb +0 -13
  167. data/test/models/validatable_test.rb +0 -127
  168. data/test/models_test.rb +0 -144
  169. data/test/omniauth/config_test.rb +0 -57
  170. data/test/omniauth/url_helpers_test.rb +0 -54
  171. data/test/orm/active_record.rb +0 -10
  172. data/test/orm/mongoid.rb +0 -13
  173. data/test/parameter_sanitizer_test.rb +0 -81
  174. data/test/rails_app/Rakefile +0 -6
  175. data/test/rails_app/app/active_record/admin.rb +0 -6
  176. data/test/rails_app/app/active_record/shim.rb +0 -2
  177. data/test/rails_app/app/active_record/user.rb +0 -6
  178. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  179. data/test/rails_app/app/controllers/admins_controller.rb +0 -11
  180. data/test/rails_app/app/controllers/application_controller.rb +0 -9
  181. data/test/rails_app/app/controllers/home_controller.rb +0 -25
  182. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  183. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  184. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  185. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  186. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  187. data/test/rails_app/app/mailers/users/mailer.rb +0 -12
  188. data/test/rails_app/app/mongoid/admin.rb +0 -29
  189. data/test/rails_app/app/mongoid/shim.rb +0 -23
  190. data/test/rails_app/app/mongoid/user.rb +0 -39
  191. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  192. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  193. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  194. data/test/rails_app/app/views/home/index.html.erb +0 -1
  195. data/test/rails_app/app/views/home/join.html.erb +0 -1
  196. data/test/rails_app/app/views/home/private.html.erb +0 -1
  197. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  198. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  199. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  200. data/test/rails_app/app/views/users/index.html.erb +0 -1
  201. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  202. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  203. data/test/rails_app/bin/bundle +0 -3
  204. data/test/rails_app/bin/rails +0 -4
  205. data/test/rails_app/bin/rake +0 -4
  206. data/test/rails_app/config/application.rb +0 -40
  207. data/test/rails_app/config/boot.rb +0 -14
  208. data/test/rails_app/config/database.yml +0 -18
  209. data/test/rails_app/config/environment.rb +0 -5
  210. data/test/rails_app/config/environments/development.rb +0 -30
  211. data/test/rails_app/config/environments/production.rb +0 -80
  212. data/test/rails_app/config/environments/test.rb +0 -36
  213. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  214. data/test/rails_app/config/initializers/devise.rb +0 -181
  215. data/test/rails_app/config/initializers/inflections.rb +0 -2
  216. data/test/rails_app/config/initializers/secret_token.rb +0 -8
  217. data/test/rails_app/config/initializers/session_store.rb +0 -1
  218. data/test/rails_app/config/routes.rb +0 -104
  219. data/test/rails_app/config.ru +0 -4
  220. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
  221. data/test/rails_app/db/schema.rb +0 -55
  222. data/test/rails_app/lib/shared_admin.rb +0 -17
  223. data/test/rails_app/lib/shared_user.rb +0 -29
  224. data/test/rails_app/public/404.html +0 -26
  225. data/test/rails_app/public/422.html +0 -26
  226. data/test/rails_app/public/500.html +0 -26
  227. data/test/rails_app/public/favicon.ico +0 -0
  228. data/test/routes_test.rb +0 -250
  229. data/test/support/assertions.rb +0 -40
  230. data/test/support/helpers.rb +0 -70
  231. data/test/support/integration.rb +0 -92
  232. data/test/support/locale/en.yml +0 -8
  233. data/test/support/webrat/integrations/rails.rb +0 -24
  234. data/test/test_helper.rb +0 -27
  235. data/test/test_helpers_test.rb +0 -173
  236. data/test/test_models.rb +0 -33
@@ -1,12 +1,13 @@
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
 
@@ -15,16 +16,19 @@ module Devise
15
16
 
16
17
  include Devise::Controllers::StoreLocation
17
18
 
18
- delegate :flash, :to => :request
19
+ delegate :flash, to: :request
19
20
 
20
21
  def self.call(env)
21
22
  @respond ||= action(:respond)
22
23
  @respond.call(env)
23
24
  end
24
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.
25
29
  def self.default_url_options(*args)
26
- if defined?(ApplicationController)
27
- ApplicationController.default_url_options(*args)
30
+ if defined?(Devise.parent_controller.constantize)
31
+ Devise.parent_controller.constantize.try(:default_url_options) || {}
28
32
  else
29
33
  {}
30
34
  end
@@ -48,18 +52,37 @@ module Devise
48
52
  end
49
53
 
50
54
  def recall
51
- env["PATH_INFO"] = attempted_path
52
- flash.now[:alert] = i18n_message(:invalid)
53
- 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(request.env)
54
75
  end
55
76
 
56
77
  def redirect
57
78
  store_location!
58
- if flash[:timedout] && flash[:alert]
59
- flash.keep(:timedout)
60
- flash.keep(:alert)
61
- else
62
- flash[:alert] = i18n_message
79
+ if is_flashing_format?
80
+ if flash[:timedout] && flash[:alert]
81
+ flash.keep(:timedout)
82
+ flash.keep(:alert)
83
+ else
84
+ flash[:alert] = i18n_message
85
+ end
63
86
  end
64
87
  redirect_to redirect_url
65
88
  end
@@ -78,9 +101,12 @@ module Devise
78
101
  options[:resource_name] = scope
79
102
  options[:scope] = "devise.failure"
80
103
  options[:default] = [message]
104
+ auth_keys = scope_class.authentication_keys
105
+ keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| scope_class.human_attribute_name(key) }
106
+ options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
81
107
  options = i18n_options(options)
82
108
 
83
- I18n.t(:"#{scope}.#{message}", options)
109
+ I18n.t(:"#{scope}.#{message}", **options)
84
110
  else
85
111
  message.to_s
86
112
  end
@@ -88,7 +114,7 @@ module Devise
88
114
 
89
115
  def redirect_url
90
116
  if warden_message == :timeout
91
- flash[:timedout] = true
117
+ flash[:timedout] = true if is_flashing_format?
92
118
 
93
119
  path = if request.get?
94
120
  attempted_path
@@ -96,26 +122,45 @@ module Devise
96
122
  request.referrer
97
123
  end
98
124
 
99
- path || scope_path
125
+ path || scope_url
100
126
  else
101
- scope_path
127
+ scope_url
102
128
  end
103
129
  end
104
130
 
105
- def scope_path
131
+ def route(scope)
132
+ :"new_#{scope}_session_url"
133
+ end
134
+
135
+ def scope_url
106
136
  opts = {}
107
- route = :"new_#{scope}_session_path"
137
+
138
+ # Initialize script_name with nil to prevent infinite loops in
139
+ # authenticated mounted engines in rails 4.2 and 5.0
140
+ opts[:script_name] = nil
141
+
142
+ route = route(scope)
143
+
108
144
  opts[:format] = request_format unless skip_format?
109
145
 
110
- config = Rails.application.config
111
- opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
146
+ router_name = Devise.mappings[scope].router_name || Devise.available_router_name
147
+ context = send(router_name)
112
148
 
113
- context = send(Devise.available_router_name)
149
+ if relative_url_root?
150
+ opts[:script_name] = relative_url_root
151
+
152
+ # We need to add the rootpath to `script_name` manually for applications that use a Rails
153
+ # version lower than 5.1. Otherwise, it is going to generate a wrong path for Engines
154
+ # that use Devise. Remove it when the support of Rails 5.0 is dropped.
155
+ elsif root_path_defined?(context) && !rails_51_and_up?
156
+ rootpath = context.routes.url_helpers.root_path
157
+ opts[:script_name] = rootpath.chomp('/') if rootpath.length > 1
158
+ end
114
159
 
115
160
  if context.respond_to?(route)
116
161
  context.send(route, opts)
117
- elsif respond_to?(:root_path)
118
- root_path(opts)
162
+ elsif respond_to?(:root_url)
163
+ root_url(opts)
119
164
  else
120
165
  "/"
121
166
  end
@@ -125,12 +170,12 @@ module Devise
125
170
  %w(html */*).include? request_format.to_s
126
171
  end
127
172
 
128
- # Choose whether we should respond in a http authentication fashion,
173
+ # Choose whether we should respond in an HTTP authentication fashion,
129
174
  # including 401 and optional headers.
130
175
  #
131
- # This method allows the user to explicitly disable http authentication
132
- # on ajax requests in case they want to redirect on failures instead of
133
- # handling the errors on their own. This is useful in case your ajax API
176
+ # This method allows the user to explicitly disable HTTP authentication
177
+ # on AJAX requests in case they want to redirect on failures instead of
178
+ # handling the errors on their own. This is useful in case your AJAX API
134
179
  # is the same as your public API and uses a format like JSON (so you
135
180
  # cannot mark JSON as a navigational format).
136
181
  def http_auth?
@@ -141,19 +186,19 @@ module Devise
141
186
  end
142
187
  end
143
188
 
144
- # It does not make sense to send authenticate headers in ajax requests
189
+ # It doesn't make sense to send authenticate headers in AJAX requests
145
190
  # or if the user disabled them.
146
191
  def http_auth_header?
147
- Devise.mappings[scope].to.http_authenticatable && !request.xhr?
192
+ scope_class.http_authenticatable && !request.xhr?
148
193
  end
149
194
 
150
195
  def http_auth_body
151
196
  return i18n_message unless request_format
152
197
  method = "to_#{request_format}"
153
198
  if method == "to_xml"
154
- { :error => i18n_message }.to_xml(:root => "errors")
199
+ { error: i18n_message }.to_xml(root: "errors")
155
200
  elsif {}.respond_to?(method)
156
- { :error => i18n_message }.send(method)
201
+ { error: i18n_message }.send(method)
157
202
  else
158
203
  i18n_message
159
204
  end
@@ -167,11 +212,11 @@ module Devise
167
212
  end
168
213
 
169
214
  def warden
170
- env['warden']
215
+ request.respond_to?(:get_header) ? request.get_header("warden") : request.env["warden"]
171
216
  end
172
217
 
173
218
  def warden_options
174
- env['warden.options']
219
+ request.respond_to?(:get_header) ? request.get_header("warden.options") : request.env["warden.options"]
175
220
  end
176
221
 
177
222
  def warden_message
@@ -182,14 +227,18 @@ module Devise
182
227
  @scope ||= warden_options[:scope] || Devise.default_scope
183
228
  end
184
229
 
230
+ def scope_class
231
+ @scope_class ||= Devise.mappings[scope].to
232
+ end
233
+
185
234
  def attempted_path
186
235
  warden_options[:attempted_path]
187
236
  end
188
237
 
189
- # Stores requested uri to redirect the user after signing in. We cannot use
190
- # scoped session provided by warden here, since the user is not authenticated
191
- # yet, but we still need to store the uri based on scope, so different scopes
192
- # would never use the same uri to redirect.
238
+ # Stores requested URI to redirect the user after signing in. We can't use
239
+ # the scoped session provided by warden here, since the user is not
240
+ # authenticated yet, but we still need to store the URI based on scope, so
241
+ # different scopes would never use the same URI to redirect.
193
242
  def store_location!
194
243
  store_location_for(scope, attempted_path) if request.get? && !http_auth?
195
244
  end
@@ -198,8 +247,38 @@ module Devise
198
247
  Devise.navigational_formats.include?(request_format)
199
248
  end
200
249
 
250
+ # Check if flash messages should be emitted. Default is to do it on
251
+ # navigational formats
252
+ def is_flashing_format?
253
+ request.respond_to?(:flash) && is_navigational_format?
254
+ end
255
+
201
256
  def request_format
202
257
  @request_format ||= request.format.try(:ref)
203
258
  end
259
+
260
+ def relative_url_root
261
+ @relative_url_root ||= begin
262
+ config = Rails.application.config
263
+
264
+ config.try(:relative_url_root) || config.action_controller.try(:relative_url_root)
265
+ end
266
+ end
267
+
268
+ def relative_url_root?
269
+ relative_url_root.present?
270
+ end
271
+
272
+ ActiveSupport.run_load_hooks(:devise_failure_app, self)
273
+
274
+ private
275
+
276
+ def root_path_defined?(context)
277
+ defined?(context.routes) && context.routes.url_helpers.respond_to?(:root_path)
278
+ end
279
+
280
+ def rails_51_and_up?
281
+ Rails.gem_version >= Gem::Version.new("5.1")
282
+ end
204
283
  end
205
284
  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,9 @@
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|
4
- if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
5
- record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
5
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
6
+ if record.respond_to?(:reset_failed_attempts!) && warden.authenticated?(options[:scope])
7
+ record.reset_failed_attempts!
6
8
  end
7
9
  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 : proxy.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 !env['devise.skip_timeout'] &&
25
+ record.timedout?(last_request_at) &&
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
@@ -42,7 +46,7 @@ module Devise
42
46
  raise "Could not find a valid mapping for #{obj.inspect}"
43
47
  end
44
48
 
45
- def self.find_by_path!(path, path_type=:fullpath)
49
+ def self.find_by_path!(path, path_type = :fullpath)
46
50
  Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
47
51
  raise "Could not find a valid mapping for path #{path.inspect}"
48
52
  end
@@ -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)