devise 3.2.1 → 4.4.3

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 (254) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +58 -10
  3. data/CHANGELOG.md +199 -979
  4. data/CODE_OF_CONDUCT.md +22 -0
  5. data/CONTRIBUTING.md +73 -8
  6. data/Gemfile +19 -11
  7. data/Gemfile.lock +152 -119
  8. data/ISSUE_TEMPLATE.md +19 -0
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +347 -93
  11. data/Rakefile +4 -2
  12. data/app/controllers/devise/confirmations_controller.rb +11 -5
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
  14. data/app/controllers/devise/passwords_controller.rb +20 -8
  15. data/app/controllers/devise/registrations_controller.rb +34 -19
  16. data/app/controllers/devise/sessions_controller.rb +47 -17
  17. data/app/controllers/devise/unlocks_controller.rb +9 -4
  18. data/app/controllers/devise_controller.rb +67 -31
  19. data/app/helpers/devise_helper.rb +4 -2
  20. data/app/mailers/devise/mailer.rb +10 -0
  21. data/app/views/devise/confirmations/new.html.erb +8 -4
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
  23. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  24. data/app/views/devise/mailer/password_change.html.erb +3 -0
  25. data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
  26. data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
  27. data/app/views/devise/passwords/edit.html.erb +15 -6
  28. data/app/views/devise/passwords/new.html.erb +8 -4
  29. data/app/views/devise/registrations/edit.html.erb +28 -14
  30. data/app/views/devise/registrations/new.html.erb +19 -8
  31. data/app/views/devise/sessions/new.html.erb +17 -8
  32. data/app/views/devise/shared/{_links.erb → _links.html.erb} +2 -2
  33. data/app/views/devise/unlocks/new.html.erb +8 -4
  34. data/bin/test +13 -0
  35. data/config/locales/en.yml +22 -17
  36. data/devise.gemspec +7 -6
  37. data/gemfiles/Gemfile.rails-4.1-stable +32 -0
  38. data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
  39. data/gemfiles/Gemfile.rails-4.2-stable +32 -0
  40. data/gemfiles/Gemfile.rails-4.2-stable.lock +192 -0
  41. data/gemfiles/Gemfile.rails-5.0-stable +33 -0
  42. data/gemfiles/Gemfile.rails-5.0-stable.lock +192 -0
  43. data/gemfiles/Gemfile.rails-5.2-rc1 +26 -0
  44. data/gemfiles/Gemfile.rails-5.2-rc1.lock +201 -0
  45. data/guides/bug_report_templates/integration_test.rb +106 -0
  46. data/lib/devise.rb +107 -84
  47. data/lib/devise/controllers/helpers.rb +111 -31
  48. data/lib/devise/controllers/rememberable.rb +15 -6
  49. data/lib/devise/controllers/scoped_views.rb +3 -1
  50. data/lib/devise/controllers/sign_in_out.rb +39 -26
  51. data/lib/devise/controllers/store_location.rb +31 -2
  52. data/lib/devise/controllers/url_helpers.rb +9 -7
  53. data/lib/devise/delegator.rb +2 -0
  54. data/lib/devise/encryptor.rb +24 -0
  55. data/lib/devise/failure_app.rb +98 -39
  56. data/lib/devise/hooks/activatable.rb +7 -6
  57. data/lib/devise/hooks/csrf_cleaner.rb +5 -1
  58. data/lib/devise/hooks/forgetable.rb +2 -0
  59. data/lib/devise/hooks/lockable.rb +7 -2
  60. data/lib/devise/hooks/proxy.rb +4 -2
  61. data/lib/devise/hooks/rememberable.rb +4 -2
  62. data/lib/devise/hooks/timeoutable.rb +16 -9
  63. data/lib/devise/hooks/trackable.rb +3 -1
  64. data/lib/devise/mailers/helpers.rb +15 -12
  65. data/lib/devise/mapping.rb +8 -2
  66. data/lib/devise/models.rb +3 -1
  67. data/lib/devise/models/authenticatable.rb +63 -36
  68. data/lib/devise/models/confirmable.rb +121 -41
  69. data/lib/devise/models/database_authenticatable.rb +66 -23
  70. data/lib/devise/models/lockable.rb +30 -17
  71. data/lib/devise/models/omniauthable.rb +3 -1
  72. data/lib/devise/models/recoverable.rb +62 -26
  73. data/lib/devise/models/registerable.rb +2 -0
  74. data/lib/devise/models/rememberable.rb +62 -33
  75. data/lib/devise/models/timeoutable.rb +4 -8
  76. data/lib/devise/models/trackable.rb +12 -3
  77. data/lib/devise/models/validatable.rb +16 -9
  78. data/lib/devise/modules.rb +12 -10
  79. data/lib/devise/omniauth.rb +2 -0
  80. data/lib/devise/omniauth/config.rb +2 -0
  81. data/lib/devise/omniauth/url_helpers.rb +14 -5
  82. data/lib/devise/orm/active_record.rb +5 -1
  83. data/lib/devise/orm/mongoid.rb +6 -2
  84. data/lib/devise/parameter_filter.rb +2 -0
  85. data/lib/devise/parameter_sanitizer.rb +131 -69
  86. data/lib/devise/rails.rb +10 -13
  87. data/lib/devise/rails/routes.rb +147 -116
  88. data/lib/devise/rails/warden_compat.rb +3 -10
  89. data/lib/devise/secret_key_finder.rb +25 -0
  90. data/lib/devise/strategies/authenticatable.rb +20 -9
  91. data/lib/devise/strategies/base.rb +3 -1
  92. data/lib/devise/strategies/database_authenticatable.rb +8 -5
  93. data/lib/devise/strategies/rememberable.rb +15 -3
  94. data/lib/devise/test/controller_helpers.rb +165 -0
  95. data/lib/devise/test/integration_helpers.rb +63 -0
  96. data/lib/devise/test_helpers.rb +7 -124
  97. data/lib/devise/time_inflector.rb +4 -2
  98. data/lib/devise/token_generator.rb +3 -41
  99. data/lib/devise/version.rb +3 -1
  100. data/lib/generators/active_record/devise_generator.rb +47 -10
  101. data/lib/generators/active_record/templates/migration.rb +9 -7
  102. data/lib/generators/active_record/templates/migration_existing.rb +9 -7
  103. data/lib/generators/devise/controllers_generator.rb +46 -0
  104. data/lib/generators/devise/devise_generator.rb +9 -5
  105. data/lib/generators/devise/install_generator.rb +22 -0
  106. data/lib/generators/devise/orm_helpers.rb +8 -19
  107. data/lib/generators/devise/views_generator.rb +51 -28
  108. data/lib/generators/mongoid/devise_generator.rb +22 -19
  109. data/lib/generators/templates/README +5 -12
  110. data/lib/generators/templates/controllers/README +14 -0
  111. data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
  112. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
  113. data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
  114. data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
  115. data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
  116. data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
  117. data/lib/generators/templates/devise.rb +64 -35
  118. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  119. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  120. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  121. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  122. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  123. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +2 -2
  124. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
  125. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
  126. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +6 -6
  127. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
  128. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +6 -6
  129. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -2
  130. data/test/controllers/custom_registrations_controller_test.rb +42 -0
  131. data/test/controllers/custom_strategy_test.rb +10 -6
  132. data/test/controllers/helper_methods_test.rb +24 -0
  133. data/test/controllers/helpers_test.rb +88 -40
  134. data/test/controllers/inherited_controller_i18n_messages_test.rb +53 -0
  135. data/test/controllers/internal_helpers_test.rb +31 -22
  136. data/test/controllers/load_hooks_controller_test.rb +21 -0
  137. data/test/controllers/passwords_controller_test.rb +8 -5
  138. data/test/controllers/sessions_controller_test.rb +42 -33
  139. data/test/controllers/url_helpers_test.rb +13 -5
  140. data/test/delegator_test.rb +3 -1
  141. data/test/devise_test.rb +34 -19
  142. data/test/failure_app_test.rb +150 -42
  143. data/test/generators/active_record_generator_test.rb +58 -31
  144. data/test/generators/controllers_generator_test.rb +50 -0
  145. data/test/generators/devise_generator_test.rb +4 -2
  146. data/test/generators/install_generator_test.rb +16 -3
  147. data/test/generators/mongoid_generator_test.rb +5 -3
  148. data/test/generators/views_generator_test.rb +40 -2
  149. data/test/helpers/devise_helper_test.rb +20 -20
  150. data/test/integration/authenticatable_test.rb +134 -141
  151. data/test/integration/confirmable_test.rb +109 -67
  152. data/test/integration/database_authenticatable_test.rb +36 -23
  153. data/test/integration/http_authenticatable_test.rb +29 -20
  154. data/test/integration/lockable_test.rb +52 -49
  155. data/test/integration/mounted_engine_test.rb +38 -0
  156. data/test/integration/omniauthable_test.rb +30 -15
  157. data/test/integration/recoverable_test.rb +76 -61
  158. data/test/integration/registerable_test.rb +107 -91
  159. data/test/integration/rememberable_test.rb +82 -30
  160. data/test/integration/timeoutable_test.rb +48 -40
  161. data/test/integration/trackable_test.rb +15 -8
  162. data/test/mailers/confirmation_instructions_test.rb +16 -14
  163. data/test/mailers/email_changed_test.rb +132 -0
  164. data/test/mailers/mailer_test.rb +20 -0
  165. data/test/mailers/reset_password_instructions_test.rb +13 -11
  166. data/test/mailers/unlock_instructions_test.rb +12 -10
  167. data/test/mapping_test.rb +15 -6
  168. data/test/models/authenticatable_test.rb +15 -3
  169. data/test/models/confirmable_test.rb +190 -95
  170. data/test/models/database_authenticatable_test.rb +75 -41
  171. data/test/models/lockable_test.rb +115 -61
  172. data/test/models/omniauthable_test.rb +3 -1
  173. data/test/models/recoverable_test.rb +116 -37
  174. data/test/models/registerable_test.rb +3 -1
  175. data/test/models/rememberable_test.rb +95 -94
  176. data/test/models/serializable_test.rb +19 -8
  177. data/test/models/timeoutable_test.rb +10 -8
  178. data/test/models/trackable_test.rb +50 -1
  179. data/test/models/validatable_test.rb +24 -30
  180. data/test/models_test.rb +19 -8
  181. data/test/omniauth/config_test.rb +15 -11
  182. data/test/omniauth/url_helpers_test.rb +8 -9
  183. data/test/orm/active_record.rb +16 -2
  184. data/test/orm/mongoid.rb +4 -2
  185. data/test/parameter_sanitizer_test.rb +53 -57
  186. data/test/rails_app/app/active_record/admin.rb +2 -0
  187. data/test/rails_app/app/active_record/shim.rb +3 -1
  188. data/test/rails_app/app/active_record/user.rb +14 -0
  189. data/test/rails_app/app/active_record/user_on_engine.rb +9 -0
  190. data/test/rails_app/app/active_record/user_on_main_app.rb +9 -0
  191. data/test/rails_app/app/active_record/user_with_validations.rb +12 -0
  192. data/test/rails_app/app/active_record/user_without_email.rb +10 -0
  193. data/test/rails_app/app/controllers/admins/sessions_controller.rb +3 -1
  194. data/test/rails_app/app/controllers/admins_controller.rb +3 -6
  195. data/test/rails_app/app/controllers/application_controller.rb +7 -3
  196. data/test/rails_app/app/controllers/application_with_fake_engine.rb +32 -0
  197. data/test/rails_app/app/controllers/custom/registrations_controller.rb +33 -0
  198. data/test/rails_app/app/controllers/home_controller.rb +7 -1
  199. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +3 -1
  200. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +3 -1
  201. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +7 -5
  202. data/test/rails_app/app/controllers/users_controller.rb +8 -6
  203. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  204. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +5 -0
  205. data/test/rails_app/app/mailers/users/mailer.rb +3 -10
  206. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +6 -0
  207. data/test/rails_app/app/mongoid/admin.rb +13 -11
  208. data/test/rails_app/app/mongoid/shim.rb +4 -2
  209. data/test/rails_app/app/mongoid/user.rb +30 -19
  210. data/test/rails_app/app/mongoid/user_on_engine.rb +41 -0
  211. data/test/rails_app/app/mongoid/user_on_main_app.rb +41 -0
  212. data/test/rails_app/app/mongoid/user_with_validations.rb +37 -0
  213. data/test/rails_app/app/mongoid/user_without_email.rb +35 -0
  214. data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
  215. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
  216. data/test/rails_app/app/views/home/index.html.erb +1 -1
  217. data/test/rails_app/app/views/home/join.html.erb +1 -1
  218. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
  219. data/test/rails_app/app/views/layouts/application.html.erb +1 -1
  220. data/test/rails_app/config/application.rb +13 -5
  221. data/test/rails_app/config/boot.rb +17 -4
  222. data/test/rails_app/config/environment.rb +2 -0
  223. data/test/rails_app/config/environments/development.rb +2 -0
  224. data/test/rails_app/config/environments/production.rb +10 -2
  225. data/test/rails_app/config/environments/test.rb +14 -3
  226. data/test/rails_app/config/initializers/backtrace_silencers.rb +2 -0
  227. data/test/rails_app/config/initializers/devise.rb +22 -21
  228. data/test/rails_app/config/initializers/inflections.rb +2 -0
  229. data/test/rails_app/config/initializers/secret_token.rb +3 -6
  230. data/test/rails_app/config/initializers/session_store.rb +2 -0
  231. data/test/rails_app/config/routes.rb +67 -43
  232. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +16 -10
  233. data/test/rails_app/db/schema.rb +2 -0
  234. data/test/rails_app/lib/shared_admin.rb +10 -4
  235. data/test/rails_app/lib/shared_user.rb +4 -1
  236. data/test/rails_app/lib/shared_user_without_email.rb +28 -0
  237. data/test/rails_app/lib/shared_user_without_omniauth.rb +15 -0
  238. data/test/rails_test.rb +11 -0
  239. data/test/routes_test.rb +92 -61
  240. data/test/secret_key_finder_test.rb +97 -0
  241. data/test/support/action_controller/record_identifier.rb +12 -0
  242. data/test/support/assertions.rb +4 -14
  243. data/test/support/helpers.rb +23 -10
  244. data/test/support/http_method_compatibility.rb +53 -0
  245. data/test/support/integration.rb +19 -16
  246. data/test/support/mongoid.yml +6 -0
  247. data/test/support/webrat/integrations/rails.rb +11 -0
  248. data/test/{test_helpers_test.rb → test/controller_helpers_test.rb} +60 -40
  249. data/test/test/integration_helpers_test.rb +34 -0
  250. data/test/test_helper.rb +9 -0
  251. data/test/test_models.rb +8 -6
  252. metadata +123 -53
  253. data/gemfiles/Gemfile.rails-3.2.x +0 -31
  254. data/gemfiles/Gemfile.rails-3.2.x.lock +0 -159
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Controllers
3
5
  # Create url helpers to be used with resource/scope configuration. Acts as
