devise 3.0.0 → 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 (242) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +351 -0
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +422 -130
  5. data/app/controllers/devise/confirmations_controller.rb +17 -6
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
  7. data/app/controllers/devise/passwords_controller.rb +23 -8
  8. data/app/controllers/devise/registrations_controller.rb +70 -28
  9. data/app/controllers/devise/sessions_controller.rb +49 -17
  10. data/app/controllers/devise/unlocks_controller.rb +11 -4
  11. data/app/controllers/devise_controller.rb +74 -34
  12. data/app/helpers/devise_helper.rb +23 -18
  13. data/app/mailers/devise/mailer.rb +25 -10
  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} +10 -10
  27. data/app/views/devise/unlocks/new.html.erb +9 -5
  28. data/config/locales/en.yml +26 -20
  29. data/lib/devise/controllers/helpers.rb +122 -125
  30. data/lib/devise/controllers/rememberable.rb +14 -14
  31. data/lib/devise/controllers/scoped_views.rb +3 -1
  32. data/lib/devise/controllers/sign_in_out.rb +121 -0
  33. data/lib/devise/controllers/store_location.rb +76 -0
  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 +132 -42
  38. data/lib/devise/hooks/activatable.rb +7 -6
  39. data/lib/devise/hooks/csrf_cleaner.rb +9 -0
  40. data/lib/devise/hooks/forgetable.rb +3 -1
  41. data/lib/devise/hooks/lockable.rb +5 -3
  42. data/lib/devise/hooks/proxy.rb +23 -0
  43. data/lib/devise/hooks/rememberable.rb +7 -4
  44. data/lib/devise/hooks/timeoutable.rb +18 -8
  45. data/lib/devise/hooks/trackable.rb +3 -1
  46. data/lib/devise/mailers/helpers.rb +15 -18
  47. data/lib/devise/mapping.rb +9 -3
  48. data/lib/devise/models/authenticatable.rb +102 -80
  49. data/lib/devise/models/confirmable.rb +154 -72
  50. data/lib/devise/models/database_authenticatable.rb +125 -25
  51. data/lib/devise/models/lockable.rb +50 -29
  52. data/lib/devise/models/omniauthable.rb +3 -1
  53. data/lib/devise/models/recoverable.rb +72 -50
  54. data/lib/devise/models/registerable.rb +4 -0
  55. data/lib/devise/models/rememberable.rb +65 -32
  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 +6 -13
  60. data/lib/devise/modules.rb +12 -11
  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 +144 -34
  68. data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
  69. data/lib/devise/rails/routes.rb +191 -127
  70. data/lib/devise/rails/warden_compat.rb +2 -1
  71. data/lib/devise/rails.rb +13 -20
  72. data/lib/devise/secret_key_finder.rb +27 -0
  73. data/lib/devise/strategies/authenticatable.rb +21 -22
  74. data/lib/devise/strategies/base.rb +3 -1
  75. data/lib/devise/strategies/database_authenticatable.rb +15 -4
  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 -123
  80. data/lib/devise/time_inflector.rb +4 -2
  81. data/lib/devise/token_generator.rb +32 -0
  82. data/lib/devise/version.rb +3 -1
  83. data/lib/devise.rb +124 -78
  84. data/lib/generators/active_record/devise_generator.rb +64 -15
  85. data/lib/generators/active_record/templates/migration.rb +9 -8
  86. data/lib/generators/active_record/templates/migration_existing.rb +9 -8
  87. data/lib/generators/devise/controllers_generator.rb +46 -0
  88. data/lib/generators/devise/devise_generator.rb +10 -6
  89. data/lib/generators/devise/install_generator.rb +19 -1
  90. data/lib/generators/devise/orm_helpers.rb +17 -9
  91. data/lib/generators/devise/views_generator.rb +51 -28
  92. data/lib/generators/mongoid/devise_generator.rb +24 -24
  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 +118 -53
  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 +73 -294
  115. data/.gitignore +0 -10
  116. data/.travis.yml +0 -20
  117. data/.yardopts +0 -9
  118. data/CHANGELOG.rdoc +0 -941
  119. data/CONTRIBUTING.md +0 -14
  120. data/Gemfile +0 -31
  121. data/Gemfile.lock +0 -159
  122. data/Rakefile +0 -35
  123. data/app/views/devise/_links.erb +0 -3
  124. data/devise.gemspec +0 -26
  125. data/devise.png +0 -0
  126. data/gemfiles/Gemfile.rails-3.2.x +0 -31
  127. data/gemfiles/Gemfile.rails-3.2.x.lock +0 -156
  128. data/lib/devise/models/token_authenticatable.rb +0 -89
  129. data/lib/devise/strategies/token_authenticatable.rb +0 -91
  130. data/test/controllers/custom_strategy_test.rb +0 -62
  131. data/test/controllers/helpers_test.rb +0 -253
  132. data/test/controllers/internal_helpers_test.rb +0 -120
  133. data/test/controllers/passwords_controller_test.rb +0 -32
  134. data/test/controllers/sessions_controller_test.rb +0 -99
  135. data/test/controllers/url_helpers_test.rb +0 -59
  136. data/test/delegator_test.rb +0 -19
  137. data/test/devise_test.rb +0 -83
  138. data/test/failure_app_test.rb +0 -221
  139. data/test/generators/active_record_generator_test.rb +0 -73
  140. data/test/generators/devise_generator_test.rb +0 -39
  141. data/test/generators/install_generator_test.rb +0 -13
  142. data/test/generators/mongoid_generator_test.rb +0 -23
  143. data/test/generators/views_generator_test.rb +0 -67
  144. data/test/helpers/devise_helper_test.rb +0 -51
  145. data/test/integration/authenticatable_test.rb +0 -699
  146. data/test/integration/confirmable_test.rb +0 -299
  147. data/test/integration/database_authenticatable_test.rb +0 -84
  148. data/test/integration/http_authenticatable_test.rb +0 -115
  149. data/test/integration/lockable_test.rb +0 -242
  150. data/test/integration/omniauthable_test.rb +0 -133
  151. data/test/integration/recoverable_test.rb +0 -335
  152. data/test/integration/registerable_test.rb +0 -349
  153. data/test/integration/rememberable_test.rb +0 -165
  154. data/test/integration/timeoutable_test.rb +0 -150
  155. data/test/integration/token_authenticatable_test.rb +0 -205
  156. data/test/integration/trackable_test.rb +0 -92
  157. data/test/mailers/confirmation_instructions_test.rb +0 -111
  158. data/test/mailers/reset_password_instructions_test.rb +0 -92
  159. data/test/mailers/unlock_instructions_test.rb +0 -87
  160. data/test/mapping_test.rb +0 -127
  161. data/test/models/authenticatable_test.rb +0 -13
  162. data/test/models/confirmable_test.rb +0 -452
  163. data/test/models/database_authenticatable_test.rb +0 -226
  164. data/test/models/lockable_test.rb +0 -282
  165. data/test/models/omniauthable_test.rb +0 -7
  166. data/test/models/recoverable_test.rb +0 -222
  167. data/test/models/registerable_test.rb +0 -7
  168. data/test/models/rememberable_test.rb +0 -175
  169. data/test/models/serializable_test.rb +0 -49
  170. data/test/models/timeoutable_test.rb +0 -46
  171. data/test/models/token_authenticatable_test.rb +0 -55
  172. data/test/models/trackable_test.rb +0 -13
  173. data/test/models/validatable_test.rb +0 -127
  174. data/test/models_test.rb +0 -163
  175. data/test/omniauth/config_test.rb +0 -57
  176. data/test/omniauth/url_helpers_test.rb +0 -54
  177. data/test/orm/active_record.rb +0 -10
  178. data/test/orm/mongoid.rb +0 -13
  179. data/test/parameter_sanitizer_test.rb +0 -58
  180. data/test/rails_app/Rakefile +0 -6
  181. data/test/rails_app/app/active_record/admin.rb +0 -6
  182. data/test/rails_app/app/active_record/shim.rb +0 -2
  183. data/test/rails_app/app/active_record/user.rb +0 -6
  184. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  185. data/test/rails_app/app/controllers/admins_controller.rb +0 -11
  186. data/test/rails_app/app/controllers/application_controller.rb +0 -9
  187. data/test/rails_app/app/controllers/home_controller.rb +0 -25
  188. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  189. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  190. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  191. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  192. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  193. data/test/rails_app/app/mailers/users/mailer.rb +0 -12
  194. data/test/rails_app/app/mongoid/admin.rb +0 -29
  195. data/test/rails_app/app/mongoid/shim.rb +0 -23
  196. data/test/rails_app/app/mongoid/user.rb +0 -42
  197. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  198. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  199. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  200. data/test/rails_app/app/views/home/index.html.erb +0 -1
  201. data/test/rails_app/app/views/home/join.html.erb +0 -1
  202. data/test/rails_app/app/views/home/private.html.erb +0 -1
  203. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  204. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  205. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  206. data/test/rails_app/app/views/users/index.html.erb +0 -1
  207. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  208. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  209. data/test/rails_app/bin/bundle +0 -3
  210. data/test/rails_app/bin/rails +0 -4
  211. data/test/rails_app/bin/rake +0 -4
  212. data/test/rails_app/config/application.rb +0 -40
  213. data/test/rails_app/config/boot.rb +0 -8
  214. data/test/rails_app/config/database.yml +0 -18
  215. data/test/rails_app/config/environment.rb +0 -5
  216. data/test/rails_app/config/environments/development.rb +0 -34
  217. data/test/rails_app/config/environments/production.rb +0 -84
  218. data/test/rails_app/config/environments/test.rb +0 -36
  219. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  220. data/test/rails_app/config/initializers/devise.rb +0 -178
  221. data/test/rails_app/config/initializers/inflections.rb +0 -2
  222. data/test/rails_app/config/initializers/secret_token.rb +0 -8
  223. data/test/rails_app/config/initializers/session_store.rb +0 -1
  224. data/test/rails_app/config/routes.rb +0 -104
  225. data/test/rails_app/config.ru +0 -4
  226. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -74
  227. data/test/rails_app/db/schema.rb +0 -52
  228. data/test/rails_app/lib/shared_admin.rb +0 -14
  229. data/test/rails_app/lib/shared_user.rb +0 -25
  230. data/test/rails_app/public/404.html +0 -26
  231. data/test/rails_app/public/422.html +0 -26
  232. data/test/rails_app/public/500.html +0 -26
  233. data/test/rails_app/public/favicon.ico +0 -0
  234. data/test/routes_test.rb +0 -250
  235. data/test/support/assertions.rb +0 -40
  236. data/test/support/helpers.rb +0 -91
  237. data/test/support/integration.rb +0 -92
  238. data/test/support/locale/en.yml +0 -4
  239. data/test/support/webrat/integrations/rails.rb +0 -24
  240. data/test/test_helper.rb +0 -34
  241. data/test/test_helpers_test.rb +0 -151
  242. data/test/test_models.rb +0 -26
