devise 1.1.9 → 1.2.rc

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 (121) hide show
  1. data/CHANGELOG.rdoc +34 -26
  2. data/README.rdoc +134 -100
  3. data/app/controllers/devise/confirmations_controller.rb +1 -1
  4. data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
  5. data/app/controllers/devise/passwords_controller.rb +1 -1
  6. data/app/controllers/devise/registrations_controller.rb +59 -6
  7. data/app/controllers/devise/sessions_controller.rb +3 -2
  8. data/app/controllers/devise/unlocks_controller.rb +1 -1
  9. data/app/helpers/devise_helper.rb +4 -2
  10. data/app/mailers/devise/mailer.rb +27 -10
  11. data/app/views/devise/confirmations/new.html.erb +1 -1
  12. data/app/views/devise/passwords/edit.html.erb +2 -2
  13. data/app/views/devise/passwords/new.html.erb +1 -1
  14. data/app/views/devise/registrations/edit.html.erb +1 -1
  15. data/app/views/devise/registrations/new.html.erb +1 -1
  16. data/app/views/devise/sessions/new.html.erb +1 -1
  17. data/app/views/devise/shared/_links.erb +6 -0
  18. data/app/views/devise/unlocks/new.html.erb +1 -1
  19. data/config/locales/en.yml +9 -2
  20. data/lib/devise.rb +116 -58
  21. data/lib/devise/controllers/helpers.rb +103 -107
  22. data/lib/devise/controllers/internal_helpers.rb +23 -7
  23. data/lib/devise/controllers/scoped_views.rb +4 -6
  24. data/lib/devise/controllers/url_helpers.rb +3 -5
  25. data/lib/devise/encryptors/base.rb +1 -1
  26. data/lib/devise/encryptors/restful_authentication_sha1.rb +4 -4
  27. data/lib/devise/failure_app.rb +29 -21
  28. data/lib/devise/hooks/forgetable.rb +2 -1
  29. data/lib/devise/hooks/rememberable.rb +11 -9
  30. data/lib/devise/mapping.rb +12 -5
  31. data/lib/devise/models.rb +0 -14
  32. data/lib/devise/models/authenticatable.rb +40 -30
  33. data/lib/devise/models/confirmable.rb +11 -15
  34. data/lib/devise/models/database_authenticatable.rb +23 -35
  35. data/lib/devise/models/encryptable.rb +65 -0
  36. data/lib/devise/models/lockable.rb +8 -7
  37. data/lib/devise/models/omniauthable.rb +23 -0
  38. data/lib/devise/models/recoverable.rb +5 -3
  39. data/lib/devise/models/registerable.rb +13 -0
  40. data/lib/devise/models/rememberable.rb +38 -30
  41. data/lib/devise/models/timeoutable.rb +20 -3
  42. data/lib/devise/models/token_authenticatable.rb +19 -7
  43. data/lib/devise/models/validatable.rb +16 -4
  44. data/lib/devise/modules.rb +15 -8
  45. data/lib/devise/omniauth.rb +47 -0
  46. data/lib/devise/omniauth/config.rb +30 -0
  47. data/lib/devise/omniauth/test_helpers.rb +57 -0
  48. data/lib/devise/omniauth/url_helpers.rb +29 -0
  49. data/lib/devise/orm/active_record.rb +2 -0
  50. data/lib/devise/orm/mongoid.rb +4 -2
  51. data/lib/devise/rails.rb +26 -46
  52. data/lib/devise/rails/routes.rb +64 -20
  53. data/lib/devise/rails/warden_compat.rb +18 -20
  54. data/lib/devise/schema.rb +13 -14
  55. data/lib/devise/strategies/authenticatable.rb +33 -7
  56. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  57. data/lib/devise/strategies/rememberable.rb +1 -1
  58. data/lib/devise/strategies/token_authenticatable.rb +6 -2
  59. data/lib/devise/test_helpers.rb +11 -1
  60. data/lib/devise/version.rb +1 -1
  61. data/lib/generators/active_record/templates/migration.rb +1 -0
  62. data/lib/generators/devise/orm_helpers.rb +3 -2
  63. data/lib/generators/templates/devise.rb +70 -39
  64. data/test/controllers/helpers_test.rb +43 -67
  65. data/test/controllers/internal_helpers_test.rb +29 -8
  66. data/test/controllers/url_helpers_test.rb +2 -1
  67. data/test/failure_app_test.rb +56 -21
  68. data/test/generators/generators_test_helper.rb +4 -0
  69. data/test/generators/install_generator_test.rb +14 -0
  70. data/test/generators/views_generator_test.rb +37 -0
  71. data/test/integration/authenticatable_test.rb +147 -62
  72. data/test/integration/database_authenticatable_test.rb +22 -0
  73. data/test/integration/http_authenticatable_test.rb +12 -2
  74. data/test/integration/omniauthable_test.rb +107 -0
  75. data/test/integration/recoverable_test.rb +39 -20
  76. data/test/integration/registerable_test.rb +30 -4
  77. data/test/integration/rememberable_test.rb +57 -34
  78. data/test/integration/timeoutable_test.rb +10 -1
  79. data/test/integration/token_authenticatable_test.rb +12 -17
  80. data/test/mailers/confirmation_instructions_test.rb +4 -0
  81. data/test/mailers/reset_password_instructions_test.rb +4 -0
  82. data/test/mailers/unlock_instructions_test.rb +4 -0
  83. data/test/mapping_test.rb +37 -3
  84. data/test/models/confirmable_test.rb +3 -3
  85. data/test/models/database_authenticatable_test.rb +14 -71
  86. data/test/models/encryptable_test.rb +65 -0
  87. data/test/models/lockable_test.rb +17 -1
  88. data/test/models/recoverable_test.rb +17 -0
  89. data/test/models/rememberable_test.rb +186 -125
  90. data/test/models/token_authenticatable_test.rb +1 -13
  91. data/test/models_test.rb +5 -5
  92. data/test/omniauth/url_helpers_test.rb +47 -0
  93. data/test/rails_app/app/active_record/admin.rb +4 -1
  94. data/test/rails_app/app/active_record/user.rb +5 -4
  95. data/test/rails_app/app/controllers/{sessions_controller.rb → admins/sessions_controller.rb} +1 -1
  96. data/test/rails_app/app/controllers/home_controller.rb +9 -0
  97. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +7 -0
  98. data/test/rails_app/app/mongoid/admin.rb +4 -1
  99. data/test/rails_app/app/mongoid/shim.rb +16 -3
  100. data/test/rails_app/app/mongoid/user.rb +5 -5
  101. data/test/rails_app/config/initializers/devise.rb +52 -28
  102. data/test/rails_app/config/routes.rb +14 -6
  103. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +21 -17
  104. data/test/rails_app/db/schema.rb +17 -51
  105. data/test/rails_app/lib/shared_admin.rb +9 -0
  106. data/test/rails_app/lib/shared_user.rb +23 -0
  107. data/test/routes_test.rb +42 -9
  108. data/test/support/integration.rb +3 -3
  109. data/test/support/webrat/integrations/rails.rb +7 -0
  110. data/test/test_helper.rb +2 -0
  111. data/test/test_helpers_test.rb +29 -0
  112. metadata +60 -30
  113. data/Gemfile +0 -27
  114. data/Gemfile.lock +0 -115
  115. data/Rakefile +0 -55
  116. data/TODO +0 -3
  117. data/lib/devise/encryptors/bcrypt.rb +0 -19
  118. data/lib/generators/devise_install_generator.rb +0 -4
  119. data/lib/generators/devise_views_generator.rb +0 -4
  120. data/test/indifferent_hash.rb +0 -33
  121. data/test/support/test_silencer.rb +0 -5
