devise 2.1.2 → 3.5.10

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 (242) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +39 -10
  3. data/.yardopts +9 -0
  4. data/{CHANGELOG.rdoc → CHANGELOG.md} +445 -112
  5. data/CODE_OF_CONDUCT.md +22 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +10 -15
  8. data/Gemfile.lock +151 -129
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +256 -96
  11. data/Rakefile +4 -2
  12. data/app/controllers/devise/confirmations_controller.rb +15 -7
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +6 -2
  14. data/app/controllers/devise/passwords_controller.rb +33 -9
  15. data/app/controllers/devise/registrations_controller.rb +66 -26
  16. data/app/controllers/devise/sessions_controller.rb +52 -21
  17. data/app/controllers/devise/unlocks_controller.rb +11 -6
  18. data/app/controllers/devise_controller.rb +65 -58
  19. data/app/helpers/devise_helper.rb +2 -2
  20. data/app/mailers/devise/mailer.rb +19 -10
  21. data/app/views/devise/confirmations/new.html.erb +8 -4
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +2 -2
  23. data/app/views/devise/mailer/password_change.html.erb +3 -0
  24. data/app/views/devise/mailer/reset_password_instructions.html.erb +2 -2
  25. data/app/views/devise/mailer/unlock_instructions.html.erb +2 -2
  26. data/app/views/devise/passwords/edit.html.erb +15 -6
  27. data/app/views/devise/passwords/new.html.erb +8 -4
  28. data/app/views/devise/registrations/edit.html.erb +29 -15
  29. data/app/views/devise/registrations/new.html.erb +19 -8
  30. data/app/views/devise/sessions/new.html.erb +17 -8
  31. data/app/views/devise/shared/{_links.erb → _links.html.erb} +4 -4
  32. data/app/views/devise/unlocks/new.html.erb +8 -4
  33. data/config/locales/en.yml +51 -47
  34. data/devise.gemspec +8 -6
  35. data/devise.png +0 -0
  36. data/gemfiles/Gemfile.rails-3.2-stable +29 -0
  37. data/gemfiles/Gemfile.rails-3.2-stable.lock +172 -0
  38. data/gemfiles/Gemfile.rails-4.0-stable +30 -0
  39. data/gemfiles/Gemfile.rails-4.0-stable.lock +166 -0
  40. data/gemfiles/Gemfile.rails-4.1-stable +30 -0
  41. data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
  42. data/gemfiles/Gemfile.rails-4.2-stable +30 -0
  43. data/gemfiles/Gemfile.rails-4.2-stable.lock +193 -0
  44. data/lib/devise/controllers/helpers.rb +126 -108
  45. data/lib/devise/controllers/rememberable.rb +19 -17
  46. data/lib/devise/controllers/scoped_views.rb +1 -1
  47. data/lib/devise/controllers/sign_in_out.rb +96 -0
  48. data/lib/devise/controllers/store_location.rb +58 -0
  49. data/lib/devise/controllers/url_helpers.rb +7 -7
  50. data/lib/devise/encryptor.rb +22 -0
  51. data/lib/devise/failure_app.rb +85 -25
  52. data/lib/devise/hooks/activatable.rb +5 -6
  53. data/lib/devise/hooks/csrf_cleaner.rb +7 -0
  54. data/lib/devise/hooks/forgetable.rb +1 -1
  55. data/lib/devise/hooks/lockable.rb +2 -2
  56. data/lib/devise/hooks/proxy.rb +21 -0
  57. data/lib/devise/hooks/rememberable.rb +5 -4
  58. data/lib/devise/hooks/timeoutable.rb +16 -8
  59. data/lib/devise/hooks/trackable.rb +1 -1
  60. data/lib/devise/mailers/helpers.rb +27 -23
  61. data/lib/devise/mapping.rb +11 -7
  62. data/lib/devise/models/authenticatable.rb +82 -66
  63. data/lib/devise/models/confirmable.rb +142 -55
  64. data/lib/devise/models/database_authenticatable.rb +59 -15
  65. data/lib/devise/models/lockable.rb +41 -30
  66. data/lib/devise/models/omniauthable.rb +3 -3
  67. data/lib/devise/models/recoverable.rb +56 -41
  68. data/lib/devise/models/rememberable.rb +65 -27
  69. data/lib/devise/models/timeoutable.rb +2 -8
  70. data/lib/devise/models/trackable.rb +6 -4
  71. data/lib/devise/models/validatable.rb +9 -9
  72. data/lib/devise/models.rb +4 -13
  73. data/lib/devise/modules.rb +10 -11
  74. data/lib/devise/omniauth/url_helpers.rb +2 -2
  75. data/lib/devise/orm/active_record.rb +1 -1
  76. data/lib/devise/orm/mongoid.rb +1 -1
  77. data/lib/devise/{param_filter.rb → parameter_filter.rb} +10 -11
  78. data/lib/devise/parameter_sanitizer.rb +99 -0
  79. data/lib/devise/rails/routes.rb +173 -115
  80. data/lib/devise/rails/warden_compat.rb +10 -31
  81. data/lib/devise/rails.rb +14 -12
  82. data/lib/devise/strategies/authenticatable.rb +26 -26
  83. data/lib/devise/strategies/base.rb +1 -1
  84. data/lib/devise/strategies/database_authenticatable.rb +8 -4
  85. data/lib/devise/strategies/rememberable.rb +15 -5
  86. data/lib/devise/test_helpers.rb +7 -5
  87. data/lib/devise/time_inflector.rb +14 -0
  88. data/lib/devise/token_generator.rb +70 -0
  89. data/lib/devise/version.rb +1 -1
  90. data/lib/devise.rb +110 -52
  91. data/lib/generators/active_record/devise_generator.rb +34 -18
  92. data/lib/generators/active_record/templates/migration.rb +5 -6
  93. data/lib/generators/active_record/templates/migration_existing.rb +5 -6
  94. data/lib/generators/devise/controllers_generator.rb +44 -0
  95. data/lib/generators/devise/devise_generator.rb +5 -3
  96. data/lib/generators/devise/install_generator.rb +5 -0
  97. data/lib/generators/devise/orm_helpers.rb +25 -6
  98. data/lib/generators/devise/views_generator.rb +52 -22
  99. data/lib/generators/mongoid/devise_generator.rb +21 -26
  100. data/lib/generators/templates/README +9 -5
  101. data/lib/generators/templates/controllers/README +14 -0
  102. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  103. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  104. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  105. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  106. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  107. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  108. data/lib/generators/templates/devise.rb +80 -43
  109. data/lib/generators/templates/markerb/confirmation_instructions.markerb +2 -2
  110. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  111. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  112. data/lib/generators/templates/markerb/unlock_instructions.markerb +2 -2
  113. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +3 -2
  114. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
  115. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
  116. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -6
  117. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
  118. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +6 -6
  119. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +3 -2
  120. data/script/cached-bundle +49 -0
  121. data/script/s3-put +71 -0
  122. data/test/controllers/custom_registrations_controller_test.rb +40 -0
  123. data/test/controllers/helper_methods_test.rb +21 -0
  124. data/test/controllers/helpers_test.rb +95 -32
  125. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  126. data/test/controllers/internal_helpers_test.rb +39 -14
  127. data/test/controllers/load_hooks_controller_test.rb +19 -0
  128. data/test/controllers/passwords_controller_test.rb +31 -0
  129. data/test/controllers/sessions_controller_test.rb +66 -6
  130. data/test/controllers/url_helpers_test.rb +10 -4
  131. data/test/delegator_test.rb +1 -1
  132. data/test/devise_test.rb +45 -10
  133. data/test/failure_app_test.rb +121 -27
  134. data/test/generators/active_record_generator_test.rb +48 -8
  135. data/test/generators/controllers_generator_test.rb +48 -0
  136. data/test/generators/devise_generator_test.rb +2 -2
  137. data/test/generators/mongoid_generator_test.rb +3 -3
  138. data/test/generators/views_generator_test.rb +54 -3
  139. data/test/helpers/devise_helper_test.rb +18 -20
  140. data/test/integration/authenticatable_test.rb +161 -65
  141. data/test/integration/confirmable_test.rb +146 -77
  142. data/test/integration/database_authenticatable_test.rb +43 -30
  143. data/test/integration/http_authenticatable_test.rb +30 -22
  144. data/test/integration/lockable_test.rb +64 -49
  145. data/test/integration/omniauthable_test.rb +17 -15
  146. data/test/integration/recoverable_test.rb +111 -70
  147. data/test/integration/registerable_test.rb +114 -79
  148. data/test/integration/rememberable_test.rb +87 -31
  149. data/test/integration/timeoutable_test.rb +77 -33
  150. data/test/integration/trackable_test.rb +5 -5
  151. data/test/mailers/confirmation_instructions_test.rb +28 -8
  152. data/test/mailers/reset_password_instructions_test.rb +21 -8
  153. data/test/mailers/unlock_instructions_test.rb +20 -6
  154. data/test/mapping_test.rb +12 -5
  155. data/test/models/authenticatable_test.rb +17 -1
  156. data/test/models/confirmable_test.rb +216 -62
  157. data/test/models/database_authenticatable_test.rb +129 -49
  158. data/test/models/lockable_test.rb +132 -45
  159. data/test/models/recoverable_test.rb +100 -54
  160. data/test/models/rememberable_test.rb +89 -94
  161. data/test/models/serializable_test.rb +12 -11
  162. data/test/models/timeoutable_test.rb +6 -1
  163. data/test/models/trackable_test.rb +28 -0
  164. data/test/models/validatable_test.rb +31 -21
  165. data/test/models_test.rb +22 -48
  166. data/test/omniauth/config_test.rb +4 -4
  167. data/test/omniauth/url_helpers_test.rb +7 -4
  168. data/test/orm/active_record.rb +1 -0
  169. data/test/orm/mongoid.rb +2 -3
  170. data/test/parameter_sanitizer_test.rb +81 -0
  171. data/test/rails_app/Rakefile +0 -4
  172. data/test/rails_app/app/active_record/shim.rb +1 -1
  173. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  174. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  175. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  176. data/test/rails_app/app/controllers/admins/sessions_controller.rb +1 -1
  177. data/test/rails_app/app/controllers/admins_controller.rb +0 -5
  178. data/test/rails_app/app/controllers/application_controller.rb +6 -2
  179. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  180. data/test/rails_app/app/controllers/custom/registrations_controller.rb +31 -0
  181. data/test/rails_app/app/controllers/home_controller.rb +1 -1
  182. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +1 -1
  183. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +1 -1
  184. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +4 -4
  185. data/test/rails_app/app/controllers/users_controller.rb +12 -4
  186. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  187. data/test/rails_app/app/mailers/users/mailer.rb +1 -1
  188. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  189. data/test/rails_app/app/mongoid/admin.rb +12 -10
  190. data/test/rails_app/app/mongoid/shim.rb +4 -5
  191. data/test/rails_app/app/mongoid/user.rb +19 -22
  192. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  193. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  194. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  195. data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
  196. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
  197. data/test/rails_app/app/views/home/index.html.erb +1 -1
  198. data/test/rails_app/app/views/home/join.html.erb +1 -1
  199. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
  200. data/test/rails_app/app/views/layouts/application.html.erb +1 -1
  201. data/test/rails_app/app/views/users/edit_form.html.erb +1 -0
  202. data/test/rails_app/bin/bundle +3 -0
  203. data/test/rails_app/bin/rails +4 -0
  204. data/test/rails_app/bin/rake +4 -0
  205. data/test/rails_app/config/application.rb +4 -5
  206. data/test/rails_app/config/boot.rb +9 -3
  207. data/test/rails_app/config/environment.rb +2 -2
  208. data/test/rails_app/config/environments/development.rb +19 -7
  209. data/test/rails_app/config/environments/production.rb +68 -17
  210. data/test/rails_app/config/environments/test.rb +24 -16
  211. data/test/rails_app/config/initializers/devise.rb +22 -20
  212. data/test/rails_app/config/initializers/secret_token.rb +8 -2
  213. data/test/rails_app/config/initializers/session_store.rb +1 -0
  214. data/test/rails_app/config/routes.rb +71 -46
  215. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +9 -12
  216. data/test/rails_app/db/schema.rb +21 -18
  217. data/test/rails_app/lib/shared_admin.rb +7 -4
  218. data/test/rails_app/lib/shared_user.rb +6 -3
  219. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  220. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  221. data/test/rails_test.rb +9 -0
  222. data/test/routes_test.rb +94 -78
  223. data/test/support/action_controller/record_identifier.rb +10 -0
  224. data/test/support/assertions.rb +2 -3
  225. data/test/support/helpers.rb +18 -32
  226. data/test/support/integration.rb +17 -16
  227. data/test/support/locale/en.yml +4 -0
  228. data/test/support/mongoid.yml +6 -0
  229. data/test/test_helper.rb +8 -1
  230. data/test/test_helpers_test.rb +64 -20
  231. data/test/test_models.rb +33 -0
  232. data/test/time_helpers.rb +137 -0
  233. metadata +172 -51
  234. data/app/views/devise/_links.erb +0 -3
  235. data/gemfiles/Gemfile.rails-3.1.x +0 -35
  236. data/gemfiles/Gemfile.rails-3.1.x.lock +0 -167
  237. data/lib/devise/models/token_authenticatable.rb +0 -77
  238. data/lib/devise/strategies/token_authenticatable.rb +0 -56
  239. data/test/indifferent_hash.rb +0 -33
  240. data/test/integration/token_authenticatable_test.rb +0 -161
  241. data/test/models/token_authenticatable_test.rb +0 -55
  242. data/test/rails_app/script/rails +0 -10