@@ -42,14 +44,14 @@ module Devise
42
44
  [:path, :url].each do |path_or_url|
43
45
  actions.each do |action|
44
46
  action = action ? "#{action}_" : ""
45
- method = "#{action}#{module_name}_#{path_or_url}"
47
+ method = :"#{action}#{module_name}_#{path_or_url}"
46
48
 
47
- class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
48
- def #{method}(resource_or_scope, *args)
49
- scope = Devise::Mapping.find_scope!(resource_or_scope)
50
- _devise_route_context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
51
- end
52
- URL_HELPERS
49
+ define_method method do |resource_or_scope, *args|
50
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
51
+ router_name = Devise.mappings[scope].router_name
52
+ context = router_name ? send(router_name) : _devise_route_context
53
+ context.send("#{action}#{scope}_#{module_name}_#{path_or_url}", *args)
54
+ end
53
55
  end
54
56
  end
55
57
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  # Checks the scope in the given environment and returns the associated failure app.
3
5
  class Delegator
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcrypt'
4
+
5
+ module Devise
6
+ module Encryptor
7
+ def self.digest(klass, password)
8
+ if klass.pepper.present?
9
+ password = "#{password}#{klass.pepper}"
10
+ end
11
+ ::BCrypt::Password.create(password, cost: klass.stretches).to_s
12
+ end
13
+
14
+ def self.compare(klass, hashed_password, password)
15
+ return false if hashed_password.blank?
16
+ bcrypt = ::BCrypt::Password.new(hashed_password)
17
+ if klass.pepper.present?
18
+ password = "#{password}#{klass.pepper}"
19
+ end
20
+ password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
21
+ Devise.secure_compare(password, hashed_password)
22
+ end
23
+ end
24
+ end
@@ -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,38 @@ 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(env)
75
+ self.response = recall_app(warden_options[:recall]).call(request.env)
54
76
  end