@@ -5,8 +5,57 @@ module Devise
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- helper_method :warden, :signed_in?, :devise_controller?, :anybody_signed_in?,
9
- *Devise.mappings.keys.map { |m| [:"current_#{m}", :"#{m}_signed_in?", :"#{m}_session"] }.flatten
8
+ helper_method :warden, :signed_in?, :devise_controller?, :anybody_signed_in?
9
+ end
10
+
11
+ # Define authentication filters and accessor helpers based on mappings.
12
+ # These filters should be used inside the controllers as before_filters,
13
+ # so you can control the scope of the user who should be signed in to
14
+ # access that specific controller/action.
15
+ # Example:
16
+ #
17
+ # Roles:
18
+ # User
19
+ # Admin
20
+ #
21
+ # Generated methods:
22
+ # authenticate_user! # Signs user in or redirect
23
+ # authenticate_admin! # Signs admin in or redirect
24
+ # user_signed_in? # Checks whether there is an user signed in or not
25
+ # admin_signed_in? # Checks whether there is an admin signed in or not
26
+ # current_user # Current signed in user
27
+ # current_admin # Current signed in admin
28
+ # user_session # Session data available only to the user scope
29
+ # admin_session # Session data available only to the admin scope
30
+ #
31
+ # Use:
32
+ # before_filter :authenticate_user! # Tell devise to use :user map
33
+ # before_filter :authenticate_admin! # Tell devise to use :admin map
34
+ #
35
+ def self.define_helpers(mapping) #:nodoc:
36
+ mapping = mapping.name
37
+
38
+ class_eval <<-METHODS, __FILE__, __LINE__ + 1
39
+ def authenticate_#{mapping}!
40
+ warden.authenticate!(:scope => :#{mapping})
41
+ end
42
+
43
+ def #{mapping}_signed_in?
44
+ !!current_#{mapping}
45
+ end
46
+
47
+ def current_#{mapping}
48
+ @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
49
+ end
50
+
51
+ def #{mapping}_session
52
+ current_#{mapping} && warden.session(:#{mapping})
53
+ end
54
+ METHODS
55
+
56
+ ActiveSupport.on_load(:action_controller) do
57
+ helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
58
+ end
10
59
  end
11
60
 
12
61
  # The main accessor for the warden proxy instance
@@ -16,7 +65,7 @@ module Devise
16
65
 
17
66
  # Return true if it's a devise_controller. false to all controllers unless
18
67
  # the controllers defined inside devise. Useful if you want to apply a before
19
- # filter to all controller, except the ones in devise:
68
+ # filter to all controllers, except the ones in devise:
20
69
  #
21
70
  # before_filter :my_filter, :unless => { |c| c.devise_controller? }
22
71
  def devise_controller?
@@ -38,15 +87,30 @@ module Devise
38
87
  # Sign in an user that already was authenticated. This helper is useful for logging
39
88
  # users in after sign up.
40
89
  #
41
- # Examples:
90
+ # All options given to sign_in is passed forward to the set_user method in warden.
91
+ # The only exception is the :bypass option, which bypass warden callbacks and stores
92
+ # the user straight in session. This option is useful in cases the user is already
93
+ # signed in, but we want to refresh the credentials in session.
42
94
  #
43
- # sign_in :user, @user # sign_in(scope, resource)
44
- # sign_in @user # sign_in(resource)
95
+ # Examples:
45
96
  #
46
- def sign_in(resource_or_scope, resource=nil)
47
- scope = Devise::Mapping.find_scope!(resource_or_scope)
48
- resource ||= resource_or_scope
49
- warden.set_user(resource, :scope => scope)
97
+ # sign_in :user, @user # sign_in(scope, resource)
98
+ # sign_in @user # sign_in(resource)
99
+ # sign_in @user, :event => :authentication # sign_in(resource, options)
100
+ # sign_in @user, :bypass => true # sign_in(resource, options)
101
+ #
102
+ def sign_in(resource_or_scope, *args)
103
+ options = args.extract_options!
104
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
105
+ resource = args.last || resource_or_scope
106
+
107
+ expire_session_data_after_sign_in!
108
+
109
+ if options[:bypass]
110
+ warden.session_serializer.store(resource, scope)
111
+ else
112
+ warden.set_user(resource, options.merge!(:scope => scope))
113
+ end
50
114
  end
51
115
 
52
116
  # Sign out a given user or scope. This helper is useful for signing out an user
@@ -57,7 +121,8 @@ module Devise
57
121
  # sign_out :user # sign_out(scope)
58
122
  # sign_out @user # sign_out(resource)
59
123
  #
60
- def sign_out(resource_or_scope)
124
+ def sign_out(resource_or_scope=nil)
125
+ return sign_out_all_scopes unless resource_or_scope
61
126
  scope = Devise::Mapping.find_scope!(resource_or_scope)
62
127
  warden.user(scope) # Without loading user here, before_logout hook is not called
63
128
  warden.raw_session.inspect # Without this inspect here. The session does not clear.
@@ -65,13 +130,10 @@ module Devise
65
130
  end
66
131
 
67
132
  # Sign out all active users or scopes. This helper is useful for signing out all roles
68
- # in one click.
133
+ # in one click. This signs out ALL scopes in warden.
69
134
  def sign_out_all_scopes
70
- # Not "warden.logout" since we need to sign_out only devise-defined scopes.
71
- scopes = Devise.mappings.keys
72
- scopes.each { |scope| warden.user(scope) }
73
135
  warden.raw_session.inspect
74
- warden.logout(*scopes)
136
+ warden.logout
75
137
  end
76
138
 
77
139
  # Returns and delete the url stored in the session for the given scope. Useful
@@ -118,36 +180,6 @@ module Devise
118
180
  respond_to?(home_path, true) ? send(home_path) : root_path
119
181
  end
120
182
 
121
- # The default url to be used after updating a resource. This is used by all Devise
122
- # controllers and you can overwrite it in your ApplicationController to
123
- # provide a custom hook for a custom resource.
124
- #
125
- # By default, it first tries to find a resource_root_path, otherwise it
126
- # uses the root path. For a user scope, you can define the default url in
127
- # the following way:
128
- #
129
- # map.user_root '/users', :controller => 'users' # creates user_root_path
130
- #
131
- # map.resources :users do |users|
132
- # users.root # creates user_root_path
133
- # end
134
- #
135
- #
136
- # If none of these are defined, root_path is used. However, if this default
137
- # is not enough, you can customize it, for example:
138
- #
139
- # def after_update_path_for(resource)
140
- # if resource.is_a?(User) && resource.can_publish?
141
- # publisher_url
142
- # else
143
- # super
144
- # end
145
- # end
146
- #
147
- def after_update_path_for(resource_or_scope)
148
- after_sign_in_path_for(resource_or_scope)
149
- end
150
-
151
183
  # Method used by sessions controller to sign out an user. You can overwrite
152
184
  # it in your ApplicationController to provide a custom hook for a custom
153
185
  # scope. Notice that differently from +after_sign_in_path_for+ this method
@@ -159,14 +191,23 @@ module Devise
159
191
  end
160
192
 
161
193
  # Sign in an user and tries to redirect first to the stored location and
162
- # then to the url specified by after_sign_in_path_for.
163
- #
164
- # If just a symbol is given, consider that the user was already signed in
165
- # through other means and just perform the redirection.
166
- def sign_in_and_redirect(resource_or_scope, resource=nil)
167
- scope = Devise::Mapping.find_scope!(resource_or_scope)
168
- resource ||= resource_or_scope
169
- sign_in(scope, resource) unless warden.user(scope) == resource
194
+ # then to the url specified by after_sign_in_path_for. It accepts the same
195
+ # parameters as the sign_in method.
196
+ def sign_in_and_redirect(resource_or_scope, *args)
197
+ options = args.extract_options!
198
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
199
+ resource = args.last || resource_or_scope
200
+
201
+ if warden.user(scope) == resource
202
+ expire_session_data_after_sign_in!
203
+ else
204
+ sign_in(scope, resource, options)
205
+ end
206
+
207
+ redirect_for_sign_in(scope, resource)
208
+ end
209
+
210
+ def redirect_for_sign_in(scope, resource) #:nodoc:
170
211
  redirect_to stored_location_for(scope) || after_sign_in_path_for(resource)
171
212
  end
172
213
 
@@ -174,64 +215,19 @@ module Devise
174
215
  # after_sign_out_path_for.
175
216
  def sign_out_and_redirect(resource_or_scope)
176
217
  scope = Devise::Mapping.find_scope!(resource_or_scope)
177
- if Devise.sign_out_all_scopes
178
- sign_out_all_scopes
179
- else
180
- sign_out(scope)
181
- end
182
- redirect_to after_sign_out_path_for(scope)
218
+ Devise.sign_out_all_scopes ? sign_out : sign_out(scope)
219
+ redirect_for_sign_out(scope)
183
220
  end
184
221
 
185
- # Override Rails' handle unverified request to sign out all scopes.
186
- def handle_unverified_request
187
- sign_out_all_scopes
188
- super # call the default behaviour which resets the session
222
+ def redirect_for_sign_out(scope) #:nodoc:
223
+ redirect_to after_sign_out_path_for(scope)
189
224
  end
190
225
 
191
- # Define authentication filters and accessor helpers based on mappings.
192
- # These filters should be used inside the controllers as before_filters,
193
- # so you can control the scope of the user who should be signed in to
194
- # access that specific controller/action.
195
- # Example:
196
- #
197
- # Roles:
198
- # User
199
- # Admin
200
- #
201
- # Generated methods:
202
- # authenticate_user! # Signs user in or redirect
203
- # authenticate_admin! # Signs admin in or redirect
204
- # user_signed_in? # Checks whether there is an user signed in or not
205
- # admin_signed_in? # Checks whether there is an admin signed in or not
206
- # current_user # Current signed in user
207
- # current_admin # Currend signed in admin
208
- # user_session # Session data available only to the user scope
209
- # admin_session # Session data available only to the admin scope
210
- #
211
- # Use:
212
- # before_filter :authenticate_user! # Tell devise to use :user map
213
- # before_filter :authenticate_admin! # Tell devise to use :admin map
214
- #
215
- Devise.mappings.each_key do |mapping|
216
- class_eval <<-METHODS, __FILE__, __LINE__ + 1
217
- def authenticate_#{mapping}!
218
- warden.authenticate!(:scope => :#{mapping})
219
- end
220
-
221
- def #{mapping}_signed_in?
222
- warden.authenticate?(:scope => :#{mapping})
223
- end
224
-
225
- def current_#{mapping}
226
- @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
227
- end
228
-
229
- def #{mapping}_session
230
- current_#{mapping} && warden.session(:#{mapping})
231
- end
232
- METHODS
226
+ # A hook called to expire session data after sign up/in. All keys
227
+ # stored under "devise." namespace are removed after sign in.
228
+ def expire_session_data_after_sign_in!
229
+ session.keys.grep(/^devise\./).each { |k| session.delete(k) }
233
230
  end
234
-
235
231
  end
236
232
  end
237
233
  end
@@ -10,7 +10,7 @@ module Devise
10
10
  included do
11
11
  helper DeviseHelper
12
12
 
13
- helpers = %w(resource scope_name resource_name
13
+ helpers = %w(resource scope_name resource_name signed_in_resource
14
14
  resource_class devise_mapping devise_controller?)
15
15
  hide_action *helpers
16
16
  helper_method *helpers
@@ -35,6 +35,11 @@ module Devise
35
35
  devise_mapping.to
36
36
  end
37
37
 
38
+ # Returns a signed in resource from session (if one exists)
39
+ def signed_in_resource
40
+ warden.authenticate(:scope => resource_name)
41
+ end
42
+
38
43
  # Attempt to find the mapped route for devise based on request path
39
44
  def devise_mapping
40
45
  @devise_mapping ||= request.env["devise.mapping"]
@@ -49,7 +54,12 @@ module Devise
49
54
 
50
55
  # Checks whether it's a devise mapped resource or not.
51
56
  def is_devise_resource? #:nodoc:
52
- raise ActionController::UnknownAction unless devise_mapping
57
+ unknown_action!("Could not find devise mapping for path #{request.fullpath.inspect}") unless devise_mapping
58
+ end
59
+
60
+ def unknown_action!(msg)
61
+ logger.debug "[Devise] #{msg}" if logger
62
+ raise ActionController::UnknownAction, msg
53
63
  end
54
64
 
55
65
  # Sets the resource creating an instance variable
@@ -68,7 +78,10 @@ module Devise
68
78
  # Example:
69
79
  # before_filter :require_no_authentication, :only => :new
70
80
  def require_no_authentication
71
- redirect_to after_sign_in_path_for(resource_name) if warden.authenticated?(resource_name)
81
+ if warden.authenticated?(resource_name)
82
+ resource = warden.user(resource_name)
83
+ redirect_to after_sign_in_path_for(resource)
84
+ end
72
85
  end
73
86
 
74
87
  # Sets the flash message with :key, using I18n. By default you are able
@@ -85,12 +98,15 @@ module Devise
85
98
  #
86
99
  # Please refer to README or en.yml locale file to check what messages are
87
100
  # available.
88
- def set_flash_message(key, kind)
89
- flash[key] = I18n.t(:"#{resource_name}.#{kind}", :resource_name => resource_name,
90
- :scope => [:devise, controller_name.to_sym], :default => kind)
101
+ def set_flash_message(key, kind, options={}) #:nodoc:
102
+ options[:scope] = "devise.#{controller_name}"
103
+ options[:default] = Array(options[:default]).unshift(kind.to_sym)
104
+ options[:resource_name] = resource_name
105
+ message = I18n.t("#{resource_name}.#{kind}", options)
106
+ flash[key] = message if message.present?
91
107
  end
92
108
 
93
- def clean_up_passwords(object)
109
+ def clean_up_passwords(object) #:nodoc:
94
110
  object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
95
111
  end
96
112
  end
@@ -17,17 +17,15 @@ module Devise
17
17
 
18
18
  # Render a view for the specified scope. Turned off by default.
19
19
  # Accepts just :controller as option.
20
- def render_with_scope(action, options={})
21
- controller_name = options.delete(:controller) || self.controller_name
22
-
20
+ def render_with_scope(action, path=self.controller_path)
23
21
  if self.class.scoped_views?
24
22
  begin
25
- render :template => "#{devise_mapping.plural}/#{controller_name}/#{action}"
23
+ render :template => "#{devise_mapping.scoped_path}/#{path.split("/").last}/#{action}"
26
24
  rescue ActionView::MissingTemplate
27
- render :template => "#{controller_path}/#{action}"
25
+ render :template => "#{path}/#{action}"
28
26
  end
29
27
  else
30
- render :template => "#{controller_path}/#{action}"
28
+ render :template => "#{path}/#{action}"
31
29
  end
32
30
  end
33
31
  end
@@ -19,13 +19,11 @@ module Devise
19
19
  # Those helpers are added to your ApplicationController.
20
20
  module UrlHelpers
21
21
 
22
- Devise::ROUTES.values.uniq.each do |module_name|
22
+ Devise::URL_HELPERS.each do |module_name, actions|
23
23
  [:path, :url].each do |path_or_url|
24
- actions = [ nil, :new_ ]
25
- actions << :edit_ if [:password, :registration].include?(module_name)
26
- actions << :destroy_ if [:session].include?(module_name)
27
-
28
24
  actions.each do |action|
25
+ action = action ? "#{action}_" : ""
26
+
29
27
  class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
30
28
  def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args)
31
29
  scope = Devise::Mapping.find_scope!(resource_or_scope)
@@ -13,7 +13,7 @@ module Devise
13
13
  end
14
14
 
15
15
  def self.salt(stretches)
16
- Devise.friendly_token
16
+ Devise.friendly_token[0,20]
17
17
  end
18
18
  end
19
19
  end
@@ -5,10 +5,10 @@ module Devise
5
5
  # = RestfulAuthenticationSha1
6
6
  # Simulates Restful Authentication's default encryption mechanism.
7
7
  # Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
8
- # Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
9
- # the initializer to silumate the default behavior.
8
+ # Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
9
+ # the initializer to simulate the default behavior.
10
10
  class RestfulAuthenticationSha1 < Base
11
-
11
+
12
12
  # Gererates a default password digest based on salt, pepper and the
13
13
  # incoming password.
14
14
  def self.digest(password, stretches, salt, pepper)
@@ -19,4 +19,4 @@ module Devise
19
19
 
20
20
  end
21
21
  end
22
- end
22
+ end
@@ -33,7 +33,7 @@ module Devise
33
33
 
34
34
  def http_auth
35
35
  self.status = 401
36
- self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect})
36
+ self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header?
37
37
  self.content_type = request.format.to_s
38
38
  self.response_body = http_auth_body
39
39
  end
@@ -41,12 +41,12 @@ module Devise
41
41
  def recall
42
42
  env["PATH_INFO"] = attempted_path
43
43
  flash.now[:alert] = i18n_message(:invalid)
44
- self.response = recall_controller.action(warden_options[:recall]).call(env)
44
+ self.response = recall_app(warden_options[:recall]).call(env)
45
45
  end
46
46
 
47
47
  def redirect
48
48
  store_location!
49
- flash[:alert] = i18n_message unless flash[:notice]
49
+ flash[:alert] = i18n_message
50
50
  redirect_to redirect_url
51
51
  end
52
52
 
@@ -67,17 +67,37 @@ module Devise
67
67
  send(:"new_#{scope}_session_path")
68
68
  end
69
69
 
70
+ # Choose whether we should respond in a http authentication fashion,
71
+ # including 401 and optional headers.
72
+ #
73
+ # This method allows the user to explicitly disable http authentication
74
+ # on ajax requests in case they want to redirect on failures instead of
75
+ # handling the errors on their own. This is useful in case your ajax API
76
+ # is the same as your public API and uses a format like JSON (so you
77
+ # cannot mark JSON as a navigational format).
70
78
  def http_auth?
71
- !Devise.navigational_formats.include?(request_format) || (request.xhr? && Devise.http_authenticatable_on_xhr)
79
+ if request.xhr?
80
+ Devise.http_authenticatable_on_xhr
81
+ else
82
+ !(request.format && Devise.navigational_formats.include?(request.format.to_sym))
83
+ end
84
+ end
85
+
86
+ # It does not make sense to send authenticate headers in ajax requests
87
+ # or if the user disabled them.
88
+ def http_auth_header?
89
+ Devise.mappings[scope].to.http_authenticatable && !request.xhr?
72
90
  end
73
91
 
74
92
  def http_auth_body
75
- method = :"to_#{request_format}"
93
+ return i18n_message unless request.format
94
+ method = "to_#{request.format.to_sym}"
76
95
  {}.respond_to?(method) ? { :error => i18n_message }.send(method) : i18n_message
77
96
  end
78
97
 
79
- def recall_controller
80
- "#{params[:controller].camelize}Controller".constantize
98
+ def recall_app(app)
99
+ controller, action = app.split("#")
100
+ "#{controller.camelize}Controller".constantize.action(action)
81
101
  end
82
102
 
83
103
  def warden
@@ -89,7 +109,7 @@ module Devise
89
109
  end
90
110
 
91
111
  def scope
92
- @scope ||= warden_options[:scope]
112
+ @scope ||= warden_options[:scope] || Devise.default_scope
93
113
  end
94
114
 
95
115
  def attempted_path
@@ -101,19 +121,7 @@ module Devise
101
121
  # yet, but we still need to store the uri based on scope, so different scopes
102
122
  # would never use the same uri to redirect.
103
123
  def store_location!
104
- session[:"#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
105
- end
106
-
107
- MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
108
-
109
- def request_format
110
- @request_format ||= if request.format.respond_to?(:ref)
111
- request.format.ref
112
- elsif MIME_REFERENCES
113
- request.format
114
- else # Rails < 3.0.4
115
- request.format.to_sym
116
- end
124
+ session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
117
125
  end
118
126
  end
119
127
  end