@@ -1,14 +1,84 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Controllers
3
5
  # Those helpers are convenience methods added to ApplicationController.
4
6
  module Helpers
5
7
  extend ActiveSupport::Concern
8
+ include Devise::Controllers::SignInOut
9
+ include Devise::Controllers::StoreLocation
6
10
 
7
11
  included do
8
- helper_method :warden, :signed_in?, :devise_controller?
12
+ if respond_to?(:helper_method)
13
+ helper_method :warden, :signed_in?, :devise_controller?
14
+ end
9
15
  end
10
16
 
11
17
  module ClassMethods
18
+ # Define authentication filters and accessor helpers for a group of mappings.
19
+ # These methods are useful when you are working with multiple mappings that
20
+ # share some functionality. They are pretty much the same as the ones
21
+ # defined for normal mappings.
22
+ #
23
+ # Example:
24
+ #
25
+ # inside BlogsController (or any other controller, it doesn't matter which):
26
+ # devise_group :blogger, contains: [:user, :admin]
27
+ #
28
+ # Generated methods:
29
+ # authenticate_blogger! # Redirects unless user or admin are signed in
30
+ # blogger_signed_in? # Checks whether there is either a user or an admin signed in
31
+ # current_blogger # Currently signed in user or admin
32
+ # current_bloggers # Currently signed in user and admin
33
+ #
34
+ # Use:
35
+ # before_action :authenticate_blogger! # Redirects unless either a user or an admin are authenticated
36
+ # before_action ->{ authenticate_blogger! :admin } # Redirects to the admin login page
37
+ # current_blogger :user # Preferably returns a User if one is signed in
38
+ #
39
+ def devise_group(group_name, opts = {})
40
+ mappings = "[#{ opts[:contains].map { |m| ":#{m}" }.join(',') }]"
41
+
42
+ class_eval <<-METHODS, __FILE__, __LINE__ + 1
43
+ def authenticate_#{group_name}!(favorite = nil, opts = {})
44
+ unless #{group_name}_signed_in?
45
+ mappings = #{mappings}
46
+ mappings.unshift mappings.delete(favorite.to_sym) if favorite
47
+ mappings.each do |mapping|
48
+ opts[:scope] = mapping
49
+ warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
50
+ end
51
+ end
52
+ end
53
+
54
+ def #{group_name}_signed_in?
55
+ #{mappings}.any? do |mapping|
56
+ warden.authenticate?(scope: mapping)
57
+ end
58
+ end
59
+
60
+ def current_#{group_name}(favorite = nil)
61
+ mappings = #{mappings}
62
+ mappings.unshift mappings.delete(favorite.to_sym) if favorite
63
+ mappings.each do |mapping|
64
+ current = warden.authenticate(scope: mapping)
65
+ return current if current
66
+ end
67
+ nil
68
+ end
69
+
70
+ def current_#{group_name.to_s.pluralize}
71
+ #{mappings}.map do |mapping|
72
+ warden.authenticate(scope: mapping)
73
+ end.compact
74
+ end
75
+
76
+ if respond_to?(:helper_method)
77
+ helper_method "current_#{group_name}", "current_#{group_name.to_s.pluralize}", "#{group_name}_signed_in?"
78
+ end
79
+ METHODS
80
+ end
81
+
12
82
  def log_process_action(payload)
