devise 1.3.4 → 1.4.1
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.
- data/.travis.yml +3 -2
- data/CHANGELOG.rdoc +29 -0
- data/Gemfile +10 -7
- data/Gemfile.lock +47 -47
- data/README.rdoc +2 -2
- data/Rakefile +1 -1
- data/app/controllers/devise/confirmations_controller.rb +2 -2
- data/app/controllers/devise/passwords_controller.rb +10 -2
- data/app/controllers/devise/registrations_controller.rb +6 -4
- data/app/controllers/devise/unlocks_controller.rb +2 -2
- data/app/helpers/devise_helper.rb +1 -1
- data/app/mailers/devise/mailer.rb +4 -77
- data/config/locales/en.yml +3 -0
- data/lib/devise.rb +45 -13
- data/lib/devise/controllers/helpers.rb +5 -2
- data/lib/devise/controllers/internal_helpers.rb +15 -1
- data/lib/devise/controllers/rememberable.rb +1 -1
- data/lib/devise/email.rb +23 -0
- data/lib/devise/hooks/forgetable.rb +1 -1
- data/lib/devise/hooks/trackable.rb +1 -1
- data/lib/devise/mailers/helpers.rb +84 -0
- data/lib/devise/mapping.rb +23 -7
- data/lib/devise/models/authenticatable.rb +14 -6
- data/lib/devise/models/database_authenticatable.rb +18 -1
- data/lib/devise/models/recoverable.rb +1 -1
- data/lib/devise/models/rememberable.rb +7 -5
- data/lib/devise/models/validatable.rb +5 -7
- data/lib/devise/modules.rb +1 -1
- data/lib/devise/omniauth.rb +0 -5
- data/lib/devise/omniauth/config.rb +6 -0
- data/lib/devise/rails/routes.rb +65 -10
- data/lib/devise/strategies/rememberable.rb +2 -7
- data/lib/devise/version.rb +1 -1
- data/lib/generators/devise/install_generator.rb +2 -2
- data/lib/generators/devise/simple_form_for/confirmations/new.html.erb +15 -0
- data/lib/generators/devise/simple_form_for/passwords/edit.html.erb +19 -0
- data/lib/generators/devise/simple_form_for/passwords/new.html.erb +15 -0
- data/lib/generators/devise/simple_form_for/registrations/edit.html.erb +22 -0
- data/lib/generators/devise/simple_form_for/registrations/new.html.erb +17 -0
- data/lib/generators/devise/simple_form_for/sessions/new.html.erb +15 -0
- data/lib/generators/devise/simple_form_for/unlocks/new.html.erb +15 -0
- data/lib/generators/devise/views_generator.rb +61 -9
- data/lib/generators/templates/devise.rb +13 -3
- data/test/controllers/internal_helpers_test.rb +9 -2
- data/test/generators/views_generator_test.rb +10 -0
- data/test/helpers/devise_helper_test.rb +43 -0
- data/test/integration/authenticatable_test.rb +74 -5
- data/test/integration/confirmable_test.rb +39 -1
- data/test/integration/database_authenticatable_test.rb +22 -0
- data/test/integration/http_authenticatable_test.rb +8 -0
- data/test/integration/lockable_test.rb +62 -4
- data/test/integration/omniauthable_test.rb +1 -3
- data/test/integration/recoverable_test.rb +66 -6
- data/test/integration/registerable_test.rb +1 -1
- data/test/integration/rememberable_test.rb +20 -1
- data/test/integration/trackable_test.rb +17 -0
- data/test/mapping_test.rb +5 -0
- data/test/models/database_authenticatable_test.rb +56 -1
- data/test/models/encryptable_test.rb +1 -1
- data/test/models/recoverable_test.rb +14 -3
- data/test/models/rememberable_test.rb +8 -0
- data/test/models/token_authenticatable_test.rb +0 -6
- data/test/models/validatable_test.rb +17 -4
- data/test/models_test.rb +4 -0
- data/test/omniauth/url_helpers_test.rb +4 -0
- data/test/rails_app/app/controllers/home_controller.rb +9 -0
- data/test/rails_app/app/controllers/users_controller.rb +6 -1
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -0
- data/test/rails_app/app/views/home/join.html.erb +1 -0
- data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -0
- data/test/rails_app/config/initializers/devise.rb +6 -0
- data/test/rails_app/config/routes.rb +30 -2
- data/test/routes_test.rb +54 -0
- metadata +21 -4
data/config/locales/en.yml
CHANGED
@@ -27,8 +27,10 @@ en:
|
|
27
27
|
passwords:
|
28
28
|
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
29
29
|
updated: 'Your password was changed successfully. You are now signed in.'
|
30
|
+
send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail"
|
30
31
|
confirmations:
|
31
32
|
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
33
|
+
send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
32
34
|
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
33
35
|
registrations:
|
34
36
|
signed_up: 'Welcome! You have signed up successfully.'
|
@@ -38,6 +40,7 @@ en:
|
|
38
40
|
unlocks:
|
39
41
|
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
40
42
|
unlocked: 'Your account was successfully unlocked. You are now signed in.'
|
43
|
+
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
41
44
|
omniauth_callbacks:
|
42
45
|
success: 'Successfully authorized from %{kind} account.'
|
43
46
|
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
data/lib/devise.rb
CHANGED
@@ -3,6 +3,7 @@ require 'active_support/core_ext/numeric/time'
|
|
3
3
|
require 'active_support/dependencies'
|
4
4
|
require 'orm_adapter'
|
5
5
|
require 'set'
|
6
|
+
require 'securerandom'
|
6
7
|
|
7
8
|
module Devise
|
8
9
|
autoload :FailureApp, 'devise/failure_app'
|
@@ -10,6 +11,7 @@ module Devise
|
|
10
11
|
autoload :PathChecker, 'devise/path_checker'
|
11
12
|
autoload :Schema, 'devise/schema'
|
12
13
|
autoload :TestHelpers, 'devise/test_helpers'
|
14
|
+
autoload :Email, 'devise/email'
|
13
15
|
|
14
16
|
module Controllers
|
15
17
|
autoload :Helpers, 'devise/controllers/helpers'
|
@@ -29,6 +31,10 @@ module Devise
|
|
29
31
|
autoload :Sha1, 'devise/encryptors/sha1'
|
30
32
|
end
|
31
33
|
|
34
|
+
module Mailers
|
35
|
+
autoload :Helpers, 'devise/mailers/helpers'
|
36
|
+
end
|
37
|
+
|
32
38
|
module Strategies
|
33
39
|
autoload :Base, 'devise/strategies/base'
|
34
40
|
autoload :Authenticatable, 'devise/strategies/authenticatable'
|
@@ -42,6 +48,9 @@ module Devise
|
|
42
48
|
STRATEGIES = ActiveSupport::OrderedHash.new
|
43
49
|
URL_HELPERS = ActiveSupport::OrderedHash.new
|
44
50
|
|
51
|
+
# Strategies that do not require user input.
|
52
|
+
NO_INPUT = []
|
53
|
+
|
45
54
|
# True values used to check params
|
46
55
|
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
47
56
|
|
@@ -74,6 +83,11 @@ module Devise
|
|
74
83
|
# False by default for backwards compatibility.
|
75
84
|
mattr_accessor :case_insensitive_keys
|
76
85
|
@@case_insensitive_keys = false
|
86
|
+
|
87
|
+
# Keys that should have whitespace stripped.
|
88
|
+
# False by default for backwards compatibility.
|
89
|
+
mattr_accessor :strip_whitespace_keys
|
90
|
+
@@strip_whitespace_keys = false
|
77
91
|
|
78
92
|
# If http authentication is enabled by default.
|
79
93
|
mattr_accessor :http_authenticatable
|
@@ -91,9 +105,11 @@ module Devise
|
|
91
105
|
mattr_accessor :http_authentication_realm
|
92
106
|
@@http_authentication_realm = "Application"
|
93
107
|
|
94
|
-
# Email regex used to validate email formats.
|
108
|
+
# Email regex used to validate email formats. Based on RFC 822 and
|
109
|
+
# retrieved from Sixarm email validation gem
|
110
|
+
# (https://github.com/SixArm/sixarm_ruby_email_address_validation).
|
95
111
|
mattr_accessor :email_regexp
|
96
|
-
@@email_regexp =
|
112
|
+
@@email_regexp = Devise::Email::EXACT_PATTERN
|
97
113
|
|
98
114
|
# Range validation for password length
|
99
115
|
mattr_accessor :password_length
|
@@ -172,7 +188,7 @@ module Devise
|
|
172
188
|
mattr_accessor :reset_password_keys
|
173
189
|
@@reset_password_keys = [ :email ]
|
174
190
|
|
175
|
-
# Time interval you can reset your password with a reset password key
|
191
|
+
# Time interval you can reset your password with a reset password key
|
176
192
|
mattr_accessor :reset_password_within
|
177
193
|
@@reset_password_within = nil
|
178
194
|
|
@@ -225,15 +241,30 @@ module Devise
|
|
225
241
|
@@warden_config = nil
|
226
242
|
@@warden_config_block = nil
|
227
243
|
|
244
|
+
# When true, enter in paranoid mode to avoid user enumeration.
|
245
|
+
mattr_accessor :paranoid
|
246
|
+
@@paranoid = false
|
247
|
+
|
228
248
|
# Default way to setup Devise. Run rails generate devise_install to create
|
229
249
|
# a fresh initializer with all configuration values.
|
230
250
|
def self.setup
|
231
251
|
yield self
|
232
252
|
end
|
233
253
|
|
254
|
+
class Getter
|
255
|
+
def initialize name
|
256
|
+
@name = name
|
257
|
+
end
|
258
|
+
|
259
|
+
def get
|
260
|
+
ActiveSupport::Dependencies.constantize(@name)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
234
264
|
def self.ref(arg)
|
235
265
|
if defined?(ActiveSupport::Dependencies::ClassCache)
|
236
|
-
ActiveSupport::Dependencies::
|
266
|
+
ActiveSupport::Dependencies::reference(arg)
|
267
|
+
Getter.new(arg)
|
237
268
|
else
|
238
269
|
ActiveSupport::Dependencies.ref(arg)
|
239
270
|
end
|
@@ -245,11 +276,7 @@ module Devise
|
|
245
276
|
|
246
277
|
# Get the mailer class from the mailer reference object.
|
247
278
|
def self.mailer
|
248
|
-
|
249
|
-
@@mailer_ref.get "Devise::Mailer"
|
250
|
-
else
|
251
|
-
@@mailer_ref.get
|
252
|
-
end
|
279
|
+
@@mailer_ref.get
|
253
280
|
end
|
254
281
|
|
255
282
|
# Set the mailer reference object to access the mailer.
|
@@ -290,13 +317,17 @@ module Devise
|
|
290
317
|
options.assert_valid_keys(:strategy, :model, :controller, :route)
|
291
318
|
|
292
319
|
if strategy = options[:strategy]
|
293
|
-
|
320
|
+
strategy = (strategy == true ? module_name : strategy)
|
321
|
+
STRATEGIES[module_name] = strategy
|
294
322
|
end
|
295
323
|
|
296
324
|
if controller = options[:controller]
|
297
|
-
|
325
|
+
controller = (controller == true ? module_name : controller)
|
326
|
+
CONTROLLERS[module_name] = controller
|
298
327
|
end
|
299
328
|
|
329
|
+
NO_INPUT << strategy if strategy && controller != :sessions
|
330
|
+
|
300
331
|
if route = options[:route]
|
301
332
|
case route
|
302
333
|
when TrueClass
|
@@ -346,7 +377,8 @@ module Devise
|
|
346
377
|
#
|
347
378
|
def self.omniauth(provider, *args)
|
348
379
|
@@helpers << Devise::OmniAuth::UrlHelpers
|
349
|
-
|
380
|
+
config = Devise::OmniAuth::Config.new(provider, args)
|
381
|
+
@@omniauth_configs[config.strategy_name.to_sym] = config
|
350
382
|
end
|
351
383
|
|
352
384
|
# Include helpers in the given scope to AC and AV.
|
@@ -385,7 +417,7 @@ module Devise
|
|
385
417
|
|
386
418
|
# Generate a friendly string randomically to be used as token.
|
387
419
|
def self.friendly_token
|
388
|
-
|
420
|
+
SecureRandom.base64(15).tr('+/=', 'xyz')
|
389
421
|
end
|
390
422
|
|
391
423
|
# constant-time comparison algorithm to prevent timing attacks
|
@@ -5,7 +5,7 @@ module Devise
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
helper_method :warden, :signed_in?, :devise_controller
|
8
|
+
helper_method :warden, :signed_in?, :devise_controller?
|
9
9
|
end
|
10
10
|
|
11
11
|
# Define authentication filters and accessor helpers based on mappings.
|
@@ -218,9 +218,12 @@ module Devise
|
|
218
218
|
session.keys.grep(/^devise\./).each { |k| session.delete(k) }
|
219
219
|
end
|
220
220
|
|
221
|
-
# Overwrite Rails' handle unverified request to sign out all scopes
|
221
|
+
# Overwrite Rails' handle unverified request to sign out all scopes,
|
222
|
+
# clear run strategies and remove cached variables.
|
222
223
|
def handle_unverified_request
|
223
224
|
sign_out_all_scopes
|
225
|
+
warden.clear_strategies_cache!
|
226
|
+
Devise.mappings.each { |_,m| instance_variable_set("@current_#{m.name}", nil) }
|
224
227
|
super # call the default behaviour which resets the session
|
225
228
|
end
|
226
229
|
end
|
@@ -91,13 +91,27 @@ MESSAGE
|
|
91
91
|
# Example:
|
92
92
|
# before_filter :require_no_authentication, :only => :new
|
93
93
|
def require_no_authentication
|
94
|
-
|
94
|
+
no_input = devise_mapping.no_input_strategies
|
95
|
+
args = no_input.dup.push :scope => resource_name
|
96
|
+
if no_input.present? && warden.authenticate?(*args)
|
95
97
|
resource = warden.user(resource_name)
|
96
98
|
flash[:alert] = I18n.t("devise.failure.already_authenticated")
|
97
99
|
redirect_to after_sign_in_path_for(resource)
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
103
|
+
# Helper for use to validate if an resource is errorless. If we are on paranoid mode, we always should assume it is
|
104
|
+
# and return false.
|
105
|
+
def successful_and_sane?(resource)
|
106
|
+
if Devise.paranoid
|
107
|
+
set_flash_message :notice, :send_paranoid_instructions if is_navigational_format?
|
108
|
+
resource.errors.clear
|
109
|
+
false
|
110
|
+
else
|
111
|
+
resource.errors.empty?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
101
115
|
# Sets the flash message with :key, using I18n. By default you are able
|
102
116
|
# to setup your messages using specific resource scope, and if no one is
|
103
117
|
# found we look to default scope.
|
@@ -29,7 +29,7 @@ module Devise
|
|
29
29
|
# Forgets the given resource by deleting a cookie
|
30
30
|
def forget_me(resource)
|
31
31
|
scope = Devise::Mapping.find_scope!(resource)
|
32
|
-
resource.forget_me!
|
32
|
+
resource.forget_me!
|
33
33
|
cookies.delete("remember_#{scope}_token", forget_cookie_values(resource))
|
34
34
|
end
|
35
35
|
|
data/lib/devise/email.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# This e-mail validation regexes were retrieved from SixArm Ruby
|
2
|
+
# e-mail validation gem (https://github.com/SixArm/sixarm_ruby_email_address_validation)
|
3
|
+
# As said on https://github.com/SixArm/sixarm_ruby_email_address_validation/blob/master/LICENSE.txt,
|
4
|
+
# we added it using Ruby license terms.
|
5
|
+
|
6
|
+
module Devise
|
7
|
+
module Email
|
8
|
+
QTEXT = Regexp.new '[^\\x0d\\x22\\x5c\\x80-\\xff]', nil, 'n'
|
9
|
+
DTEXT = Regexp.new '[^\\x0d\\x5b-\\x5d\\x80-\\xff]', nil, 'n'
|
10
|
+
ATOM = Regexp.new '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+', nil, 'n'
|
11
|
+
QUOTED_PAIR = Regexp.new '\\x5c[\\x00-\\x7f]', nil, 'n'
|
12
|
+
DOMAIN_LITERAL = Regexp.new "\\x5b(?:#{DTEXT}|#{QUOTED_PAIR})*\\x5d", nil, 'n'
|
13
|
+
QUOTED_STRING = Regexp.new "\\x22(?:#{QTEXT}|#{QUOTED_PAIR})*\\x22", nil, 'n'
|
14
|
+
DOMAIN_REF = ATOM
|
15
|
+
SUB_DOMAIN = "(?:#{DOMAIN_REF}|#{DOMAIN_LITERAL})"
|
16
|
+
WORD = "(?:#{ATOM}|#{QUOTED_STRING})"
|
17
|
+
DOMAIN = "#{SUB_DOMAIN}(?:\\x2e#{SUB_DOMAIN})*"
|
18
|
+
LOCAL_PART = "#{WORD}(?:\\x2e#{WORD})*"
|
19
|
+
SPEC = "#{LOCAL_PART}\\x40#{DOMAIN}"
|
20
|
+
PATTERN = Regexp.new "#{SPEC}", nil, 'n'
|
21
|
+
EXACT_PATTERN = Regexp.new "\\A#{SPEC}\\z", nil, 'n'
|
22
|
+
end
|
23
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Before logout hook to forget the user in the given scope, if it responds
|
2
2
|
# to forget_me! Also clear remember token to ensure the user won't be
|
3
|
-
# remembered again. Notice that we forget the user unless the record is
|
3
|
+
# remembered again. Notice that we forget the user unless the record is not persisted.
|
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!)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# and on authentication. Retrieving the user from session (:fetch) does
|
4
4
|
# not trigger it.
|
5
5
|
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
6
|
-
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope])
|
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
|
9
9
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Devise
|
2
|
+
module Mailers
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
include Devise::Controllers::ScopedViews
|
8
|
+
attr_reader :scope_name, :resource
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# Configure default email options
|
14
|
+
def devise_mail(record, action)
|
15
|
+
initialize_from_record(record)
|
16
|
+
mail headers_for(action)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize_from_record(record)
|
20
|
+
@scope_name = Devise::Mapping.find_scope!(record)
|
21
|
+
@resource = instance_variable_set("@#{devise_mapping.name}", record)
|
22
|
+
end
|
23
|
+
|
24
|
+
def devise_mapping
|
25
|
+
@devise_mapping ||= Devise.mappings[scope_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def headers_for(action)
|
29
|
+
headers = {
|
30
|
+
:subject => translate(devise_mapping, action),
|
31
|
+
:from => mailer_sender(devise_mapping),
|
32
|
+
:to => resource.email,
|
33
|
+
:template_path => template_paths
|
34
|
+
}
|
35
|
+
|
36
|
+
if resource.respond_to?(:headers_for)
|
37
|
+
headers.merge!(resource.headers_for(action))
|
38
|
+
end
|
39
|
+
|
40
|
+
unless headers.key?(:reply_to)
|
41
|
+
headers[:reply_to] = headers[:from]
|
42
|
+
end
|
43
|
+
|
44
|
+
headers
|
45
|
+
end
|
46
|
+
|
47
|
+
def mailer_sender(mapping)
|
48
|
+
if Devise.mailer_sender.is_a?(Proc)
|
49
|
+
Devise.mailer_sender.call(mapping.name)
|
50
|
+
else
|
51
|
+
Devise.mailer_sender
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def template_paths
|
56
|
+
template_path = [self.class.mailer_name]
|
57
|
+
template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
|
58
|
+
template_path
|
59
|
+
end
|
60
|
+
|
61
|
+
# Setup a subject doing an I18n lookup. At first, it attemps to set a subject
|
62
|
+
# based on the current mapping:
|
63
|
+
#
|
64
|
+
# en:
|
65
|
+
# devise:
|
66
|
+
# mailer:
|
67
|
+
# confirmation_instructions:
|
68
|
+
# user_subject: '...'
|
69
|
+
#
|
70
|
+
# If one does not exist, it fallbacks to ActionMailer default:
|
71
|
+
#
|
72
|
+
# en:
|
73
|
+
# devise:
|
74
|
+
# mailer:
|
75
|
+
# confirmation_instructions:
|
76
|
+
# subject: '...'
|
77
|
+
#
|
78
|
+
def translate(mapping, key)
|
79
|
+
I18n.t(:"#{mapping.name}_subject", :scope => [:devise, :mailer, key],
|
80
|
+
:default => [:subject, key.to_s.humanize])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/devise/mapping.rb
CHANGED
@@ -22,7 +22,7 @@ module Devise
|
|
22
22
|
# # is the modules included in the class
|
23
23
|
#
|
24
24
|
class Mapping #:nodoc:
|
25
|
-
attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via
|
25
|
+
attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via, :format
|
26
26
|
alias :name :singular
|
27
27
|
|
28
28
|
# Receives an object and find a scope for it. If a scope cannot be found,
|
@@ -58,12 +58,20 @@ module Devise
|
|
58
58
|
mod = options[:module] || "devise"
|
59
59
|
@controllers = Hash.new { |h,k| h[k] = "#{mod}/#{k}" }
|
60
60
|
@controllers.merge!(options[:controllers] || {})
|
61
|
+
@controllers.each { |k,v| @controllers[k] = v.to_s }
|
61
62
|
|
62
63
|
@path_names = Hash.new { |h,k| h[k] = k.to_s }
|
63
64
|
@path_names.merge!(:registration => "")
|
64
65
|
@path_names.merge!(options[:path_names] || {})
|
66
|
+
|
67
|
+
@constraints = Hash.new { |h,k| h[k] = k.to_s }
|
68
|
+
@constraints.merge!(options[:constraints] || {})
|
69
|
+
|
70
|
+
@defaults = Hash.new { |h,k| h[k] = k.to_s }
|
71
|
+
@defaults.merge!(options[:defaults] || {})
|
65
72
|
|
66
73
|
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
|
74
|
+
@format = options[:format]
|
67
75
|
end
|
68
76
|
|
69
77
|
# Return modules for the mapping.
|
@@ -73,17 +81,17 @@ module Devise
|
|
73
81
|
|
74
82
|
# Gives the class the mapping points to.
|
75
83
|
def to
|
76
|
-
|
77
|
-
@ref.get @class_name
|
78
|
-
else
|
79
|
-
@ref.get
|
80
|
-
end
|
84
|
+
@ref.get
|
81
85
|
end
|
82
86
|
|
83
87
|
def strategies
|
84
88
|
@strategies ||= STRATEGIES.values_at(*self.modules).compact.uniq.reverse
|
85
89
|
end
|
86
90
|
|
91
|
+
def no_input_strategies
|
92
|
+
self.strategies & Devise::NO_INPUT
|
93
|
+
end
|
94
|
+
|
87
95
|
def routes
|
88
96
|
@routes ||= ROUTES.values_at(*self.modules).compact.uniq
|
89
97
|
end
|
@@ -95,7 +103,15 @@ module Devise
|
|
95
103
|
def fullpath
|
96
104
|
"/#{@path_prefix}/#{@path}".squeeze("/")
|
97
105
|
end
|
98
|
-
|
106
|
+
|
107
|
+
def constraints
|
108
|
+
@constraints
|
109
|
+
end
|
110
|
+
|
111
|
+
def defaults
|
112
|
+
@defaults
|
113
|
+
end
|
114
|
+
|
99
115
|
# Create magic predicates for verifying what module is activated by this map.
|
100
116
|
# Example:
|
101
117
|
#
|
@@ -76,7 +76,8 @@ module Devise
|
|
76
76
|
def authenticatable_salt
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
# TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
|
80
|
+
%w(to_xml serializable_hash).each do |method|
|
80
81
|
class_eval <<-RUBY, __FILE__, __LINE__
|
81
82
|
def #{method}(options={})
|
82
83
|
if self.class.respond_to?(:accessible_attributes)
|
@@ -90,7 +91,7 @@ module Devise
|
|
90
91
|
end
|
91
92
|
|
92
93
|
module ClassMethods
|
93
|
-
Devise::Models.config(self, :authentication_keys, :request_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
94
|
+
Devise::Models.config(self, :authentication_keys, :request_keys, :strip_whitespace_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
94
95
|
|
95
96
|
def params_authenticatable?(strategy)
|
96
97
|
params_authenticatable.is_a?(Array) ?
|
@@ -113,8 +114,9 @@ module Devise
|
|
113
114
|
# end
|
114
115
|
#
|
115
116
|
def find_for_authentication(conditions)
|
116
|
-
filter_auth_params(conditions)
|
117
|
+
conditions = filter_auth_params(conditions.dup)
|
117
118
|
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
119
|
+
(strip_whitespace_keys || []).each { |k| conditions[k].try(:strip!) }
|
118
120
|
to_adapter.find_first(conditions)
|
119
121
|
end
|
120
122
|
|
@@ -126,14 +128,15 @@ module Devise
|
|
126
128
|
# Find an initialize a group of attributes based on a list of required attributes.
|
127
129
|
def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
|
128
130
|
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
129
|
-
|
131
|
+
(strip_whitespace_keys || []).each { |k| attributes[k].try(:strip!) }
|
132
|
+
|
130
133
|
attributes = attributes.slice(*required_attributes)
|
131
134
|
attributes.delete_if { |key, value| value.blank? }
|
132
135
|
|
133
136
|
if attributes.size == required_attributes.size
|
134
137
|
record = to_adapter.find_first(filter_auth_params(attributes))
|
135
138
|
end
|
136
|
-
|
139
|
+
|
137
140
|
unless record
|
138
141
|
record = new
|
139
142
|
|
@@ -152,9 +155,14 @@ module Devise
|
|
152
155
|
# Force keys to be string to avoid injection on mongoid related database.
|
153
156
|
def filter_auth_params(conditions)
|
154
157
|
conditions.each do |k, v|
|
155
|
-
conditions[k] = v.to_s
|
158
|
+
conditions[k] = v.to_s if auth_param_requires_string_conversion?(v)
|
156
159
|
end if conditions.is_a?(Hash)
|
157
160
|
end
|
161
|
+
|
162
|
+
# Determine which values should be transformed to string or passed as-is to the query builder underneath
|
163
|
+
def auth_param_requires_string_conversion?(value)
|
164
|
+
true unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Fixnum)
|
165
|
+
end
|
158
166
|
|
159
167
|
# Generate a token by looping and ensuring does not already exist.
|
160
168
|
def generate_token(column)
|