@@ -0,0 +1,58 @@
1
+ require "uri"
2
+
3
+ module Devise
4
+ module Controllers
5
+ # Provide the ability to store a location.
6
+ # Used to redirect back to a desired path after sign in.
7
+ # Included by default in all controllers.
8
+ module StoreLocation
9
+ # Returns and delete (if it's navigational format) the url stored in the session for
10
+ # the given scope. Useful for giving redirect backs after sign up:
11
+ #
12
+ # Example:
13
+ #
14
+ # redirect_to stored_location_for(:user) || root_path
15
+ #
16
+ def stored_location_for(resource_or_scope)
17
+ session_key = stored_location_key_for(resource_or_scope)
18
+
19
+ if is_navigational_format?
20
+ session.delete(session_key)
21
+ else
22
+ session[session_key]
23
+ end
24
+ end
25
+
26
+ # Stores the provided location to redirect the user after signing in.
27
+ # Useful in combination with the `stored_location_for` helper.
28
+ #
29
+ # Example:
30
+ #
31
+ # store_location_for(:user, dashboard_path)
32
+ # redirect_to user_omniauth_authorize_path(:facebook)
33
+ #
34
+ def store_location_for(resource_or_scope, location)
35
+ session_key = stored_location_key_for(resource_or_scope)
36
+ uri = parse_uri(location)
37
+ if uri
38
+ path = [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
39
+ path = [path, uri.fragment].compact.join('#')
40
+ session[session_key] = path
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def parse_uri(location)
47
+ location && URI.parse(location)
48
+ rescue URI::InvalidURIError
49
+ nil
50
+ end
51
+
52
+ def stored_location_key_for(resource_or_scope)
53
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
54
+ "#{scope}_return_to"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -42,14 +42,14 @@ module Devise
42
42
  [:path, :url].each do |path_or_url|
43
43
  actions.each do |action|
44
44
  action = action ? "#{action}_" : ""
45
- method = "#{action}#{module_name}_#{path_or_url}"
45
+ method = :"#{action}#{module_name}_#{path_or_url}"
46
46
 
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
47
+ define_method method do |resource_or_scope, *args|
48
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
49
+ router_name = Devise.mappings[scope].router_name
50
+ context = router_name ? send(router_name) : _devise_route_context
51
+ context.send("#{action}#{scope}_#{module_name}_#{path_or_url}", *args)
52
+ end
53
53
  end
54
54
  end
55
55
  end
@@ -0,0 +1,22 @@
1
+ require 'bcrypt'
2
+
3
+ module Devise
4
+ module Encryptor
5
+ def self.digest(klass, password)
6
+ if klass.pepper.present?
7
+ password = "#{password}#{klass.pepper}"
8
+ end
9
+ ::BCrypt::Password.create(password, cost: klass.stretches).to_s
10
+ end
11
+
12
+ def self.compare(klass, encrypted_password, password)
13
+ return false if encrypted_password.blank?
14
+ bcrypt = ::BCrypt::Password.new(encrypted_password)
15
+ if klass.pepper.present?
16
+ password = "#{password}#{klass.pepper}"
17
+ end
18
+ password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
19
+ Devise.secure_compare(password, encrypted_password)
20
+ end
21
+ end
22
+ end
@@ -13,16 +13,21 @@ module Devise
13
13
  include Rails.application.routes.url_helpers
14
14
  include Rails.application.routes.mounted_helpers
15
15
 
16
- delegate :flash, :to => :request
16
+ include Devise::Controllers::StoreLocation
17
+
18
+ delegate :flash, to: :request
17
19
 
18
20
  def self.call(env)
19
21
  @respond ||= action(:respond)
20
22
  @respond.call(env)
21
23
  end
22
24
 
25
+ # Try retrieving the URL options from the parent controller (usually
26
+ # ApplicationController). Instance methods are not supported at the moment,
27
+ # so only the class-level attribute is used.
23
28
  def self.default_url_options(*args)
24
- if defined?(ApplicationController)
25
- ApplicationController.default_url_options(*args)
29
+ if defined?(Devise.parent_controller.constantize)
30
+ Devise.parent_controller.constantize.try(:default_url_options) || {}
26
31
  else
27
32
  {}
28
33
  end
@@ -46,30 +51,55 @@ module Devise
46
51
  end
47
52
 
48
53
  def recall
49
- env["PATH_INFO"] = attempted_path
50
- flash.now[:alert] = i18n_message(:invalid)
54
+ config = Rails.application.config
55
+
56
+ if config.try(:relative_url_root)
57
+ base_path = Pathname.new(config.relative_url_root)
58
+ full_path = Pathname.new(attempted_path)
59
+
60
+ env["SCRIPT_NAME"] = config.relative_url_root
61
+ env["PATH_INFO"] = '/' + full_path.relative_path_from(base_path).to_s
62
+ else
63
+ env["PATH_INFO"] = attempted_path
64
+ end
65
+
66
+ flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
51
67
  self.response = recall_app(warden_options[:recall]).call(env)
52
68
  end
53
69
 
54
70
  def redirect
55
71
  store_location!
56
- if flash[:timedout] && flash[:alert]
57
- flash.keep(:timedout)
58
- flash.keep(:alert)
59
- else
60
- flash[:alert] = i18n_message
72
+ if is_flashing_format?
73
+ if flash[:timedout] && flash[:alert]
74
+ flash.keep(:timedout)
75
+ flash.keep(:alert)
76
+ else
77
+ flash[:alert] = i18n_message
78
+ end
61
79
  end
62
80
  redirect_to redirect_url
63
81
  end
64
82
 
65
83
  protected
66
84
 
85
+ def i18n_options(options)
86
+ options
87
+ end
88
+
67
89
  def i18n_message(default = nil)
68
90
  message = warden_message || default || :unauthenticated
69
91
 
70
92
  if message.is_a?(Symbol)
71
- I18n.t(:"#{scope}.#{message}", :resource_name => scope,
72
- :scope => "devise.failure", :default => [message])
93
+ options = {}
94
+ options[:resource_name] = scope
95
+ options[:scope] = "devise.failure"
96
+ options[:default] = [message]
97
+ auth_keys = scope_class.authentication_keys
98
+ keys = auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
99
+ options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
100
+ options = i18n_options(options)
101
+
102
+ I18n.t(:"#{scope}.#{message}", options)
73
103
  else
74
104
  message.to_s
75
105
  end
@@ -77,27 +107,47 @@ module Devise
77
107
 
78
108
  def redirect_url
79
109
  if warden_message == :timeout
80
- flash[:timedout] = true
81
- attempted_path || scope_path
110
+ flash[:timedout] = true if is_flashing_format?
111
+
112
+ path = if request.get?
113
+ attempted_path
114
+ else
115
+ request.referrer
116
+ end
117
+
118
+ path || scope_url
82
119
  else
83
- scope_path
120
+ scope_url
84
121
  end
85
122
  end
86
123
 
87
- def scope_path
124
+ def route(scope)
125
+ :"new_#{scope}_session_url"
126
+ end
127
+
128
+ def scope_url
88
129
  opts = {}
89
- route = :"new_#{scope}_session_path"
130
+ route = route(scope)
90
131
  opts[:format] = request_format unless skip_format?
91
132
 
92
133
  config = Rails.application.config
93
- opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
94
134
 
95
- context = send(Devise.available_router_name)
135
+ # Rails 4.2 goes into an infinite loop if opts[:script_name] is unset
136
+ if (Rails::VERSION::MAJOR >= 4) && (Rails::VERSION::MINOR >= 2)
137
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
138
+ else
139
+ if config.respond_to?(:relative_url_root) && config.relative_url_root.present?
140
+ opts[:script_name] = config.relative_url_root
141
+ end
142
+ end
143
+
144
+ router_name = Devise.mappings[scope].router_name || Devise.available_router_name
145
+ context = send(router_name)
96
146
 
97
147
  if context.respond_to?(route)
98
148
  context.send(route, opts)
99
- elsif respond_to?(:root_path)
100
- root_path(opts)
149
+ elsif respond_to?(:root_url)
150
+ root_url(opts)
101
151
  else
102
152
  "/"
103
153
  end
@@ -126,16 +176,16 @@ module Devise
126
176
  # It does not make sense to send authenticate headers in ajax requests
127
177
  # or if the user disabled them.
128
178
  def http_auth_header?
129
- Devise.mappings[scope].to.http_authenticatable && !request.xhr?
179
+ scope_class.http_authenticatable && !request.xhr?
130
180
  end
131
181
 
132
182
  def http_auth_body
133
183
  return i18n_message unless request_format
134
184
  method = "to_#{request_format}"
135
185
  if method == "to_xml"
136
- { :error => i18n_message }.to_xml(:root => "errors")
186
+ { error: i18n_message }.to_xml(root: "errors")
137
187
  elsif {}.respond_to?(method)
138
- { :error => i18n_message }.send(method)
188
+ { error: i18n_message }.send(method)
139
189
  else
140
190
  i18n_message
141
191
  end
@@ -164,6 +214,10 @@ module Devise
164
214
  @scope ||= warden_options[:scope] || Devise.default_scope
165
215
  end
166
216
 
217
+ def scope_class
218
+ @scope_class ||= Devise.mappings[scope].to
219
+ end
220
+
167
221
  def attempted_path
168
222
  warden_options[:attempted_path]
169
223
  end
@@ -173,13 +227,19 @@ module Devise
173
227
  # yet, but we still need to store the uri based on scope, so different scopes
174
228
  # would never use the same uri to redirect.
175
229
  def store_location!
176
- session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
230
+ store_location_for(scope, attempted_path) if request.get? && !http_auth?
177
231
  end
178
232
 
179
233
  def is_navigational_format?
180
234
  Devise.navigational_formats.include?(request_format)
181
235
  end
182
236
 
237
+ # Check if flash messages should be emitted. Default is to do it on
238
+ # navigational formats
239
+ def is_flashing_format?
240
+ is_navigational_format?
241
+ end
242
+
183
243
  def request_format
184
244
  @request_format ||= request.format.try(:ref)
185
245
  end
@@ -1,11 +1,10 @@
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
+ # Deny user access whenever their account is not active yet.
2
+ # We need this as hook to validate the user activity on each request
3
+ # and in case the user is using other strategies beside Devise ones.
5
4
  Warden::Manager.after_set_user do |record, warden, options|
6
5
  if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
7
6
  scope = options[:scope]
8
7
  warden.logout(scope)
9
- throw :warden, :scope => scope, :message => record.inactive_message
8
+ throw :warden, scope: scope, message: record.inactive_message
10
9
  end
11
- end
10
+ end
@@ -0,0 +1,7 @@
1
+ Warden::Manager.after_authentication do |record, warden, options|
2
+ clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
3
+ warden.winning_strategy.clean_up_csrf?
4
+ if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
5
+ warden.request.session.try(:delete, :_csrf_token)
6
+ end
7
+ end
@@ -4,6 +4,6 @@
4
4
  # This avoids forgetting deleted users.
5
5
  Warden::Manager.before_logout do |record, warden, options|
6
6
  if record.respond_to?(:forget_me!)
7
- Devise::Controllers::Rememberable::Proxy.new(warden).forget_me(record)
7
+ Devise::Hooks::Proxy.new(warden).forget_me(record)
8
8
  end
9
9
  end
@@ -1,7 +1,7 @@
1
1
  # After each sign in, if resource responds to failed_attempts, sets it to 0
2
2
  # 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|
3
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
4
4
  if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
5
- record.update_attribute(:failed_attempts, 0)
5
+ record.update_attribute(:failed_attempts, 0) unless record.failed_attempts.to_i.zero?
6
6
  end
7
7
  end
@@ -0,0 +1,21 @@
1
+ module Devise
2
+ module Hooks
3
+ # A small warden proxy so we can remember, forget and
4
+ # sign out users from hooks.
5
+ class Proxy #:nodoc:
6
+ include Devise::Controllers::Rememberable
7
+ include Devise::Controllers::SignInOut
8
+
9
+ attr_reader :warden
10
+ delegate :cookies, :env, to: :warden
11
+
12
+ def initialize(warden)
13
+ @warden = warden
14
+ end
15
+
16
+ def session
17
+ warden.request.session
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,7 @@
1
- Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
1
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
2
2
  scope = options[:scope]
3
- if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
4
- Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
3
+ if record.respond_to?(:remember_me) && options[:store] != false &&
4
+ record.remember_me && warden.authenticated?(scope)
5
+ Devise::Hooks::Proxy.new(warden).remember_me(record)
5
6
  end
6
- end
7
+ end
@@ -7,19 +7,27 @@ Warden::Manager.after_set_user do |record, warden, options|
7
7
  scope = options[:scope]
8
8
  env = warden.request.env
9
9
 
10
- if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
10
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
11
+ options[:store] != false && !env['devise.skip_timeoutable']
11
12
  last_request_at = warden.session(scope)['last_request_at']
12
13
 
13
- if record.timedout?(last_request_at) && !env['devise.skip_timeout']
14
- warden.logout(scope)
15
- if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
16
- record.reset_authentication_token!
17
- end
18
- throw :warden, :scope => scope, :message => :timeout
14
+ if last_request_at.is_a? Integer
15
+ last_request_at = Time.at(last_request_at).utc
16
+ elsif last_request_at.is_a? String
17
+ last_request_at = Time.parse(last_request_at)
18
+ end
19
+
20
+ proxy = Devise::Hooks::Proxy.new(warden)
21
+
22
+ if record.timedout?(last_request_at) &&
23
+ !env['devise.skip_timeout'] &&
24
+ !proxy.remember_me_is_active?(record)
25
+ Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
26
+ throw :warden, scope: scope, message: :timeout
19
27
  end
20
28
 
21
29
  unless env['devise.skip_trackable']
22
- warden.session(scope)['last_request_at'] = Time.now.utc
30
+ warden.session(scope)['last_request_at'] = Time.now.utc.to_i
23
31
  end
24
32
  end
25
33
  end
@@ -2,7 +2,7 @@
2
2
  # This is only triggered when the user is explicitly set (with set_user)
3
3
  # and on authentication. Retrieving the user from session (:fetch) does
4
4
  # not trigger it.
5
- Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
5
+ Warden::Manager.after_set_user except: :fetch do |record, warden, options|
6
6
  if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope]) && !warden.request.env['devise.skip_trackable']
