Module: Clearance::User

Extended by:
ActiveSupport::Concern
Defined in:
lib/clearance/user.rb

Overview

Required to be included in your configued user class, which is User by default, but can be changed with Configuration#user_model=.

class User
  include Clearance::User

  # ...
end

This will also include methods exposed by your password strategy, which can be configured with Configuration#password_strategy=. By default, this is PasswordStrategies::BCrypt.

Validations

These validations are added to the class that the User module is mixed into.

Callbacks

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#confirmation_tokenString



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#emailString



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#encrypted_passwordString



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#passwordString (readonly)



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#password_changingString



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#remember_tokenString



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

Class Method Details

.authenticateUser?

Finds the user with the given email and authenticates them with the provided password. If the email corresponds to a user and the provided password is correct for that user, this method will return that user. Otherwise it will return nil.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

.find_by_normalized_emailUser?

Finds the user with the given email. The email with be normalized via #normalize_email.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

.normalize_emailString

Normalizes the provided email by downcasing and removing all spaces. This is used by find_by_normalized_email and is also called when validating a user to ensure only normalized emails are stored in the database.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

Instance Method Details

#authenticated?Boolean

Check's the provided password against the user's encrypted password using the configured password strategy. By default, this will be PasswordStrategies::BCrypt#authenticated?, but can be changed with Configuration#password_strategy.

See Also:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#email_optional?false (private)

Always false. Override this method in your user model to allow for other forms of user authentication (username, Facebook, etc).



231
232
233
# File 'lib/clearance/user.rb', line 231

def email_optional?
  false
end

#forgot_password!Boolean

Generates a #confirmation_token for the user, which allows them to reset their password via an email link.

Calling forgot_password! will cause the user model to be saved without validations. Any other changes you made to this user instance will also be persisted, without validation. It is inteded to be called on an instance with no changes (dirty? == false).



173
174
175
176
# File 'lib/clearance/user.rb', line 173

def forgot_password!
  generate_confirmation_token
  save validate: false
end

#generate_confirmation_tokenString (private)

Sets the #confirmation_token on the instance to a new value generated by Token.new. The change is not automatically persisted. If you would like to generate and save in a single method call, use #forgot_password!.



256
257
258
# File 'lib/clearance/user.rb', line 256

def generate_confirmation_token
  self.confirmation_token = Clearance::Token.new
end

#generate_remember_tokenString (private)

Sets the #remember_token on the instance to a new value generated by Token.new. The change is not automatically persisted. If you would like to generate and sace in a single method call, use #reset_remember_token!.



266
267
268
# File 'lib/clearance/user.rb', line 266

def generate_remember_token
  self.remember_token = Clearance::Token.new
end

#normalize_emailString (private)

Sets the email on this instance to the value returned by normalize_email



223
224
225
# File 'lib/clearance/user.rb', line 223

def normalize_email
  self.email = self.class.normalize_email(email)
end

#password=void (readonly)

This method returns an undefined value.

Sets the user's encrypted_password by using the configured Password Strategy's password= method. By default, this will be PasswordStrategies::BCrypt#password=, but can be changed with Configuration#password_strategy.

See Also:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/clearance/user.rb', line 102