13
83
  payload[:status] ||= 401 unless payload[:exception]
14
84
  super
@@ -16,7 +86,7 @@ module Devise
16
86
  end
17
87
 
18
88
  # Define authentication filters and accessor helpers based on mappings.
19
- # These filters should be used inside the controllers as before_filters,
89
+ # These filters should be used inside the controllers as before_actions,
20
90
  # so you can control the scope of the user who should be signed in to
21
91
  # access that specific controller/action.
22
92
  # Example:
@@ -36,14 +106,14 @@ module Devise
36
106
  # admin_session # Session data available only to the admin scope
37
107
  #
38
108
  # Use:
39
- # before_filter :authenticate_user! # Tell devise to use :user map
40
- # before_filter :authenticate_admin! # Tell devise to use :admin map
109
+ # before_action :authenticate_user! # Tell devise to use :user map
110
+ # before_action :authenticate_admin! # Tell devise to use :admin map
41
111
  #
42
112
  def self.define_helpers(mapping) #:nodoc:
43
113
  mapping = mapping.name
44
114
 
45
115
  class_eval <<-METHODS, __FILE__, __LINE__ + 1
46
- def authenticate_#{mapping}!(opts={})
116
+ def authenticate_#{mapping}!(opts = {})
47
117
  opts[:scope] = :#{mapping}