7
7
  record.update_tracked_fields!(warden.request)
8
8
  end
@@ -11,9 +11,9 @@ module Devise
11
11
  protected
12
12
 
13
13
  # Configure default email options
14
- def devise_mail(record, action)
14
+ def devise_mail(record, action, opts={})
15
15
  initialize_from_record(record)
16
- mail headers_for(action)
16
+ mail headers_for(action, opts)
17
17
  end
18
18
 
19
19
  def initialize_from_record(record)
@@ -25,28 +25,32 @@ module Devise
25
25
  @devise_mapping ||= Devise.mappings[scope_name]
26
26
  end
27
27
 
28
- def headers_for(action)
28
+ def headers_for(action, opts)
29
29
  headers = {
30
- :subject => translate(devise_mapping, action),
31
- :from => mailer_sender(devise_mapping),
32
- :to => resource.email,
33
- :template_path => template_paths
34
- }
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
36
+ }.merge(opts)
35
37
 
36
- if resource.respond_to?(:headers_for)
37
- headers.merge!(resource.headers_for(action))
38
- end
38
+ @email = headers[:to]
39
+ headers
40
+ end
39
41
 
40
- unless headers.key?(:reply_to)
41
- headers[:reply_to] = headers[:from]
42
- end
42
+ def mailer_reply_to(mapping)
43
+ mailer_sender(mapping, :reply_to)
44
+ end
43
45
 