module User
  extend ActiveSupport::Concern

  included do
    attr_accessor :password_changing
    attr_reader :password

    include Validations
    include Callbacks
    include password_strategy
  end

  # @api private
  module ClassMethods
    def authenticate(email, password)
      if user = find_by_normalized_email(email)
        if password.present? && user.authenticated?(password)
          return user
        end
      end
    end

    def find_by_normalized_email(email)
      find_by_email normalize_email(email)
    end

    def normalize_email(email)
      email.to_s.downcase.gsub(/\s+/, "")
    end

    private

    def password_strategy
      Clearance.configuration.password_strategy || PasswordStrategies::BCrypt
    end
  end

  # @api private
  module Validations
    extend ActiveSupport::Concern

    included do
      validates :email,
        email: { strict_mode: true },
        presence: true,
        uniqueness: { allow_blank: true },
        unless: :email_optional?

      validates :password, presence: true, unless: :skip_password_validation?
    end
  end

  # @api private
  module Callbacks
    extend ActiveSupport::Concern

    included do
      before_validation :normalize_email
      before_create :generate_remember_token
    end
  end

  # Generates a {#confirmation_token} for the user, which allows them to reset
  # their password via an email link.
  #
  # Calling `forgot_password!` will cause the user model to be saved without
  # validations. Any other changes you made to this user instance will also
  # be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def forgot_password!
    generate_confirmation_token
    save validate: false
  end

  # Generates a new {#remember_token} for the user, which will have the effect
  # of signing all of the user's current sessions out. This is called
  # internally by {Session#sign_out}.
  #
  # Calling `reset_remember_token!` will cause the user model to be saved
  # without validations. Any other changes you made to this user instance will
  # also be persisted, without validation. It is inteded to be called on an
  # instance with no changes (`dirty? == false`).
  #
  # @return [Boolean] Was the save successful?
  def reset_remember_token!
    generate_remember_token
    save validate: false
  end

  # Sets the user's password to the new value, using the `password=` method on
  # the configured password strategy. By default, this is
  # {PasswordStrategies::BCrypt#password=}.
  #
  # This also has the side-effect of blanking the {#confirmation_token} and
  # rotating the `#remember_token`.
  #
  # Validations will be run as part of this update. If the user instance is
  # not valid, the password change will not be persisted, and this method will
  # return `false`.
  #
  # @return [Boolean] Was the save successful?
  def update_password(new_password)
    self.password_changing = true
    self.password = new_password

    if valid?
      self.confirmation_token = nil
      generate_remember_token
    end

    save
  end

  private

  # Sets the email on this instance to the value returned by
  # {.normalize_email}
  #
  # @return [String]
  def normalize_email
    self.email = self.class.normalize_email(email)
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def email_optional?
    false
  end

  # Always false. Override this method in your user model to allow for other
  # forms of user authentication (username, Facebook, etc).
  #
  # @return [false]
  def password_optional?
    false
  end

  # True if {#password_optional?} is true or if the user already has an
  # {#encrypted_password} that is not changing.
  #
  # @return [Boolean]
  def skip_password_validation?
    password_optional? || (encrypted_password.present? && !password_changing)
  end

  # Sets the {#confirmation_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and save in a single method call, use {#forgot_password!}.
  #
  # @return [String] The new confirmation token
  def generate_confirmation_token
    self.confirmation_token = Clearance::Token.new
  end

  # Sets the {#remember_token} on the instance to a new value generated by
  # {Token.new}. The change is not automatically persisted. If you would like
  # to generate and sace in a single method call, use
  # {#reset_remember_token!}.
  #
  # @return [String] The new remember token
  def generate_remember_token
    self.remember_token = Clearance::Token.new
  end

  private_constant :Callbacks, :ClassMethods, :Validations
end

#password_optional?false (private)

Always false. Override this method in your user model to allow for other forms of user authentication (username, Facebook, etc).



239
240
241
# File 'lib/clearance/user.rb', line 239

def password_optional?
  false
end

#reset_remember_token!Boolean

Generates a new #remember_token for the user, which will have the effect of signing all of the user's current sessions out. This is called internally by Session#sign_out.

Calling reset_remember_token! will cause the user model to be saved without validations. Any other changes you made to this user instance will also be persisted, without validation. It is inteded to be called on an instance with no changes (dirty? == false).



188
189
190
191
# File 'lib/clearance/user.rb', line 188

def reset_remember_token!
  generate_remember_token
  save validate: false
end

#skip_password_validation?Boolean (private)

True if #password_optional? is true or if the user already has an #encrypted_password that is not changing.



247
248
249
# File 'lib/clearance/user.rb', line 247

def skip_password_validation?
  password_optional? || (encrypted_password.present? && !password_changing)
end

#update_password(new_password) ⇒ Boolean

Sets the user's password to the new value, using the password= method on the configured password strategy. By default, this is PasswordStrategies::BCrypt#password=.

This also has the side-effect of blanking the #confirmation_token and rotating the #remember_token.

Validations will be run as part of this update. If the user instance is not valid, the password change will not be persisted, and this method will return false.



205
206
207
208
209
210
211
212
213
214
215
# File 'lib/clearance/user.rb', line 205

def update_password(new_password)
  self.password_changing = true
  self.password = new_password

  if valid?
    self.confirmation_token = nil
    generate_remember_token
  end

  save
end