48
118
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
49
119
  end
@@ -53,7 +123,7 @@ module Devise
53
123
  end
54
124
 
55
125
  def current_#{mapping}
56
- @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
126
+ @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
57
127
  end
58
128
 
59
129
  def #{mapping}_session
@@ -62,33 +132,31 @@ module Devise
62
132
  METHODS
63
133
 
64
134
  ActiveSupport.on_load(:action_controller) do
65
- helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
135
+ if respond_to?(:helper_method)
136
+ helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
137
+ end
66
138
  end
67
139
  end
68
140
 
69
141
  # The main accessor for the warden proxy instance
70
142
  def warden
71
- request.env['warden']
143
+ request.env['warden'] or raise MissingWarden
72
144
  end
73
145
 
74
146
  # Return true if it's a devise_controller. false to all controllers unless
75
147
  # the controllers defined inside devise. Useful if you want to apply a before
76
148
  # filter to all controllers, except the ones in devise:
77
149
  #
78
- # before_filter :my_filter, :unless => :devise_controller?
150
+ # before_action :my_filter, unless: :devise_controller?
79
151
  def devise_controller?
80
- is_a?(DeviseController)
152
+ is_a?(::DeviseController)
81
153
  end
82
154
 
83
- # Setup a param sanitizer to filter parameters using strong_parameters. See
155
+ # Set up a param sanitizer to filter parameters using strong_parameters. See
84
156
  # lib/devise/parameter_sanitizer.rb for more info. Override this
85
157
  # method in your application controller to use your own parameter sanitizer.
86
158
  def devise_parameter_sanitizer
87
- @devise_parameter_sanitizer ||= if defined?(ActionController::StrongParameters)
88
- Devise::ParameterSanitizer.new(resource_class, resource_name, params)
89
- else
90
- Devise::BaseSanitizer.new(resource_class, resource_name, params)
91
- end
159
+ @devise_parameter_sanitizer ||= Devise::ParameterSanitizer.new(resource_class, resource_name, params)
92
160
  end