44
- headers
46
+ def mailer_from(mapping)
47
+ mailer_sender(mapping, :from)
45
48
  end
46
49
 
47
- def mailer_sender(mapping)
48
- if default_params[:from].present?
49
- default_params[:from]
50
+ def mailer_sender(mapping, sender = :from)
51
+ default_sender = default_params[sender]
52
+ if default_sender.present?
53
+ default_sender.respond_to?(:to_proc) ? instance_eval(&default_sender) : default_sender
50
54
  elsif Devise.mailer_sender.is_a?(Proc)
51
55
  Devise.mailer_sender.call(mapping.name)
52
56
  else
@@ -55,12 +59,12 @@ module Devise
55
59
  end
56
60
 
57
61
  def template_paths
58
- template_path = [self.class.mailer_name]
62
+ template_path = _prefixes.dup
59
63
  template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
60
64
  template_path
61
65
  end
62
66
 
63
- # Setup a subject doing an I18n lookup. At first, it attemps to set a subject
67
+ # Setup a subject doing an I18n lookup. At first, it attempts to set a subject
64
68
  # based on the current mapping:
65
69
  #
66
70
  # en:
@@ -77,9 +81,9 @@ module Devise
77
81
  # confirmation_instructions:
78
82
  # subject: '...'
79
83
  #
80
- def translate(mapping, key)
81
- I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
82
- :default => [:subject, key.to_s.humanize])
84
+ def subject_for(key)
85
+ I18n.t(:"#{devise_mapping.name}_subject", scope: [:devise, :mailer, key],
86
+ default: [:subject, key.to_s.humanize])
83
87
  end
84
88
  end
85
89
  end