55
77
 
56
78
  def redirect
57
79
  store_location!
58
- if flash[:timedout] && flash[:alert]
59
- flash.keep(:timedout)
60
- flash.keep(:alert)
61
- else
62
- 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
63
87
  end
64
88
  redirect_to redirect_url
65
89
  end
@@ -78,6 +102,9 @@ module Devise
78
102
  options[:resource_name] = scope
79
103
  options[:scope] = "devise.failure"
80
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"))
81
108
  options = i18n_options(options)
82
109
 
83
110
  I18n.t(:"#{scope}.#{message}", options)
@@ -88,7 +115,7 @@ module Devise
88
115
 
89
116
  def redirect_url
90
117
  if warden_message == :timeout
91
- flash[:timedout] = true
118
+ flash[:timedout] = true if is_flashing_format?
92
119
 
93
120
  path = if request.get?
94
121
  attempted_path
@@ -96,26 +123,36 @@ module Devise
96
123
  request.referrer
97
124
  end
98
125
 
99
- path || scope_path
126
+ path || scope_url
100
127
  else
101
- scope_path
128
+ scope_url
102
129
  end
103
130
  end
104
131
 
105
- def scope_path
132
+ def route(scope)
133
+ :"new_#{scope}_session_url"
134
+ end
135
+
136
+ def scope_url
106
137
  opts = {}