93
161
 
94
162
  # Tell warden that params authentication is allowed for that specific page.
@@ -96,107 +164,20 @@ module Devise
96
164
  request.env["devise.allow_params_authentication"] = true
97
165
  end
98
166
 
99
- # Return true if the given scope is signed in session. If no scope given, return
100
- # true if any scope is signed in. Does not run authentication hooks.
101
- def signed_in?(scope=nil)
102
- [ scope || Devise.mappings.keys ].flatten.any? do |_scope|
103
- warden.authenticate?(:scope => _scope)
104
- end
105
- end
106
-
107
- # Sign in a user that already was authenticated. This helper is useful for logging
108
- # users in after sign up.
109
- #
110
- # All options given to sign_in is passed forward to the set_user method in warden.
111
- # The only exception is the :bypass option, which bypass warden callbacks and stores
112
- # the user straight in session. This option is useful in cases the user is already
113
- # signed in, but we want to refresh the credentials in session.
114
- #
115
- # Examples:
116
- #
117
- # sign_in :user, @user # sign_in(scope, resource)
118
- # sign_in @user # sign_in(resource)
119
- # sign_in @user, :event => :authentication # sign_in(resource, options)
120
- # sign_in @user, :bypass => true # sign_in(resource, options)
121
- #
122
- def sign_in(resource_or_scope, *args)
123
- options = args.extract_options!
124
- scope = Devise::Mapping.find_scope!(resource_or_scope)
125
- resource = args.last || resource_or_scope
126
-
127
- expire_session_data_after_sign_in!
128
-
129
- if options[:bypass]
130
- warden.session_serializer.store(resource, scope)
131
- elsif warden.user(scope) == resource && !options.delete(:force)
132
- # Do nothing. User already signed in and we are not forcing it.
133
- true
134
- else
135
- warden.set_user(resource, options.merge!(:scope => scope))
136
- end
137
- end
138
-
139
- # Sign out a given user or scope. This helper is useful for signing out a user
140
- # after deleting accounts. Returns true if there was a logout and false if there
141
- # is no user logged in on the referred scope
142
- #
143
- # Examples:
144
- #
145
- # sign_out :user # sign_out(scope)
146
- # sign_out @user # sign_out(resource)
147
- #
148
- def sign_out(resource_or_scope=nil)
149
- return sign_out_all_scopes unless resource_or_scope
150
- scope = Devise::Mapping.find_scope!(resource_or_scope)
151
- user = warden.user(:scope => scope, :run_callbacks => false) # If there is no user
152
-
153
- warden.raw_session.inspect # Without this inspect here. The session does not clear.
154
- warden.logout(scope)
155
- warden.clear_strategies_cache!(:scope => scope)
156
- instance_variable_set(:"@current_#{scope}", nil)
157
-
158
- !!user
159
- end
160
-
161
- # Sign out all active users or scopes. This helper is useful for signing out all roles
162
- # in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
163
- # and false if there was no user logged in on all scopes.
164
- def sign_out_all_scopes(lock=true)
165
- users = Devise.mappings.keys.map { |s| warden.user(:scope => s, :run_callbacks => false) }
166
-
167
- warden.raw_session.inspect
168
- warden.logout
169
- expire_devise_cached_variables!
170
- warden.clear_strategies_cache!
171
- warden.lock! if lock
172
-
173
- users.any?
174
- end
175
-
176
- # Returns and delete (if it's navigational format) the url stored in the session for
177
- # the given scope. Useful for giving redirect backs after sign up:
178
- #
179
- # Example:
180
- #
181
- # redirect_to stored_location_for(:user) || root_path
182
- #
183
- def stored_location_for(resource_or_scope)
184
- scope = Devise::Mapping.find_scope!(resource_or_scope)
185
-
186
- if is_navigational_format?
187
- session.delete("#{scope}_return_to")
188
- else
189
- session["#{scope}_return_to"]
190
- end
191
- end
192
-
193
- # The scope root url to be used when he's signed in. By default, it first
167
+ # The scope root url to be used when they're signed in. By default, it first
194
168
  # tries to find a resource_root_path, otherwise it uses the root_path.
195
169
  def signed_in_root_path(resource_or_scope)
196
170
  scope = Devise::Mapping.find_scope!(resource_or_scope)
171
+ router_name = Devise.mappings[scope].router_name
172
+
197
173
  home_path = "#{scope}_root_path"
