devise 2.1.4 → 2.2.0.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.
- data/.travis.yml +26 -0
- data/CHANGELOG.rdoc +29 -10
- data/CONTRIBUTING.md +14 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +68 -77
- data/README.md +15 -9
- data/app/controllers/devise/omniauth_callbacks_controller.rb +1 -1
- data/app/controllers/devise/passwords_controller.rb +9 -0
- data/app/controllers/devise/registrations_controller.rb +17 -5
- data/app/controllers/devise/sessions_controller.rb +3 -3
- data/app/controllers/devise_controller.rb +3 -11
- data/app/views/devise/confirmations/new.html.erb +1 -1
- data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
- data/app/views/devise/passwords/edit.html.erb +1 -1
- data/app/views/devise/passwords/new.html.erb +1 -1
- data/app/views/devise/registrations/edit.html.erb +5 -1
- data/app/views/devise/registrations/new.html.erb +1 -1
- data/app/views/devise/sessions/new.html.erb +1 -1
- data/app/views/devise/unlocks/new.html.erb +1 -1
- data/config/locales/en.yml +2 -0
- data/gemfiles/Gemfile.rails-3.1.x +1 -3
- data/gemfiles/Gemfile.rails-3.1.x.lock +9 -12
- data/lib/devise.rb +12 -7
- data/lib/devise/controllers/helpers.rb +16 -3
- data/lib/devise/mailers/helpers.rb +14 -8
- data/lib/devise/models/authenticatable.rb +14 -9
- data/lib/devise/models/confirmable.rb +36 -3
- data/lib/devise/models/database_authenticatable.rb +2 -1
- data/lib/devise/models/lockable.rb +6 -2
- data/lib/devise/models/recoverable.rb +2 -2
- data/lib/devise/models/token_authenticatable.rb +12 -0
- data/lib/devise/models/trackable.rb +1 -1
- data/lib/devise/models/validatable.rb +1 -1
- data/lib/devise/param_filter.rb +2 -1
- data/lib/devise/rails/routes.rb +11 -11
- data/lib/devise/strategies/database_authenticatable.rb +1 -1
- data/lib/devise/test_helpers.rb +3 -2
- data/lib/devise/time_inflector.rb +14 -0
- data/lib/devise/version.rb +1 -1
- data/lib/generators/active_record/devise_generator.rb +5 -1
- data/lib/generators/mongoid/devise_generator.rb +0 -3
- data/lib/generators/templates/README +5 -1
- data/lib/generators/templates/devise.rb +12 -4
- data/lib/generators/templates/markerb/confirmation_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 -1
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +1 -1
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +5 -0
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -1
- data/test/controllers/internal_helpers_test.rb +6 -0
- data/test/controllers/sessions_controller_test.rb +43 -1
- data/test/devise_test.rb +12 -1
- data/test/generators/active_record_generator_test.rb +7 -1
- data/test/integration/authenticatable_test.rb +4 -4
- data/test/integration/confirmable_test.rb +44 -0
- data/test/integration/database_authenticatable_test.rb +17 -15
- data/test/integration/http_authenticatable_test.rb +3 -3
- data/test/integration/lockable_test.rb +18 -0
- data/test/integration/omniauthable_test.rb +2 -2
- data/test/integration/recoverable_test.rb +43 -6
- data/test/integration/registerable_test.rb +34 -11
- data/test/mailers/confirmation_instructions_test.rb +7 -0
- data/test/models/authenticatable_test.rb +1 -7
- data/test/models/confirmable_test.rb +35 -1
- data/test/models/database_authenticatable_test.rb +49 -24
- data/test/models/lockable_test.rb +13 -3
- data/test/models/serializable_test.rb +2 -1
- data/test/models_test.rb +1 -22
- data/test/orm/mongoid.rb +2 -3
- data/test/rails_app/app/controllers/application_controller.rb +1 -0
- data/test/rails_app/app/mailers/users/mailer.rb +6 -1
- data/test/rails_app/app/mongoid/admin.rb +4 -2
- data/test/rails_app/app/mongoid/shim.rb +3 -3
- data/test/rails_app/app/mongoid/user.rb +2 -2
- data/test/rails_app/config/initializers/devise.rb +2 -2
- data/test/rails_app/lib/shared_user.rb +1 -1
- data/test/support/helpers.rb +2 -2
- data/test/support/integration.rb +4 -3
- data/test/test_helpers_test.rb +19 -2
- data/test/test_models.rb +27 -0
- metadata +31 -29
- data/test/indifferent_hash.rb +0 -33
@@ -5,14 +5,14 @@ class Devise::SessionsController < DeviseController
|
|
5
5
|
|
6
6
|
# GET /resource/sign_in
|
7
7
|
def new
|
8
|
-
resource = build_resource(nil, :unsafe => true)
|
8
|
+
self.resource = build_resource(nil, :unsafe => true)
|
9
9
|
clean_up_passwords(resource)
|
10
10
|
respond_with(resource, serialize_options(resource))
|
11
11
|
end
|
12
12
|
|
13
13
|
# POST /resource/sign_in
|
14
14
|
def create
|
15
|
-
resource = warden.authenticate!(auth_options)
|
15
|
+
self.resource = warden.authenticate!(auth_options)
|
16
16
|
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
17
17
|
sign_in(resource_name, resource)
|
18
18
|
respond_with resource, :location => after_sign_in_path_for(resource)
|
@@ -22,7 +22,7 @@ class Devise::SessionsController < DeviseController
|
|
22
22
|
def destroy
|
23
23
|
redirect_path = after_sign_out_path_for(resource_name)
|
24
24
|
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
25
|
-
set_flash_message :notice, :signed_out if signed_out
|
25
|
+
set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
|
26
26
|
|
27
27
|
# We actually need to hardcode this as Rails default responder doesn't
|
28
28
|
# support returning empty response on GET request
|
@@ -10,7 +10,7 @@ class DeviseController < Devise.parent_controller.constantize
|
|
10
10
|
helper_method *helpers
|
11
11
|
|
12
12
|
prepend_before_filter :assert_is_devise_resource!
|
13
|
-
respond_to
|
13
|
+
respond_to :html if mimes_for_respond_to.empty?
|
14
14
|
|
15
15
|
# Gets the actual resource stored in the instance variable
|
16
16
|
def resource
|
@@ -72,7 +72,7 @@ This may happen for two reasons:
|
|
72
72
|
|
73
73
|
2) You are testing a Devise controller bypassing the router.
|
74
74
|
If so, you can explicitly tell Devise which mapping to use:
|
75
|
-
|
75
|
+
|
76
76
|
@request.env["devise.mapping"] = Devise.mappings[:user]
|
77
77
|
|
78
78
|
MESSAGE
|
@@ -168,7 +168,7 @@ MESSAGE
|
|
168
168
|
options[:default] = Array(options[:default]).unshift(kind.to_sym)
|
169
169
|
options[:resource_name] = resource_name
|
170
170
|
options = devise_i18n_options(options) if respond_to?(:devise_i18n_options, true)
|
171
|
-
message = I18n.t("#{resource_name}.#{kind}", options)
|
171
|
+
message = I18n.t("#{options[:resource_name]}.#{kind}", options)
|
172
172
|
flash[key] = message if message.present?
|
173
173
|
end
|
174
174
|
|
@@ -181,12 +181,4 @@ MESSAGE
|
|
181
181
|
format.any(*navigational_formats, &block)
|
182
182
|
end
|
183
183
|
end
|
184
|
-
|
185
|
-
def request_format
|
186
|
-
@request_format ||= request.format.try(:ref)
|
187
|
-
end
|
188
|
-
|
189
|
-
def is_navigational_format?
|
190
|
-
Devise.navigational_formats.include?(request.format.try(:ref))
|
191
|
-
end
|
192
184
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<p>Hello <%= @resource.email %>!</p>
|
2
2
|
|
3
|
-
<p>Your account has been locked due to an excessive
|
3
|
+
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
|
4
4
|
|
5
5
|
<p>Click the link below to unlock your account:</p>
|
6
6
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<%= f.hidden_field :reset_password_token %>
|
6
6
|
|
7
7
|
<div><%= f.label :password, "New password" %><br />
|
8
|
-
<%= f.password_field :password %></div>
|
8
|
+
<%= f.password_field :password, :autofocus => true %></div>
|
9
9
|
|
10
10
|
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
|
11
11
|
<%= f.password_field :password_confirmation %></div>
|
@@ -4,7 +4,11 @@
|
|
4
4
|
<%= devise_error_messages! %>
|
5
5
|
|
6
6
|
<div><%= f.label :email %><br />
|
7
|
-
<%= f.email_field :email %></div>
|
7
|
+
<%= f.email_field :email, :autofocus => true %></div>
|
8
|
+
|
9
|
+
<% if resource.class.reconfirmable && resource.unconfirmed_email.present? %>
|
10
|
+
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
|
11
|
+
<% end %>
|
8
12
|
|
9
13
|
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
|
10
14
|
<%= f.password_field :password, :autocomplete => "off" %></div>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
4
4
|
<div><%= f.label :email %><br />
|
5
|
-
<%= f.email_field :email %></div>
|
5
|
+
<%= f.email_field :email, :autofocus => true %></div>
|
6
6
|
|
7
7
|
<div><%= f.label :password %><br />
|
8
8
|
<%= f.password_field :password %></div>
|
data/config/locales/en.yml
CHANGED
@@ -10,6 +10,7 @@ en:
|
|
10
10
|
not_saved:
|
11
11
|
one: "1 error prohibited this %{resource} from being saved:"
|
12
12
|
other: "%{count} errors prohibited this %{resource} from being saved:"
|
13
|
+
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
13
14
|
|
14
15
|
devise:
|
15
16
|
failure:
|
@@ -17,6 +18,7 @@ en:
|
|
17
18
|
unauthenticated: 'You need to sign in or sign up before continuing.'
|
18
19
|
unconfirmed: 'You have to confirm your account before continuing.'
|
19
20
|
locked: 'Your account is locked.'
|
21
|
+
not_found_in_database: 'Invalid email or password.'
|
20
22
|
invalid: 'Invalid email or password.'
|
21
23
|
invalid_token: 'Invalid authentication token.'
|
22
24
|
timeout: 'Your session expired, please sign in again to continue.'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
devise (2.1.
|
4
|
+
devise (2.1.2)
|
5
5
|
bcrypt-ruby (~> 3.0)
|
6
6
|
orm_adapter (~> 0.1)
|
7
7
|
railties (~> 3.1)
|
@@ -40,9 +40,7 @@ GEM
|
|
40
40
|
multi_json (~> 1.0)
|
41
41
|
addressable (2.2.7)
|
42
42
|
arel (2.2.3)
|
43
|
-
bcrypt-ruby (3.
|
44
|
-
bson (1.5.2)
|
45
|
-
bson_ext (1.3.1)
|
43
|
+
bcrypt-ruby (3.0.1)
|
46
44
|
builder (3.0.0)
|
47
45
|
columnize (0.3.6)
|
48
46
|
erubis (2.7.0)
|
@@ -64,12 +62,12 @@ GEM
|
|
64
62
|
mime-types (1.18)
|
65
63
|
mocha (0.10.4)
|
66
64
|
metaclass (~> 0.0.1)
|
67
|
-
|
68
|
-
bson (>= 1.3.1)
|
69
|
-
mongoid (2.4.4)
|
65
|
+
mongoid (3.0.12)
|
70
66
|
activemodel (~> 3.1)
|
71
|
-
|
67
|
+
moped (~> 1.1)
|
68
|
+
origin (~> 1.0)
|
72
69
|
tzinfo (~> 0.3.22)
|
70
|
+
moped (1.2.9)
|
73
71
|
multi_json (1.3.4)
|
74
72
|
multipart-post (1.1.5)
|
75
73
|
nokogiri (1.5.0)
|
@@ -87,6 +85,7 @@ GEM
|
|
87
85
|
omniauth-openid (1.0.1)
|
88
86
|
omniauth (~> 1.0)
|
89
87
|
rack-openid (~> 1.3.1)
|
88
|
+
origin (1.0.10)
|
90
89
|
orm_adapter (0.4.0)
|
91
90
|
polyglot (0.3.3)
|
92
91
|
rack (1.3.6)
|
@@ -137,7 +136,7 @@ GEM
|
|
137
136
|
polyglot
|
138
137
|
polyglot (>= 0.3.1)
|
139
138
|
tzinfo (0.3.33)
|
140
|
-
warden (1.2.
|
139
|
+
warden (1.2.1)
|
141
140
|
rack (>= 1.0)
|
142
141
|
webrat (0.7.2)
|
143
142
|
nokogiri (>= 1.2.0)
|
@@ -150,12 +149,10 @@ PLATFORMS
|
|
150
149
|
DEPENDENCIES
|
151
150
|
activerecord-jdbc-adapter
|
152
151
|
activerecord-jdbcsqlite3-adapter
|
153
|
-
bson_ext (~> 1.3.0)
|
154
152
|
devise!
|
155
153
|
jruby-openssl
|
156
154
|
mocha
|
157
|
-
|
158
|
-
mongoid (~> 2.0)
|
155
|
+
mongoid (~> 3.0)
|
159
156
|
omniauth (~> 1.0.0)
|
160
157
|
omniauth-facebook
|
161
158
|
omniauth-oauth2 (~> 1.0.0)
|
data/lib/devise.rb
CHANGED
@@ -6,11 +6,12 @@ require 'set'
|
|
6
6
|
require 'securerandom'
|
7
7
|
|
8
8
|
module Devise
|
9
|
-
autoload :Delegator,
|
10
|
-
autoload :FailureApp,
|
11
|
-
autoload :OmniAuth,
|
12
|
-
autoload :ParamFilter,
|
13
|
-
autoload :TestHelpers,
|
9
|
+
autoload :Delegator, 'devise/delegator'
|
10
|
+
autoload :FailureApp, 'devise/failure_app'
|
11
|
+
autoload :OmniAuth, 'devise/omniauth'
|
12
|
+
autoload :ParamFilter, 'devise/param_filter'
|
13
|
+
autoload :TestHelpers, 'devise/test_helpers'
|
14
|
+
autoload :TimeInflector, 'devise/time_inflector'
|
14
15
|
|
15
16
|
module Controllers
|
16
17
|
autoload :Helpers, 'devise/controllers/helpers'
|
@@ -86,7 +87,7 @@ module Devise
|
|
86
87
|
# an one (and only one) @ exists in the given string. This is mainly
|
87
88
|
# to give user feedback and not to assert the e-mail validity.
|
88
89
|
mattr_accessor :email_regexp
|
89
|
-
@@email_regexp = /\A[
|
90
|
+
@@email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
90
91
|
|
91
92
|
# Range validation for password length
|
92
93
|
mattr_accessor :password_length
|
@@ -104,6 +105,10 @@ module Devise
|
|
104
105
|
mattr_accessor :allow_unconfirmed_access_for
|
105
106
|
@@allow_unconfirmed_access_for = 0.days
|
106
107
|
|
108
|
+
# Time interval the confirmation token is valid. nil = unlimited
|
109
|
+
mattr_accessor :confirm_within
|
110
|
+
@@confirm_within = nil
|
111
|
+
|
107
112
|
# Defines which key will be used when confirming an account.
|
108
113
|
mattr_accessor :confirmation_keys
|
109
114
|
@@confirmation_keys = [ :email ]
|
@@ -199,7 +204,7 @@ module Devise
|
|
199
204
|
# to provide custom routes.
|
200
205
|
mattr_accessor :router_name
|
201
206
|
@@router_name = nil
|
202
|
-
|
207
|
+
|
203
208
|
# Set the omniauth path prefix so it can be overriden when
|
204
209
|
# Devise is used in a mountable engine
|
205
210
|
mattr_accessor :omniauth_path_prefix
|
@@ -162,8 +162,8 @@ module Devise
|
|
162
162
|
users.any?
|
163
163
|
end
|
164
164
|
|
165
|
-
# Returns and delete the url stored in the session for
|
166
|
-
# for giving redirect backs after sign up:
|
165
|
+
# Returns and delete (if it's navigational format) the url stored in the session for
|
166
|
+
# the given scope. Useful for giving redirect backs after sign up:
|
167
167
|
#
|
168
168
|
# Example:
|
169
169
|
#
|
@@ -171,7 +171,12 @@ module Devise
|
|
171
171
|
#
|
172
172
|
def stored_location_for(resource_or_scope)
|
173
173
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
174
|
-
|
174
|
+
|
175
|
+
if is_navigational_format?
|
176
|
+
session.delete("#{scope}_return_to")
|
177
|
+
else
|
178
|
+
session["#{scope}_return_to"]
|
179
|
+
end
|
175
180
|
end
|
176
181
|
|
177
182
|
# The scope root url to be used when he's signed in. By default, it first
|
@@ -262,6 +267,14 @@ module Devise
|
|
262
267
|
super # call the default behaviour which resets the session
|
263
268
|
end
|
264
269
|
|
270
|
+
def request_format
|
271
|
+
@request_format ||= request.format.try(:ref)
|
272
|
+
end
|
273
|
+
|
274
|
+
def is_navigational_format?
|
275
|
+
Devise.navigational_formats.include?(request_format)
|
276
|
+
end
|
277
|
+
|
265
278
|
private
|
266
279
|
|
267
280
|
def expire_devise_cached_variables!
|
@@ -28,8 +28,9 @@ module Devise
|
|
28
28
|
def headers_for(action)
|
29
29
|
headers = {
|
30
30
|
:subject => translate(devise_mapping, action),
|
31
|
-
:from => mailer_sender(devise_mapping),
|
32
31
|
:to => resource.email,
|
32
|
+
:from => mailer_sender(devise_mapping),
|
33
|
+
:reply_to => mailer_reply_to(devise_mapping),
|
33
34
|
:template_path => template_paths
|
34
35
|
}
|
35
36
|
|
@@ -37,16 +38,21 @@ module Devise
|
|
37
38
|
headers.merge!(resource.headers_for(action))
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
headers[:reply_to] = headers[:from]
|
42
|
-
end
|
43
|
-
|
41
|
+
@email = headers[:to]
|
44
42
|
headers
|
45
43
|
end
|
46
44
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
45
|
+
def mailer_reply_to(mapping)
|
46
|
+
mailer_sender(mapping, :reply_to)
|
47
|
+
end
|
48
|
+
|
49
|
+
def mailer_from(mapping)
|
50
|
+
mailer_sender(mapping, :from)
|
51
|
+
end
|
52
|
+
|
53
|
+
def mailer_sender(mapping, sender = :from)
|
54
|
+
if default_params[sender].present?
|
55
|
+
default_params[sender]
|
50
56
|
elsif Devise.mailer_sender.is_a?(Proc)
|
51
57
|
Devise.mailer_sender.call(mapping.name)
|
52
58
|
else
|
@@ -164,11 +164,15 @@ module Devise
|
|
164
164
|
end
|
165
165
|
|
166
166
|
def downcase_keys
|
167
|
-
self.class.case_insensitive_keys.each { |k|
|
167
|
+
self.class.case_insensitive_keys.each { |k| apply_to_attribute_or_variable(k, :downcase!) }
|
168
168
|
end
|
169
169
|
|
170
170
|
def strip_whitespace
|
171
|
-
self.class.strip_whitespace_keys.each { |k|
|
171
|
+
self.class.strip_whitespace_keys.each { |k| apply_to_attribute_or_variable(k, :strip!) }
|
172
|
+
end
|
173
|
+
|
174
|
+
def apply_to_attribute_or_variable(attr, method)
|
175
|
+
(self[attr] || send(attr)).try(method)
|
172
176
|
end
|
173
177
|
|
174
178
|
module ClassMethods
|
@@ -199,26 +203,27 @@ module Devise
|
|
199
203
|
# it may be wrapped as well. For instance, database authenticatable
|
200
204
|
# provides a `find_for_database_authentication` that wraps a call to
|
201
205
|
# this method. This allows you to customize both database authenticatable
|
202
|
-
# or the whole authenticate stack by customize `find_for_authentication.`
|
206
|
+
# or the whole authenticate stack by customize `find_for_authentication.`
|
203
207
|
#
|
204
208
|
# Overwrite to add customized conditions, create a join, or maybe use a
|
205
209
|
# namedscope to filter records while authenticating.
|
206
210
|
# Example:
|
207
211
|
#
|
208
|
-
# def self.find_for_authentication(
|
209
|
-
#
|
212
|
+
# def self.find_for_authentication(conditions={})
|
213
|
+
# conditions[:active] = true
|
214
|
+
# super
|
210
215
|
# end
|
211
216
|
#
|
212
217
|
# Finally, notice that Devise also queries for users in other scenarios
|
213
218
|
# besides authentication, for example when retrieving an user to send
|
214
219
|
# an e-mail for password reset. In such cases, find_for_authentication
|
215
220
|
# is not called.
|
216
|
-
def find_for_authentication(
|
217
|
-
find_first_by_auth_conditions(
|
221
|
+
def find_for_authentication(conditions)
|
222
|
+
find_first_by_auth_conditions(conditions)
|
218
223
|
end
|
219
224
|
|
220
|
-
def find_first_by_auth_conditions(
|
221
|
-
to_adapter.find_first
|
225
|
+
def find_first_by_auth_conditions(conditions)
|
226
|
+
to_adapter.find_first devise_param_filter.filter(conditions)
|
222
227
|
end
|
223
228
|
|
224
229
|
# Find an initialize a record setting an error if it can't be found.
|
@@ -19,6 +19,8 @@ module Devise
|
|
19
19
|
# db field to be setup (t.reconfirmable in migrations). Until confirmed new email is
|
20
20
|
# stored in unconfirmed email column, and copied to email column on successful
|
21
21
|
# confirmation.
|
22
|
+
# * +confirm_within+: the time before a sent confirmation token becomes invalid.
|
23
|
+
# You can use this to force the user to confirm within a set period of time.
|
22
24
|
#
|
23
25
|
# == Examples
|
24
26
|
#
|
@@ -28,6 +30,7 @@ module Devise
|
|
28
30
|
#
|
29
31
|
module Confirmable
|
30
32
|
extend ActiveSupport::Concern
|
33
|
+
include ActionView::Helpers::DateHelper
|
31
34
|
|
32
35
|
included do
|
33
36
|
before_create :generate_confirmation_token, :if => :confirmation_required?
|
@@ -47,6 +50,12 @@ module Devise
|
|
47
50
|
# add errors
|
48
51
|
def confirm!
|
49
52
|
pending_any_confirmation do
|
53
|
+
if confirmation_period_expired?
|
54
|
+
self.errors.add(:email, :confirmation_period_expired,
|
55
|
+
:period => Devise::TimeInflector.time_ago_in_words(self.class.confirm_within.ago))
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
50
59
|
self.confirmation_token = nil
|
51
60
|
self.confirmed_at = Time.now.utc
|
52
61
|
|
@@ -83,7 +92,10 @@ module Devise
|
|
83
92
|
|
84
93
|
# Resend confirmation token. This method does not need to generate a new token.
|
85
94
|
def resend_confirmation_token
|
86
|
-
pending_any_confirmation
|
95
|
+
pending_any_confirmation do
|
96
|
+
self.confirmation_token = nil if confirmation_period_expired?
|
97
|
+
send_confirmation_instructions
|
98
|
+
end
|
87
99
|
end
|
88
100
|
|
89
101
|
# Overwrites active_for_authentication? for confirmation
|
@@ -156,9 +168,25 @@ module Devise
|
|
156
168
|
confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
|
157
169
|
end
|
158
170
|
|
171
|
+
# Checks if the user confirmation happens before the token becomes invalid
|
172
|
+
# Examples:
|
173
|
+
#
|
174
|
+
# # confirm_within = 3.days and confirmation_sent_at = 2.days.ago
|
175
|
+
# confirmation_period_expired? # returns false
|
176
|
+
#
|
177
|
+
# # confirm_within = 3.days and confirmation_sent_at = 4.days.ago
|
178
|
+
# confirmation_period_expired? # returns true
|
179
|
+
#
|
180
|
+
# # confirm_within = nil
|
181
|
+
# confirmation_period_expired? # will always return false
|
182
|
+
#
|
183
|
+
def confirmation_period_expired?
|
184
|
+
self.class.confirm_within && (Time.now > self.confirmation_sent_at + self.class.confirm_within )
|
185
|
+
end
|
186
|
+
|
159
187
|
# Checks whether the record requires any confirmation.
|
160
188
|
def pending_any_confirmation
|
161
|
-
if !confirmed? || pending_reconfirmation?
|
189
|
+
if (!confirmed? || pending_reconfirmation?)
|
162
190
|
yield
|
163
191
|
else
|
164
192
|
self.errors.add(:email, :already_confirmed)
|
@@ -177,6 +205,11 @@ module Devise
|
|
177
205
|
generate_confirmation_token && save(:validate => false)
|
178
206
|
end
|
179
207
|
|
208
|
+
def after_password_reset
|
209
|
+
super
|
210
|
+
confirm! unless confirmed?
|
211
|
+
end
|
212
|
+
|
180
213
|
def postpone_email_change_until_confirmation
|
181
214
|
@reconfirmation_required = true
|
182
215
|
self.unconfirmed_email = self.email
|
@@ -230,7 +263,7 @@ module Devise
|
|
230
263
|
find_or_initialize_with_errors(unconfirmed_required_attributes, unconfirmed_attributes, :not_found)
|
231
264
|
end
|
232
265
|
|
233
|
-
Devise::Models.config(self, :allow_unconfirmed_access_for, :confirmation_keys, :reconfirmable)
|
266
|
+
Devise::Models.config(self, :allow_unconfirmed_access_for, :confirmation_keys, :reconfirmable, :confirm_within)
|
234
267
|
end
|
235
268
|
end
|
236
269
|
end
|