107
- 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
+
108
145
  opts[:format] = request_format unless skip_format?
109
146
 
110
- config = Rails.application.config
111
- opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
147
+ opts[:script_name] = relative_url_root if relative_url_root?
112
148
 
113
- context = send(Devise.available_router_name)
149
+ router_name = Devise.mappings[scope].router_name || Devise.available_router_name
150
+ context = send(router_name)
114
151
 
115
152
  if context.respond_to?(route)
116
153
  context.send(route, opts)
117
- elsif respond_to?(:root_path)
118
- root_path(opts)
154
+ elsif respond_to?(:root_url)
155
+ root_url(opts)
119
156
  else
120
157
  "/"
121
158
  end
@@ -125,12 +162,12 @@ module Devise
125
162
  %w(html */*).include? request_format.to_s
126
163
  end
127
164
 
128
- # Choose whether we should respond in a http authentication fashion,
165
+ # Choose whether we should respond in an HTTP authentication fashion,
129
166
  # including 401 and optional headers.
130
167
  #
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
168
+ # This method allows the user to explicitly disable HTTP authentication
169
+ # on AJAX requests in case they want to redirect on failures instead of
170
+ # handling the errors on their own. This is useful in case your AJAX API
134
171
  # is the same as your public API and uses a format like JSON (so you
135
172
  # cannot mark JSON as a navigational format).
136
173
  def http_auth?
@@ -141,19 +178,19 @@ module Devise
141
178
  end
142
179
  end
143
180
 
144
- # It does not make sense to send authenticate headers in ajax requests
181
+ # It doesn't make sense to send authenticate headers in AJAX requests
145
182
  # or if the user disabled them.
146
183
  def http_auth_header?
147
- Devise.mappings[scope].to.http_authenticatable && !request.xhr?
184
+ scope_class.http_authenticatable && !request.xhr?
148
185
  end
149
186
 
150
187
  def http_auth_body
151
188
  return i18n_message unless request_format
152
189
  method = "to_#{request_format}"
153
190
  if method == "to_xml"
154
- { :error => i18n_message }.to_xml(:root => "errors")
191
+ { error: i18n_message }.to_xml(root: "errors")
155
192
  elsif {}.respond_to?(method)
156
- { :error => i18n_message }.send(method)
193
+ { error: i18n_message }.send(method)
157
194
  else
158
195
  i18n_message
159
196
  end
@@ -167,11 +204,11 @@ module Devise
167
204
  end
168
205
 
169
206
  def warden
170
- env['warden']
207
+ request.respond_to?(:get_header) ? request.get_header("warden") : request.env["warden"]
171
208
  end
172
209
 
173
210
  def warden_options
174
- env['warden.options']
211
+ request.respond_to?(:get_header) ? request.get_header("warden.options") : request.env["warden.options"]
175
212
  end
176
213
 
177
214
  def warden_message
@@ -182,14 +219,18 @@ module Devise
182
219
  @scope ||= warden_options[:scope] || Devise.default_scope
183
220
  end
184
221
 
222
+ def scope_class
223
+ @scope_class ||= Devise.mappings[scope].to
224
+ end
225
+
185
226
  def attempted_path
186
227
  warden_options[:attempted_path]
187
228
  end
188
229
 
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.
230
+ # Stores requested URI to redirect the user after signing in. We can't use
231
+ # the scoped session provided by warden here, since the user is not
232
+ # authenticated yet, but we still need to store the URI based on scope, so
233
+ # different scopes would never use the same URI to redirect.
193
234
  def store_location!
194
235
  store_location_for(scope, attempted_path) if request.get? && !http_auth?
195
236
  end
@@ -198,8 +239,26 @@ module Devise
198
239
  Devise.navigational_formats.include?(request_format)
199
240
  end
200
241
 
242
+ # Check if flash messages should be emitted. Default is to do it on
243
+ # navigational formats
244
+ def is_flashing_format?
245
+ is_navigational_format?
246
+ end
247
+
201
248
  def request_format
202
249
  @request_format ||= request.format.try(:ref)
203
250
  end
251
+
252
+ def relative_url_root
253
+ @relative_url_root ||= begin
254
+ config = Rails.application.config
255
+
256
+ config.try(:relative_url_root) || config.action_controller.try(:relative_url_root)
257
+ end
258
+ end
259
+
260
+ def relative_url_root?
261
+ relative_url_root.present?
262
+ end
204
263
  end
205
264
  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