198
- if respond_to?(home_path, true)
199
- send(home_path)
174
+
175
+ context = router_name ? send(router_name) : self
176
+
177
+ if context.respond_to?(home_path, true)
178
+ context.send(home_path)
179
+ elsif context.respond_to?(:root_path)
180
+ context.root_path
200
181
  elsif respond_to?(:root_path)
201
182
  root_path
202
183
  else
@@ -213,10 +194,10 @@ module Devise
213
194
  # root path. For a user scope, you can define the default url in
214
195
  # the following way:
215
196
  #
216
- # map.user_root '/users', :controller => 'users' # creates user_root_path
197
+ # get '/users' => 'users#index', as: :user_root # creates user_root_path
217
198
  #
218
- # map.namespace :user do |user|
219
- # user.root :controller => 'users' # creates user_root_path
199
+ # namespace :user do
200
+ # root 'users#index' # creates user_root_path
220
201
  # end
221
202
  #
222
203
  # If the resource root path is not defined, root_path is used. However,
@@ -242,7 +223,10 @@ module Devise
242
223
  #
243
224
  # By default it is the root_path.
244
225
  def after_sign_out_path_for(resource_or_scope)
245
- respond_to?(:root_path) ? root_path : "/"
226
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
227
+ router_name = Devise.mappings[scope].router_name
228
+ context = router_name ? send(router_name) : self
229
+ context.respond_to?(:root_path) ? context.root_path : "/"
246
230
  end
247
231
 
248
232
  # Sign in a user and tries to redirect first to the stored location and
@@ -256,10 +240,6 @@ module Devise
256
240
  redirect_to after_sign_in_path_for(resource)
257
241
  end
258
242
 
259
- def expire_session_data_after_sign_in!
260
- session.keys.grep(/^devise\./).each { |k| session.delete(k) }
261
- end
262
-
263
243
  # Sign out a user and tries to redirect to the url specified by
264
244
  # after_sign_out_path_for.
265
245
  def sign_out_and_redirect(resource_or_scope)
@@ -272,10 +252,9 @@ module Devise
272
252
  # Overwrite Rails' handle unverified request to sign out all scopes,
273
253
  # clear run strategies and remove cached variables.
274
254
  def handle_unverified_request
275
- sign_out_all_scopes(false)
255
+ super # call the default behavior which resets/nullifies/raises
276
256
  request.env["devise.skip_storage"] = true
277
- expire_devise_cached_variables!
278
- super # call the default behaviour which resets the session
257
+ sign_out_all_scopes(false)
279
258
  end
280
259
 
281
260
  def request_format
@@ -286,11 +265,29 @@ module Devise
286
265
  Devise.navigational_formats.include?(request_format)
287
266
  end
288
267
 
268
+ # Check if flash messages should be emitted. Default is to do it on
269
+ # navigational formats
270
+ def is_flashing_format?
271
+ request.respond_to?(:flash) && is_navigational_format?
272
+ end
273
+
289
274
  private
290
275
 
291
- def expire_devise_cached_variables!
276
+ def expire_data_after_sign_out!
292
277
  Devise.mappings.each { |_,m| instance_variable_set("@current_#{m.name}", nil) }
278
+ super
293
279
  end
294
280
  end
295
281
  end
282
+
283
+ class MissingWarden < StandardError
284
+ def initialize
285
+ super "Devise could not find the `Warden::Proxy` instance on your request environment.\n" + \
286
+ "Make sure that your application is loading Devise and Warden as expected and that " + \
287
+ "the `Warden::Manager` middleware is present in your middleware stack.\n" + \
288
+ "If you are seeing this on one of your tests, ensure that your tests are either " + \
289
+ "executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` " + \
290
+ "module to inject the `request.env['warden']` object for you."
291
+ end
292
+ end
296
293
  end
@@ -1,28 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Controllers
3
5
  # A module that may be optionally included in a controller in order
4
- # to provide remember me behavior.
6
+ # to provide remember me behavior. Useful when signing in is done
7
+ # through a callback, like in OmniAuth.
5
8
  module Rememberable
6
9
  # Return default cookie values retrieved from session options.
7
10
  def self.cookie_values
8
11
  Rails.configuration.session_options.slice(:path, :domain, :secure)
9
12
  end
10
13
 
