devise 3.2.1 → 4.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.travis.yml +58 -10
- data/CHANGELOG.md +199 -979
- data/CODE_OF_CONDUCT.md +22 -0
- data/CONTRIBUTING.md +73 -8
- data/Gemfile +19 -11
- data/Gemfile.lock +152 -119
- data/ISSUE_TEMPLATE.md +19 -0
- data/MIT-LICENSE +1 -1
- data/README.md +347 -93
- data/Rakefile +4 -2
- data/app/controllers/devise/confirmations_controller.rb +11 -5
- data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
- data/app/controllers/devise/passwords_controller.rb +20 -8
- data/app/controllers/devise/registrations_controller.rb +34 -19
- data/app/controllers/devise/sessions_controller.rb +47 -17
- data/app/controllers/devise/unlocks_controller.rb +9 -4
- data/app/controllers/devise_controller.rb +67 -31
- data/app/helpers/devise_helper.rb +4 -2
- data/app/mailers/devise/mailer.rb +10 -0
- data/app/views/devise/confirmations/new.html.erb +8 -4
- data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/devise/mailer/email_changed.html.erb +7 -0
- data/app/views/devise/mailer/password_change.html.erb +3 -0
- data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
- data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
- data/app/views/devise/passwords/edit.html.erb +15 -6
- data/app/views/devise/passwords/new.html.erb +8 -4
- data/app/views/devise/registrations/edit.html.erb +28 -14
- data/app/views/devise/registrations/new.html.erb +19 -8
- data/app/views/devise/sessions/new.html.erb +17 -8
- data/app/views/devise/shared/{_links.erb → _links.html.erb} +2 -2
- data/app/views/devise/unlocks/new.html.erb +8 -4
- data/bin/test +13 -0
- data/config/locales/en.yml +22 -17
- data/devise.gemspec +7 -6
- data/gemfiles/Gemfile.rails-4.1-stable +32 -0
- data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
- data/gemfiles/Gemfile.rails-4.2-stable +32 -0
- data/gemfiles/Gemfile.rails-4.2-stable.lock +192 -0
- data/gemfiles/Gemfile.rails-5.0-stable +33 -0
- data/gemfiles/Gemfile.rails-5.0-stable.lock +192 -0
- data/gemfiles/Gemfile.rails-5.2-rc1 +26 -0
- data/gemfiles/Gemfile.rails-5.2-rc1.lock +201 -0
- data/guides/bug_report_templates/integration_test.rb +106 -0
- data/lib/devise.rb +107 -84
- data/lib/devise/controllers/helpers.rb +111 -31
- data/lib/devise/controllers/rememberable.rb +15 -6
- data/lib/devise/controllers/scoped_views.rb +3 -1
- data/lib/devise/controllers/sign_in_out.rb +39 -26
- data/lib/devise/controllers/store_location.rb +31 -2
- data/lib/devise/controllers/url_helpers.rb +9 -7
- data/lib/devise/delegator.rb +2 -0
- data/lib/devise/encryptor.rb +24 -0
- data/lib/devise/failure_app.rb +98 -39
- data/lib/devise/hooks/activatable.rb +7 -6
- data/lib/devise/hooks/csrf_cleaner.rb +5 -1
- data/lib/devise/hooks/forgetable.rb +2 -0
- data/lib/devise/hooks/lockable.rb +7 -2
- data/lib/devise/hooks/proxy.rb +4 -2
- data/lib/devise/hooks/rememberable.rb +4 -2
- data/lib/devise/hooks/timeoutable.rb +16 -9
- data/lib/devise/hooks/trackable.rb +3 -1
- data/lib/devise/mailers/helpers.rb +15 -12
- data/lib/devise/mapping.rb +8 -2
- data/lib/devise/models.rb +3 -1
- data/lib/devise/models/authenticatable.rb +63 -36
- data/lib/devise/models/confirmable.rb +121 -41
- data/lib/devise/models/database_authenticatable.rb +66 -23
- data/lib/devise/models/lockable.rb +30 -17
- data/lib/devise/models/omniauthable.rb +3 -1
- data/lib/devise/models/recoverable.rb +62 -26
- data/lib/devise/models/registerable.rb +2 -0
- data/lib/devise/models/rememberable.rb +62 -33
- data/lib/devise/models/timeoutable.rb +4 -8
- data/lib/devise/models/trackable.rb +12 -3
- data/lib/devise/models/validatable.rb +16 -9
- data/lib/devise/modules.rb +12 -10
- data/lib/devise/omniauth.rb +2 -0
- data/lib/devise/omniauth/config.rb +2 -0
- data/lib/devise/omniauth/url_helpers.rb +14 -5
- data/lib/devise/orm/active_record.rb +5 -1
- data/lib/devise/orm/mongoid.rb +6 -2
- data/lib/devise/parameter_filter.rb +2 -0
- data/lib/devise/parameter_sanitizer.rb +131 -69
- data/lib/devise/rails.rb +10 -13
- data/lib/devise/rails/routes.rb +147 -116
- data/lib/devise/rails/warden_compat.rb +3 -10
- data/lib/devise/secret_key_finder.rb +25 -0
- data/lib/devise/strategies/authenticatable.rb +20 -9
- data/lib/devise/strategies/base.rb +3 -1
- data/lib/devise/strategies/database_authenticatable.rb +8 -5
- data/lib/devise/strategies/rememberable.rb +15 -3
- data/lib/devise/test/controller_helpers.rb +165 -0
- data/lib/devise/test/integration_helpers.rb +63 -0
- data/lib/devise/test_helpers.rb +7 -124
- data/lib/devise/time_inflector.rb +4 -2
- data/lib/devise/token_generator.rb +3 -41
- data/lib/devise/version.rb +3 -1
- data/lib/generators/active_record/devise_generator.rb +47 -10
- data/lib/generators/active_record/templates/migration.rb +9 -7
- data/lib/generators/active_record/templates/migration_existing.rb +9 -7
- data/lib/generators/devise/controllers_generator.rb +46 -0
- data/lib/generators/devise/devise_generator.rb +9 -5
- data/lib/generators/devise/install_generator.rb +22 -0
- data/lib/generators/devise/orm_helpers.rb +8 -19
- data/lib/generators/devise/views_generator.rb +51 -28
- data/lib/generators/mongoid/devise_generator.rb +22 -19
- data/lib/generators/templates/README +5 -12
- data/lib/generators/templates/controllers/README +14 -0
- data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
- data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
- data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
- data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
- data/lib/generators/templates/devise.rb +64 -35
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/email_changed.markerb +7 -0
- data/lib/generators/templates/markerb/password_change.markerb +3 -0
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
- data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +2 -2
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +6 -6
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +6 -6
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -2
- data/test/controllers/custom_registrations_controller_test.rb +42 -0
- data/test/controllers/custom_strategy_test.rb +10 -6
- data/test/controllers/helper_methods_test.rb +24 -0
- data/test/controllers/helpers_test.rb +88 -40
- data/test/controllers/inherited_controller_i18n_messages_test.rb +53 -0
- data/test/controllers/internal_helpers_test.rb +31 -22
- data/test/controllers/load_hooks_controller_test.rb +21 -0
- data/test/controllers/passwords_controller_test.rb +8 -5
- data/test/controllers/sessions_controller_test.rb +42 -33
- data/test/controllers/url_helpers_test.rb +13 -5
- data/test/delegator_test.rb +3 -1
- data/test/devise_test.rb +34 -19
- data/test/failure_app_test.rb +150 -42
- data/test/generators/active_record_generator_test.rb +58 -31
- data/test/generators/controllers_generator_test.rb +50 -0
- data/test/generators/devise_generator_test.rb +4 -2
- data/test/generators/install_generator_test.rb +16 -3
- data/test/generators/mongoid_generator_test.rb +5 -3
- data/test/generators/views_generator_test.rb +40 -2
- data/test/helpers/devise_helper_test.rb +20 -20
- data/test/integration/authenticatable_test.rb +134 -141
- data/test/integration/confirmable_test.rb +109 -67
- data/test/integration/database_authenticatable_test.rb +36 -23
- data/test/integration/http_authenticatable_test.rb +29 -20
- data/test/integration/lockable_test.rb +52 -49
- data/test/integration/mounted_engine_test.rb +38 -0
- data/test/integration/omniauthable_test.rb +30 -15
- data/test/integration/recoverable_test.rb +76 -61
- data/test/integration/registerable_test.rb +107 -91
- data/test/integration/rememberable_test.rb +82 -30
- data/test/integration/timeoutable_test.rb +48 -40
- data/test/integration/trackable_test.rb +15 -8
- data/test/mailers/confirmation_instructions_test.rb +16 -14
- data/test/mailers/email_changed_test.rb +132 -0
- data/test/mailers/mailer_test.rb +20 -0
- data/test/mailers/reset_password_instructions_test.rb +13 -11
- data/test/mailers/unlock_instructions_test.rb +12 -10
- data/test/mapping_test.rb +15 -6
- data/test/models/authenticatable_test.rb +15 -3
- data/test/models/confirmable_test.rb +190 -95
- data/test/models/database_authenticatable_test.rb +75 -41
- data/test/models/lockable_test.rb +115 -61
- data/test/models/omniauthable_test.rb +3 -1
- data/test/models/recoverable_test.rb +116 -37
- data/test/models/registerable_test.rb +3 -1
- data/test/models/rememberable_test.rb +95 -94
- data/test/models/serializable_test.rb +19 -8
- data/test/models/timeoutable_test.rb +10 -8
- data/test/models/trackable_test.rb +50 -1
- data/test/models/validatable_test.rb +24 -30
- data/test/models_test.rb +19 -8
- data/test/omniauth/config_test.rb +15 -11
- data/test/omniauth/url_helpers_test.rb +8 -9
- data/test/orm/active_record.rb +16 -2
- data/test/orm/mongoid.rb +4 -2
- data/test/parameter_sanitizer_test.rb +53 -57
- data/test/rails_app/app/active_record/admin.rb +2 -0
- data/test/rails_app/app/active_record/shim.rb +3 -1
- data/test/rails_app/app/active_record/user.rb +14 -0
- data/test/rails_app/app/active_record/user_on_engine.rb +9 -0
- data/test/rails_app/app/active_record/user_on_main_app.rb +9 -0
- data/test/rails_app/app/active_record/user_with_validations.rb +12 -0
- data/test/rails_app/app/active_record/user_without_email.rb +10 -0
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +3 -1
- data/test/rails_app/app/controllers/admins_controller.rb +3 -6
- data/test/rails_app/app/controllers/application_controller.rb +7 -3
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +32 -0
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +33 -0
- data/test/rails_app/app/controllers/home_controller.rb +7 -1
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +3 -1
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +3 -1
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +7 -5
- data/test/rails_app/app/controllers/users_controller.rb +8 -6
- data/test/rails_app/app/helpers/application_helper.rb +2 -0
- data/test/rails_app/app/mailers/users/from_proc_mailer.rb +5 -0
- data/test/rails_app/app/mailers/users/mailer.rb +3 -10
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +6 -0
- data/test/rails_app/app/mongoid/admin.rb +13 -11
- data/test/rails_app/app/mongoid/shim.rb +4 -2
- data/test/rails_app/app/mongoid/user.rb +30 -19
- data/test/rails_app/app/mongoid/user_on_engine.rb +41 -0
- data/test/rails_app/app/mongoid/user_on_main_app.rb +41 -0
- data/test/rails_app/app/mongoid/user_with_validations.rb +37 -0
- data/test/rails_app/app/mongoid/user_without_email.rb +35 -0
- data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
- data/test/rails_app/app/views/home/index.html.erb +1 -1
- data/test/rails_app/app/views/home/join.html.erb +1 -1
- data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
- data/test/rails_app/app/views/layouts/application.html.erb +1 -1
- data/test/rails_app/config/application.rb +13 -5
- data/test/rails_app/config/boot.rb +17 -4
- data/test/rails_app/config/environment.rb +2 -0
- data/test/rails_app/config/environments/development.rb +2 -0
- data/test/rails_app/config/environments/production.rb +10 -2
- data/test/rails_app/config/environments/test.rb +14 -3
- data/test/rails_app/config/initializers/backtrace_silencers.rb +2 -0
- data/test/rails_app/config/initializers/devise.rb +22 -21
- data/test/rails_app/config/initializers/inflections.rb +2 -0
- data/test/rails_app/config/initializers/secret_token.rb +3 -6
- data/test/rails_app/config/initializers/session_store.rb +2 -0
- data/test/rails_app/config/routes.rb +67 -43
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +16 -10
- data/test/rails_app/db/schema.rb +2 -0
- data/test/rails_app/lib/shared_admin.rb +10 -4
- data/test/rails_app/lib/shared_user.rb +4 -1
- data/test/rails_app/lib/shared_user_without_email.rb +28 -0
- data/test/rails_app/lib/shared_user_without_omniauth.rb +15 -0
- data/test/rails_test.rb +11 -0
- data/test/routes_test.rb +92 -61
- data/test/secret_key_finder_test.rb +97 -0
- data/test/support/action_controller/record_identifier.rb +12 -0
- data/test/support/assertions.rb +4 -14
- data/test/support/helpers.rb +23 -10
- data/test/support/http_method_compatibility.rb +53 -0
- data/test/support/integration.rb +19 -16
- data/test/support/mongoid.yml +6 -0
- data/test/support/webrat/integrations/rails.rb +11 -0
- data/test/{test_helpers_test.rb → test/controller_helpers_test.rb} +60 -40
- data/test/test/integration_helpers_test.rb +34 -0
- data/test/test_helper.rb +9 -0
- data/test/test_models.rb +8 -6
- metadata +123 -53
- data/gemfiles/Gemfile.rails-3.2.x +0 -31
- data/gemfiles/Gemfile.rails-3.2.x.lock +0 -159
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'devise/strategies/rememberable'
|
2
4
|
require 'devise/hooks/rememberable'
|
3
5
|
require 'devise/hooks/forgetable'
|
4
6
|
|
5
7
|
module Devise
|
6
8
|
module Models
|
7
|
-
# Rememberable manages generating and clearing token for
|
9
|
+
# Rememberable manages generating and clearing token for remembering the user
|
8
10
|
# from a saved cookie. Rememberable also has utility methods for dealing
|
9
11
|
# with serializing the user into the cookie and back from the cookie, trying
|
10
12
|
# to lookup the record based on the saved information.
|
@@ -17,7 +19,7 @@ module Devise
|
|
17
19
|
#
|
18
20
|
# * +remember_for+: the time you want the user will be remembered without
|
19
21
|
# asking for credentials. After this time the user will be blocked and
|
20
|
-
# will have to enter
|
22
|
+
# will have to enter their credentials again. This configuration is also
|
21
23
|
# used to calculate the expires time for the cookie created to remember
|
22
24
|
# the user. By default remember_for is 2.weeks.
|
23
25
|
#
|
@@ -39,46 +41,42 @@ module Devise
|
|
39
41
|
module Rememberable
|
40
42
|
extend ActiveSupport::Concern
|
41
43
|
|
42
|
-
attr_accessor :remember_me
|
44
|
+
attr_accessor :remember_me
|
43
45
|
|
44
46
|
def self.required_fields(klass)
|
45
47
|
[:remember_created_at]
|
46
48
|
end
|
47
49
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period)
|
53
|
-
save(:validate => false) if self.changed?
|
50
|
+
def remember_me!
|
51
|
+
self.remember_token ||= self.class.remember_token if respond_to?(:remember_token)
|
52
|
+
self.remember_created_at ||= Time.now.utc
|
53
|
+
save(validate: false) if self.changed?
|
54
54
|
end
|
55
55
|
|
56
56
|
# If the record is persisted, remove the remember token (but only if
|
57
57
|
# it exists), and save the record without validations.
|
58
58
|
def forget_me!
|
59
59
|
return unless persisted?
|
60
|
-
self.remember_token = nil if respond_to?(:remember_token
|
61
|
-
self.remember_created_at = nil
|
62
|
-
save(:
|
60
|
+
self.remember_token = nil if respond_to?(:remember_token)
|
61
|
+
self.remember_created_at = nil if self.class.expire_all_remember_me_on_sign_out
|
62
|
+
save(validate: false)
|
63
63
|
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
remember_created_at.nil? || (remember_expires_at <= Time.now.utc)
|
65
|
+
def remember_expires_at
|
66
|
+
self.class.remember_for.from_now
|
68
67
|
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
remember_created_at + self.class.remember_for
|
69
|
+
def extend_remember_period
|
70
|
+
self.class.extend_remember_period
|
73
71
|
end
|
74
72
|
|
75
73
|
def rememberable_value
|
76
74
|
if respond_to?(:remember_token)
|
77
75
|
remember_token
|
78
|
-
elsif respond_to?(:authenticatable_salt) && (salt = authenticatable_salt)
|
76
|
+
elsif respond_to?(:authenticatable_salt) && (salt = authenticatable_salt.presence)
|
79
77
|
salt
|
80
78
|
else
|
81
|
-
raise "
|
79
|
+
raise "authenticatable_salt returned nil for the #{self.class.name} model. " \
|
82
80
|
"In order to use rememberable, you must ensure a password is always set " \
|
83
81
|
"or have a remember_token column in your model or implement your own " \
|
84
82
|
"rememberable_value in the model with custom logic."
|
@@ -89,40 +87,71 @@ module Devise
|
|
89
87
|
self.class.rememberable_options
|
90
88
|
end
|
91
89
|
|
92
|
-
|
90
|
+
# A callback initiated after successfully being remembered. This can be
|
91
|
+
# used to insert your own logic that is only run after the user is
|
92
|
+
# remembered.
|
93
|
+
#
|
94
|
+
# Example:
|
95
|
+
#
|
96
|
+
# def after_remembered
|
97
|
+
# self.update_attribute(:invite_code, nil)
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
def after_remembered
|
101
|
+
end
|
102
|
+
|
103
|
+
def remember_me?(token, generated_at)
|
104
|
+
# TODO: Normalize the JSON type coercion along with the Timeoutable hook
|
105
|
+
# in a single place https://github.com/plataformatec/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
|
106
|
+
if generated_at.is_a?(String)
|
107
|
+
generated_at = time_from_json(generated_at)
|
108
|
+
end
|
93
109
|
|
94
|
-
|
95
|
-
|
110
|
+
# The token is only valid if:
|
111
|
+
# 1. we have a date
|
112
|
+
# 2. the current time does not pass the expiry period
|
113
|
+
# 3. the record has a remember_created_at date
|
114
|
+
# 4. the token date is bigger than the remember_created_at
|
115
|
+
# 5. the token matches
|
116
|
+
generated_at.is_a?(Time) &&
|
117
|
+
(self.class.remember_for.ago < generated_at) &&
|
118
|
+
(generated_at > (remember_created_at || Time.now).utc) &&
|
119
|
+
Devise.secure_compare(rememberable_value, token)
|
96
120
|
end
|
97
121
|
|
98
|
-
|
99
|
-
|
100
|
-
def
|
101
|
-
|
122
|
+
private
|
123
|
+
|
124
|
+
def time_from_json(value)
|
125
|
+
if value =~ /\A\d+\.\d+\Z/
|
126
|
+
Time.at(value.to_f)
|
127
|
+
else
|
128
|
+
Time.parse(value) rescue nil
|
129
|
+
end
|
102
130
|
end
|
103
131
|
|
104
132
|
module ClassMethods
|
105
133
|
# Create the cookie key using the record id and remember_token
|
106
134
|
def serialize_into_cookie(record)
|
107
|
-
[record.to_key, record.rememberable_value]
|
135
|
+
[record.to_key, record.rememberable_value, Time.now.utc.to_f.to_s]
|
108
136
|
end
|
109
137
|
|
110
138
|
# Recreate the user based on the stored cookie
|
111
|
-
def serialize_from_cookie(
|
139
|
+
def serialize_from_cookie(*args)
|
140
|
+
id, token, generated_at = *args
|
141
|
+
|
112
142
|
record = to_adapter.get(id)
|
113
|
-
record if record &&
|
114
|
-
Devise.secure_compare(record.rememberable_value, remember_token)
|
143
|
+
record if record && record.remember_me?(token, generated_at)
|
115
144
|
end
|
116
145
|
|
117
146
|
# Generate a token checking if one does not already exist in the database.
|
118
147
|
def remember_token #:nodoc:
|
119
148
|
loop do
|
120
149
|
token = Devise.friendly_token
|
121
|
-
break token unless to_adapter.find_first({ :
|
150
|
+
break token unless to_adapter.find_first({ remember_token: token })
|
122
151
|
end
|
123
152
|
end
|
124
153
|
|
125
|
-
Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options)
|
154
|
+
Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options, :expire_all_remember_me_on_sign_out)
|
126
155
|
end
|
127
156
|
end
|
128
157
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'devise/hooks/timeoutable'
|
2
4
|
|
3
5
|
module Devise
|
4
6
|
module Models
|
5
|
-
# Timeoutable takes care of
|
7
|
+
# Timeoutable takes care of verifying whether a user session has already
|
6
8
|
# expired or not. When a session expires after the configured time, the user
|
7
|
-
# will be asked for credentials again, it means,
|
9
|
+
# will be asked for credentials again, it means, they will be redirected
|
8
10
|
# to the sign in page.
|
9
11
|
#
|
10
12
|
# == Options
|
@@ -26,7 +28,6 @@ module Devise
|
|
26
28
|
|
27
29
|
# Checks whether the user session has expired based on configured time.
|
28
30
|
def timedout?(last_access)
|
29
|
-
return false if remember_exists_and_not_expired?
|
30
31
|
!timeout_in.nil? && last_access && last_access <= timeout_in.ago
|
31
32
|
end
|
32
33
|
|
@@ -36,11 +37,6 @@ module Devise
|
|
36
37
|
|
37
38
|
private
|
38
39
|
|
39
|
-
def remember_exists_and_not_expired?
|
40
|
-
return false unless respond_to?(:remember_created_at) && respond_to?(:remember_expired?)
|
41
|
-
remember_created_at && !remember_expired?
|
42
|
-
end
|
43
|
-
|
44
40
|
module ClassMethods
|
45
41
|
Devise::Models.config(self, :timeout_in)
|
46
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'devise/hooks/trackable'
|
2
4
|
|
3
5
|
module Devise
|
@@ -15,7 +17,7 @@ module Devise
|
|
15
17
|
[:current_sign_in_at, :current_sign_in_ip, :last_sign_in_at, :last_sign_in_ip, :sign_in_count]
|
16
18
|
end
|
17
19
|
|
18
|
-
def update_tracked_fields
|
20
|
+
def update_tracked_fields(request)
|
19
21
|
old_current, new_current = self.current_sign_in_at, Time.now.utc
|
20
22
|
self.last_sign_in_at = old_current || new_current
|
21
23
|
self.current_sign_in_at = new_current
|
@@ -26,9 +28,16 @@ module Devise
|
|
26
28
|
|
27
29
|
self.sign_in_count ||= 0
|
28
30
|
self.sign_in_count += 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def update_tracked_fields!(request)
|
34
|
+
# We have to check if the user is already persisted before running
|
35
|
+
# `save` here because invalid users can be saved if we don't.
|
36
|
+
# See https://github.com/plataformatec/devise/issues/4673 for more details.
|
37
|
+
return if new_record?
|
29
38
|
|
30
|
-
|
31
|
-
|
39
|
+
update_tracked_fields(request)
|
40
|
+
save(validate: false)
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module Models
|
3
5
|
# Validatable creates all needed validations for a user email and password.
|
@@ -10,12 +12,12 @@ module Devise
|
|
10
12
|
# Validatable adds the following options to devise_for:
|
11
13
|
#
|
12
14
|
# * +email_regexp+: the regular expression used to validate e-mails;
|
13
|
-
# * +password_length+: a range expressing password length. Defaults to
|
15
|
+
# * +password_length+: a range expressing password length. Defaults to 6..128.
|
14
16
|
#
|
15
17
|
module Validatable
|
16
18
|
# All validations used by this module.
|
17
|
-
VALIDATIONS = [
|
18
|
-
|
19
|
+
VALIDATIONS = [:validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
20
|
+
:validates_confirmation_of, :validates_length_of].freeze
|
19
21
|
|
20
22
|
def self.required_fields(klass)
|
21
23
|
[]
|
@@ -26,13 +28,18 @@ module Devise
|
|
26
28
|
assert_validations_api!(base)
|
27
29
|
|
28
30
|
base.class_eval do
|
29
|
-
validates_presence_of :email, :
|
30
|
-
|
31
|
-
|
31
|
+
validates_presence_of :email, if: :email_required?
|
32
|
+
if Devise.activerecord51?
|
33
|
+
validates_uniqueness_of :email, allow_blank: true, if: :will_save_change_to_email?
|
34
|
+
validates_format_of :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?
|
35
|
+
else
|
36
|
+
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
|
37
|
+
validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
|
38
|
+
end
|
32
39
|
|
33
|
-
validates_presence_of :password, :
|
34
|
-
validates_confirmation_of :password, :
|
35
|
-
validates_length_of :password, :
|
40
|
+
validates_presence_of :password, if: :password_required?
|
41
|
+
validates_confirmation_of :password, if: :password_required?
|
42
|
+
validates_length_of :password, within: password_length, allow_blank: true
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
data/lib/devise/modules.rb
CHANGED
@@ -1,28 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/core_ext/object/with_options'
|
2
4
|
|
3
|
-
Devise.with_options :
|
5
|
+
Devise.with_options model: true do |d|
|
4
6
|
# Strategies first
|
5
|
-
d.with_options :
|
7
|
+
d.with_options strategy: true do |s|
|
6
8
|
routes = [nil, :new, :destroy]
|
7
|
-
s.add_module :database_authenticatable, :
|
8
|
-
s.add_module :rememberable, :
|
9
|
+
s.add_module :database_authenticatable, controller: :sessions, route: { session: routes }
|
10
|
+
s.add_module :rememberable, no_input: true
|
9
11
|
end
|
10
12
|
|
11
13
|
# Other authentications
|
12
|
-
d.add_module :omniauthable, :
|
14
|
+
d.add_module :omniauthable, controller: :omniauth_callbacks, route: :omniauth_callback
|
13
15
|
|
14
16
|
# Misc after
|
15
17
|
routes = [nil, :new, :edit]
|
16
|
-
d.add_module :recoverable, :
|
17
|
-
d.add_module :registerable, :
|
18
|
+
d.add_module :recoverable, controller: :passwords, route: { password: routes }
|
19
|
+
d.add_module :registerable, controller: :registrations, route: { registration: (routes << :cancel) }
|
18
20
|
d.add_module :validatable
|
19
21
|
|
20
22
|
# The ones which can sign out after
|
21
23
|
routes = [nil, :new]
|
22
|
-
d.add_module :confirmable, :
|
23
|
-
d.add_module :lockable, :
|
24
|
+
d.add_module :confirmable, controller: :confirmations, route: { confirmation: routes }
|
25
|
+
d.add_module :lockable, controller: :unlocks, route: { unlock: routes }
|
24
26
|
d.add_module :timeoutable
|
25
27
|
|
26
28
|
# Stats for last, so we make sure the user is really signed in
|
27
29
|
d.add_module :trackable
|
28
|
-
end
|
30
|
+
end
|
data/lib/devise/omniauth.rb
CHANGED
@@ -1,17 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module OmniAuth
|
3
5
|
module UrlHelpers
|
4
|
-
def
|
6
|
+
def omniauth_authorize_path(resource_or_scope, provider, *args)
|
7
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
8
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def omniauth_authorize_url(resource_or_scope, provider, *args)
|
12
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
13
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_url", *args)
|
5
14
|
end
|
6
15
|
|
7
|
-
def
|
16
|
+
def omniauth_callback_path(resource_or_scope, provider, *args)
|
8
17
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
9
|
-
send("#{scope}
|
18
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_path", *args)
|
10
19
|
end
|
11
20
|
|
12
|
-
def
|
21
|
+
def omniauth_callback_url(resource_or_scope, provider, *args)
|
13
22
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
14
|
-
send("#{scope}
|
23
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_url", *args)
|
15
24
|
end
|
16
25
|
end
|
17
26
|
end
|
data/lib/devise/orm/mongoid.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
ActiveSupport.on_load(:mongoid) do
|
4
|
+
require 'orm_adapter/adapters/mongoid'
|
5
|
+
|
6
|
+
Mongoid::Document::ClassMethods.send :include, Devise::Models
|
7
|
+
end
|
@@ -1,99 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
|
-
|
3
|
-
|
4
|
+
# The +ParameterSanitizer+ deals with permitting specific parameters values
|
5
|
+
# for each +Devise+ scope in the application.
|
6
|
+
#
|
7
|
+
# The sanitizer knows about Devise default parameters (like +password+ and
|
8
|
+
# +password_confirmation+ for the `RegistrationsController`), and you can
|
9
|
+
# extend or change the permitted parameters list on your controllers.
|
10
|
+
#
|
11
|
+
# === Permitting new parameters
|
12
|
+
#
|
13
|
+
# You can add new parameters to the permitted list using the +permit+ method
|
14
|
+
# in a +before_action+ method, for instance.
|
15
|
+
#
|
16
|
+
# class ApplicationController < ActionController::Base
|
17
|
+
# before_action :configure_permitted_parameters, if: :devise_controller?
|
18
|
+
#
|
19
|
+
# protected
|
20
|
+
#
|
21
|
+
# def configure_permitted_parameters
|
22
|
+
# # Permit the `subscribe_newsletter` parameter along with the other
|
23
|
+
# # sign up parameters.
|
24
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Using a block yields an +ActionController::Parameters+ object so you can
|
29
|
+
# permit nested parameters and have more control over how the parameters are
|
30
|
+
# permitted in your controller.
|
31
|
+
#
|
32
|
+
# def configure_permitted_parameters
|
33
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
34
|
+
# user.permit(newsletter_preferences: [])
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
class ParameterSanitizer
|
38
|
+
DEFAULT_PERMITTED_ATTRIBUTES = {
|
39
|
+
sign_in: [:password, :remember_me],
|
40
|
+
sign_up: [:password, :password_confirmation],
|
41
|
+
account_update: [:password, :password_confirmation, :current_password]
|
42
|
+
}
|
4
43
|
|
5
44
|
def initialize(resource_class, resource_name, params)
|
6
|
-
@
|
7
|
-
@resource_name = resource_name
|
45
|
+
@auth_keys = extract_auth_keys(resource_class)
|
8
46
|
@params = params
|
9
|
-
@
|
10
|
-
|
47
|
+
@resource_name = resource_name
|
48
|
+
@permitted = {}
|
11
49
|
|
12
|
-
|
13
|
-
|
14
|
-
@blocks[kind] = block
|
15
|
-
else
|
16
|
-
default_for(kind)
|
50
|
+
DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
|
51
|
+
permit(action, keys: keys)
|
17
52
|
end
|
18
53
|
end
|
19
54
|
|
20
|
-
|
21
|
-
|
22
|
-
|
55
|
+
# Sanitize the parameters for a specific +action+.
|
56
|
+
#
|
57
|
+
# === Arguments
|
58
|
+
#
|
59
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
60
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
61
|
+
#
|
62
|
+
# === Examples
|
63
|
+
#
|
64
|
+
# # Inside the `RegistrationsController#create` action.
|
65
|
+
# resource = build_resource(devise_parameter_sanitizer.sanitize(:sign_up))
|
66
|
+
# resource.save
|
67
|
+
#
|
68
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+ with the permitted
|
69
|
+
# attributes.
|
70
|
+
def sanitize(action)
|
71
|
+
permissions = @permitted[action]
|
72
|
+
|
73
|
+
if permissions.respond_to?(:call)
|
74
|
+
cast_to_hash permissions.call(default_params)
|
75
|
+
elsif permissions.present?
|
76
|
+
cast_to_hash permit_keys(default_params, permissions)
|
23
77
|
else
|
24
|
-
|
78
|
+
unknown_action!(action)
|
25
79
|
end
|
26
80
|
end
|
27
81
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
82
|
+
# Add or remove new parameters to the permitted list of an +action+.
|
83
|
+
#
|
84
|
+
# === Arguments
|
85
|
+
#
|
86
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
87
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
88
|
+
# * +keys:+ - An +Array+ of keys that also should be permitted.
|
89
|
+
# * +except:+ - An +Array+ of keys that shouldn't be permitted.
|
90
|
+
# * +block+ - A block that should be used to permit the action
|
91
|
+
# parameters instead of the +Array+ based approach. The block will be
|
92
|
+
# called with an +ActionController::Parameters+ instance.
|
93
|
+
#
|
94
|
+
# === Examples
|
95
|
+
#
|
96
|
+
# # Adding new parameters to be permitted in the `sign_up` action.
|
97
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
98
|
+
#
|
99
|
+
# # Removing the `password` parameter from the `account_update` action.
|
100
|
+
# devise_parameter_sanitizer.permit(:account_update, except: [:password])
|
101
|
+
#
|
102
|
+
# # Using the block form to completely override how we permit the
|
103
|
+
# # parameters for the `sign_up` action.
|
104
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
105
|
+
# user.permit(:email, :password, :password_confirmation)
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
#
|
109
|
+
# Returns nothing.
|
110
|
+
def permit(action, keys: nil, except: nil, &block)
|
111
|
+
if block_given?
|
112
|
+
@permitted[action] = block
|
113
|
+
end
|
37
114
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
115
|
+
if keys.present?
|
116
|
+
@permitted[action] ||= @auth_keys.dup
|
117
|
+
@permitted[action].concat(keys)
|
118
|
+
end
|
42
119
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
120
|
+
if except.present?
|
121
|
+
@permitted[action] ||= @auth_keys.dup
|
122
|
+
@permitted[action] = @permitted[action] - except
|
123
|
+
end
|
47
124
|
end
|
48
125
|
|
49
|
-
|
50
|
-
permit self.for(:sign_in)
|
51
|
-
end
|
126
|
+
private
|
52
127
|
|
53
|
-
|
54
|
-
|
128
|
+
# Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
|
129
|
+
# that can be used elsewhere.
|
130
|
+
#
|
131
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+.
|
132
|
+
def cast_to_hash(params)
|
133
|
+
# TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
|
134
|
+
params && params.to_h.with_indifferent_access
|
55
135
|
end
|
56
136
|
|
57
|
-
def
|
58
|
-
|
137
|
+
def default_params
|
138
|
+
@params.fetch(@resource_name, {})
|
59
139
|
end
|
60
140
|
|
61
|
-
|
62
|
-
|
63
|
-
# TODO: We do need to flatten so it works with strong_parameters
|
64
|
-
# gem. We should drop it once we move to Rails 4 only support.
|
65
|
-
def permit(keys)
|
66
|
-
default_params.permit(*Array(keys))
|
141
|
+
def permit_keys(parameters, keys)
|
142
|
+
parameters.permit(*keys)
|
67
143
|
end
|
68
144
|
|
69
|
-
|
70
|
-
|
71
|
-
def default_for(kind)
|
72
|
-
@permitted[kind] || raise("No sanitizer provided for #{kind}")
|
73
|
-
end
|
145
|
+
def extract_auth_keys(klass)
|
146
|
+
auth_keys = klass.authentication_keys
|
74
147
|
|
75
|
-
|
76
|
-
if respond_to?(kind, true)
|
77
|
-
send(kind)
|
78
|
-
else
|
79
|
-
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
|
80
|
-
end
|
148
|
+
auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
|
81
149
|
end
|
82
150
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
auth_keys + [:password, :password_confirmation]
|
89
|
-
when :account_update
|
90
|
-
auth_keys + [:password, :password_confirmation, :current_password]
|
91
|
-
end
|
92
|
-
end
|
151
|
+
def unknown_action!(action)
|
152
|
+
raise NotImplementedError, <<-MESSAGE.strip_heredoc
|
153
|
+
"Devise doesn't know how to sanitize parameters for '#{action}'".
|
154
|
+
If you want to define a new set of parameters to be sanitized use the
|
155
|
+
`permit` method first:
|
93
156
|
|
94
|
-
|
95
|
-
|
96
|
-
@resource_class.authentication_keys.keys : @resource_class.authentication_keys
|
157
|
+
devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
|
158
|
+
MESSAGE
|
97
159
|
end
|
98
160
|
end
|
99
161
|
end
|