11
- # A small warden proxy so we can remember and forget uses from hooks.
12
- class Proxy #:nodoc:
13
- include Devise::Controllers::Rememberable
14
-
15
- delegate :cookies, :env, :to => :@warden
16
-
17
- def initialize(warden)
18
- @warden = warden
19
- end
14
+ def remember_me_is_active?(resource)
15
+ return false unless resource.respond_to?(:remember_me)
16
+ scope = Devise::Mapping.find_scope!(resource)
17
+ _, token, generated_at = cookies.signed[remember_key(resource, scope)]
18
+ resource.remember_me?(token, generated_at)
20
19
  end
21
20
 
22
21
  # Remembers the given resource by setting up a cookie
23
22
  def remember_me(resource)
23
+ return if request.env["devise.skip_storage"]
24
24
  scope = Devise::Mapping.find_scope!(resource)
25
- resource.remember_me!(resource.extend_remember_period)
25
+ resource.remember_me!
26
26
  cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)
27
27
  end
28
28
 
@@ -40,11 +40,11 @@ module Devise
40
40
  end
41
41
 
42
42
  def remember_cookie_values(resource)
43
- options = { :httponly => true }
43
+ options = { httponly: true }
44
44
  options.merge!(forget_cookie_values(resource))
45
45
  options.merge!(
46
- :value => resource.class.serialize_into_cookie(resource),
47
- :expires => resource.remember_expires_at
46
+ value: resource.class.serialize_into_cookie(resource),
47
+ expires: resource.remember_expires_at
48
48
  )
49
49
  end
50
50
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Controllers
3
5
  module ScopedViews
@@ -14,4 +16,4 @@ module Devise
14
16
  end
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Controllers
5
+ # Provide sign in and sign out functionality.
6
+ # Included by default in all controllers.
7
+ module SignInOut
8
+ # Return true if the given scope is signed in session. If no scope given, return
9
+ # true if any scope is signed in. This will run authentication hooks, which may
10
+ # cause exceptions to be thrown from this method; if you simply want to check
11
+ # if a scope has already previously been authenticated without running
12
+ # authentication hooks, you can directly call `warden.authenticated?(scope: scope)`
13
+ def signed_in?(scope = nil)
14
+ [scope || Devise.mappings.keys].flatten.any? do |_scope|
15
+ warden.authenticate?(scope: _scope)
16
+ end
17
+ end
18
+
19
+ # Sign in a user that already was authenticated. This helper is useful for logging
20
+ # users in after sign up. All options given to sign_in is passed forward
21
+ # to the set_user method in warden.
22
+ # If you are using a custom warden strategy and the timeoutable module, you have to
23
+ # set `env["devise.skip_timeout"] = true` in the request to use this method, like we do
24
+ # in the sessions controller: https://github.com/heartcombo/devise/blob/master/app/controllers/devise/sessions_controller.rb#L7
25
+ #
26
+ # Examples:
27
+ #
28
+ # sign_in :user, @user # sign_in(scope, resource)
29
+ # sign_in @user # sign_in(resource)
30
+ # sign_in @user, event: :authentication # sign_in(resource, options)
31
+ # sign_in @user, store: false # sign_in(resource, options)
32
+ #
33
+ def sign_in(resource_or_scope, *args)
34
+ options = args.extract_options!
35
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
36
+ resource = args.last || resource_or_scope
37
+
38
+ expire_data_after_sign_in!
39
+
40
+ if options[:bypass]
41
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
42
+ [Devise] bypass option is deprecated and it will be removed in future version of Devise.
43
+ Please use bypass_sign_in method instead.
44
+ Example:
45
+
46
+ bypass_sign_in(user)
47
+ DEPRECATION
48
+ warden.session_serializer.store(resource, scope)
49
+ elsif warden.user(scope) == resource && !options.delete(:force)
50
+ # Do nothing. User already signed in and we are not forcing it.
51
+ true
52
+ else
53
+ warden.set_user(resource, options.merge!(scope: scope))
54
+ end
55
+ end
56
+
57
+ # Sign in a user bypassing the warden callbacks and stores the user
58
+ # straight in session. This option is useful in cases the user is already
59
+ # signed in, but we want to refresh the credentials in session.
60
+ #
61
+ # Examples:
62
+ #
63
+ # bypass_sign_in @user, scope: :user
64
+ # bypass_sign_in @user
65
+ def bypass_sign_in(resource, scope: nil)
66
+ scope ||= Devise::Mapping.find_scope!(resource)
67
+ expire_data_after_sign_in!
68
+ warden.session_serializer.store(resource, scope)
69
+ end
70
+
71
+ # Sign out a given user or scope. This helper is useful for signing out a user
72
+ # after deleting accounts. Returns true if there was a logout and false if there
73
+ # is no user logged in on the referred scope
74
+ #
75
+ # Examples:
76
+ #
77
+ # sign_out :user # sign_out(scope)
78
+ # sign_out @user # sign_out(resource)
79
+ #
80
+ def sign_out(resource_or_scope = nil)
81
+ return sign_out_all_scopes unless resource_or_scope
82
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
83
+ user = warden.user(scope: scope, run_callbacks: false) # If there is no user
84
+
85
+ warden.logout(scope)
86
+ warden.clear_strategies_cache!(scope: scope)
87
+ instance_variable_set(:"@current_#{scope}", nil)
88
+
89
+ !!user
90
+ end
91
+
92
+ # Sign out all active users or scopes. This helper is useful for signing out all roles
93
+ # in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
94
+ # and false if there was no user logged in on all scopes.
95
+ def sign_out_all_scopes(lock = true)
96
+ users = Devise.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }
97
+
98
+ warden.logout
99
+ expire_data_after_sign_out!
100
+ warden.clear_strategies_cache!
101
+ warden.lock! if lock
102
+
103
+ users.any?
104
+ end
105
+
106
+ private
107
+
108
+ def expire_data_after_sign_in!
109
+ # TODO: remove once Rails 5.2+ and forward are only supported.
110
+ # session.keys will return an empty array if the session is not yet loaded.
111
+ # This is a bug in both Rack and Rails.
112
+ # A call to #empty? forces the session to be loaded.
113
+ session.empty?
114
+
115
+ session.keys.grep(/^devise\./).each { |k| session.delete(k) }
116
+ end
117
+
118
+ alias :expire_data_after_sign_out! :expire_data_after_sign_in!
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Devise
6
+ module Controllers
7
+ # Provide the ability to store a location.
8
+ # Used to redirect back to a desired path after sign in.
9
+ # Included by default in all controllers.
10
+ module StoreLocation
11
+ # Returns and delete (if it's navigational format) the url stored in the session for
12
+ # the given scope. Useful for giving redirect backs after sign up:
13
+ #
14
+ # Example:
15
+ #
16
+ # redirect_to stored_location_for(:user) || root_path
17
+ #
18
+ def stored_location_for(resource_or_scope)
19
+ session_key = stored_location_key_for(resource_or_scope)
20
+
21
+ if is_navigational_format?
22
+ session.delete(session_key)
23
+ else
24
+ session[session_key]
25
+ end
26
+ end
27
+
28
+ # Stores the provided location to redirect the user after signing in.
29
+ # Useful in combination with the `stored_location_for` helper.
30
+ #
31
+ # Example:
32
+ #
33
+ # store_location_for(:user, dashboard_path)
34
+ # redirect_to user_facebook_omniauth_authorize_path
35
+ #
36
+ def store_location_for(resource_or_scope, location)
37
+ session_key = stored_location_key_for(resource_or_scope)
38
+
39
+ path = extract_path_from_location(location)
40
+ session[session_key] = path if path
41
+ end
42
+
43
+ private
44
+
45
+ def parse_uri(location)
46
+ location && URI.parse(location)
47
+ rescue URI::InvalidURIError
48
+ nil
49
+ end
50
+
51
+ def stored_location_key_for(resource_or_scope)
52
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
53
+ "#{scope}_return_to"
54
+ end
55
+
56
+ def extract_path_from_location(location)
57
+ uri = parse_uri(location)
58
+
59
+ if uri
60
+ path = remove_domain_from_uri(uri)
61
+ path = add_fragment_back_to_path(uri, path)
62
+
63
+ path
64
+ end
65
+ end
66
+
67
+ def remove_domain_from_uri(uri)
68
+ [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
69
+ end
70
+
71
+ def add_fragment_back_to_path(uri, path)
72
+ [path, uri.fragment].compact.join('#')
73
+ end
74
+ end
75
+ end
76
+ end
@@ -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
@@ -32,7 +34,7 @@ module Devise
32
34
  end
33
35
  end
34
36
 
35
- def self.generate_helpers!(routes=nil)
37
+ def self.generate_helpers!(routes = nil)
36
38
  routes ||= begin
37
39
  mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
38
40
  Devise::URL_HELPERS.slice(*mappings)
@@ -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