2009-09-17 10:06:46 -04:00
|
|
|
module Devise
|
2009-10-09 07:30:25 -04:00
|
|
|
module Models
|
2009-10-09 08:27:44 -04:00
|
|
|
# Confirmable is responsible to verify if an account is already confirmed to
|
2009-10-13 16:01:42 -04:00
|
|
|
# sign in, and to send emails with confirmation instructions.
|
2009-10-09 08:27:44 -04:00
|
|
|
# Confirmation instructions are sent to the user email after creating a
|
2010-08-24 01:01:14 -04:00
|
|
|
# record and when manually requested by a new confirmation instruction request.
|
2009-10-22 07:49:19 -04:00
|
|
|
#
|
2010-07-15 07:01:31 -04:00
|
|
|
# == Options
|
2009-10-22 07:49:19 -04:00
|
|
|
#
|
2010-07-15 07:01:31 -04:00
|
|
|
# Confirmable adds the following options to devise_for:
|
2009-10-22 07:49:19 -04:00
|
|
|
#
|
2010-07-15 07:01:31 -04:00
|
|
|
# * +confirm_within+: the time you want to allow the user to access his account
|
|
|
|
# before confirming it. After this period, the user access is denied. You can
|
|
|
|
# use this to let your user access some features of your application without
|
|
|
|
# confirming the account, but blocking it after a certain period (ie 7 days).
|
|
|
|
# By default confirm_within is zero, it means users always have to confirm to sign in.
|
|
|
|
#
|
|
|
|
# == Examples
|
2009-10-09 08:27:44 -04:00
|
|
|
#
|
|
|
|
# User.find(1).confirm! # returns true unless it's already confirmed
|
|
|
|
# User.find(1).confirmed? # true/false
|
|
|
|
# User.find(1).send_confirmation_instructions # manually send instructions
|
2010-07-15 07:01:31 -04:00
|
|
|
#
|
2009-10-09 07:30:25 -04:00
|
|
|
module Confirmable
|
2010-02-17 06:35:38 -05:00
|
|
|
extend ActiveSupport::Concern
|
2009-09-17 10:06:46 -04:00
|
|
|
|
2010-02-17 06:35:38 -05:00
|
|
|
included do
|
|
|
|
before_create :generate_confirmation_token, :if => :confirmation_required?
|
|
|
|
after_create :send_confirmation_instructions, :if => :confirmation_required?
|
2009-09-17 10:06:46 -04:00
|
|
|
end
|
|
|
|
|
2009-10-09 07:30:25 -04:00
|
|
|
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
|
|
|
# is already confirmed, add en error to email field
|
|
|
|
def confirm!
|
2009-10-15 15:43:30 -04:00
|
|
|
unless_confirmed do
|
2009-10-22 22:54:42 -04:00
|
|
|
self.confirmation_token = nil
|
|
|
|
self.confirmed_at = Time.now
|
2010-02-16 08:31:49 -05:00
|
|
|
save(:validate => false)
|
2009-10-09 07:30:25 -04:00
|
|
|
end
|
2009-09-17 10:06:46 -04:00
|
|
|
end
|
2009-10-08 18:50:46 -04:00
|
|
|
|
2009-10-09 07:30:25 -04:00
|
|
|
# Verifies whether a user is confirmed or not
|
|
|
|
def confirmed?
|
2010-07-08 02:21:14 -04:00
|
|
|
!!confirmed_at
|
2009-10-08 18:50:46 -04:00
|
|
|
end
|
|
|
|
|
2009-10-09 07:30:25 -04:00
|
|
|
# Send confirmation instructions by email
|
|
|
|
def send_confirmation_instructions
|
2010-07-14 12:03:34 -04:00
|
|
|
generate_confirmation_token! if self.confirmation_token.nil?
|
2010-06-12 14:56:55 -04:00
|
|
|
::Devise.mailer.confirmation_instructions(self).deliver
|
2009-09-17 19:03:38 -04:00
|
|
|
end
|
2009-09-17 18:54:19 -04:00
|
|
|
|
2010-03-28 17:09:28 -04:00
|
|
|
# Resend confirmation token. This method does not need to generate a new token.
|
2010-03-10 10:13:54 -05:00
|
|
|
def resend_confirmation_token
|
2010-03-28 17:09:28 -04:00
|
|
|
unless_confirmed { send_confirmation_instructions }
|
2009-10-07 23:53:04 -04:00
|
|
|
end
|
|
|
|
|
2009-12-20 07:53:53 -05:00
|
|
|
# Overwrites active? from Devise::Models::Activatable for confirmation
|
|
|
|
# by verifying whether an user is active to sign in or not. If the user
|
|
|
|
# is already confirmed, it should never be blocked. Otherwise we need to
|
|
|
|
# calculate if the confirm time has not expired for this user.
|
2009-10-20 19:32:30 -04:00
|
|
|
def active?
|
2010-05-05 17:31:11 -04:00
|
|
|
super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
|
2009-10-20 19:32:30 -04:00
|
|
|
end
|
|
|
|
|
2009-12-20 07:53:53 -05:00
|
|
|
# The message to be shown if the account is inactive.
|
|
|
|
def inactive_message
|
2010-03-10 10:13:54 -05:00
|
|
|
!confirmed? ? :unconfirmed : super
|
2009-12-20 07:53:53 -05:00
|
|
|
end
|
|
|
|
|
2009-12-14 18:30:28 -05:00
|
|
|
# If you don't want confirmation to be sent on create, neither a code
|
|
|
|
# to be generated, call skip_confirmation!
|
|
|
|
def skip_confirmation!
|
2010-07-08 02:21:14 -04:00
|
|
|
self.confirmed_at = Time.now
|
2009-12-14 18:30:28 -05:00
|
|
|
end
|
|
|
|
|
2009-10-20 09:08:40 -04:00
|
|
|
protected
|
2009-10-09 07:30:25 -04:00
|
|
|
|
2009-12-14 18:30:28 -05:00
|
|
|
# Callback to overwrite if confirmation is required or not.
|
|
|
|
def confirmation_required?
|
2010-07-08 02:21:14 -04:00
|
|
|
!confirmed?
|
2009-12-14 18:30:28 -05:00
|
|
|
end
|
|
|
|
|
2009-10-20 19:32:30 -04:00
|
|
|
# Checks if the confirmation for the user is within the limit time.
|
|
|
|
# We do this by calculating if the difference between today and the
|
|
|
|
# confirmation sent date does not exceed the confirm in time configured.
|
|
|
|
# Confirm_in is a model configuration, must always be an integer value.
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-20 19:32:30 -04:00
|
|
|
# Example:
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-30 05:23:47 -04:00
|
|
|
# # confirm_within = 1.day and confirmation_sent_at = today
|
2009-10-20 19:32:30 -04:00
|
|
|
# confirmation_period_valid? # returns true
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-30 05:23:47 -04:00
|
|
|
# # confirm_within = 5.days and confirmation_sent_at = 4.days.ago
|
2009-10-20 19:32:30 -04:00
|
|
|
# confirmation_period_valid? # returns true
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-30 05:23:47 -04:00
|
|
|
# # confirm_within = 5.days and confirmation_sent_at = 5.days.ago
|
2009-10-20 19:32:30 -04:00
|
|
|
# confirmation_period_valid? # returns false
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-30 05:23:47 -04:00
|
|
|
# # confirm_within = 0.days
|
2009-10-20 19:32:30 -04:00
|
|
|
# confirmation_period_valid? # will always return false
|
2009-10-22 22:54:42 -04:00
|
|
|
#
|
2009-10-20 19:32:30 -04:00
|
|
|
def confirmation_period_valid?
|
2009-11-24 08:00:35 -05:00
|
|
|
confirmation_sent_at && confirmation_sent_at.utc >= self.class.confirm_within.ago
|
2009-10-09 07:30:25 -04:00
|
|
|
end
|
|
|
|
|
2009-10-18 07:14:52 -04:00
|
|
|
# Checks whether the record is confirmed or not, yielding to the block
|
|
|
|
# if it's already confirmed, otherwise adds an error to email.
|
2009-10-15 15:43:30 -04:00
|
|
|
def unless_confirmed
|
|
|
|
unless confirmed?
|
|
|
|
yield
|
|
|
|
else
|
2010-02-16 11:00:36 -05:00
|
|
|
self.errors.add(:email, :already_confirmed)
|
2009-10-15 15:43:30 -04:00
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-10-18 07:14:52 -04:00
|
|
|
# Generates a new random token for confirmation, and stores the time
|
|
|
|
# this token is being generated
|
|
|
|
def generate_confirmation_token
|
2009-10-30 05:49:18 -04:00
|
|
|
self.confirmed_at = nil
|
2010-03-29 10:13:19 -04:00
|
|
|
self.confirmation_token = self.class.confirmation_token
|
2009-10-18 07:14:52 -04:00
|
|
|
self.confirmation_sent_at = Time.now.utc
|
|
|
|
end
|
|
|
|
|
2010-07-14 12:03:34 -04:00
|
|
|
def generate_confirmation_token!
|
|
|
|
generate_confirmation_token && save(:validate => false)
|
|
|
|
end
|
|
|
|
|
2009-10-09 07:30:25 -04:00
|
|
|
module ClassMethods
|
|
|
|
# Attempt to find a user by it's email. If a record is found, send new
|
|
|
|
# confirmation instructions to it. If not user is found, returns a new user
|
|
|
|
# with an email not found error.
|
|
|
|
# Options must contain the user email
|
2009-10-10 15:20:23 -04:00
|
|
|
def send_confirmation_instructions(attributes={})
|
2009-11-24 18:35:07 -05:00
|
|
|
confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
|
2010-03-28 16:26:07 -04:00
|
|
|
confirmable.resend_confirmation_token if confirmable.persisted?
|
2009-10-09 07:30:25 -04:00
|
|
|
confirmable
|
|
|
|
end
|
|
|
|
|
|
|
|
# Find a user by it's confirmation token and try to confirm it.
|
2009-10-18 08:16:30 -04:00
|
|
|
# If no user is found, returns a new user with an error.
|
2009-10-09 07:30:25 -04:00
|
|
|
# If the user is already confirmed, create an error for the user
|
2009-10-18 08:16:30 -04:00
|
|
|
# Options must have the confirmation_token
|
2010-03-10 10:13:54 -05:00
|
|
|
def confirm_by_token(confirmation_token)
|
|
|
|
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
|
2010-03-28 16:26:07 -04:00
|
|
|
confirmable.confirm! if confirmable.persisted?
|
2009-10-18 07:14:52 -04:00
|
|
|
confirmable
|
|
|
|
end
|
2009-10-22 17:02:03 -04:00
|
|
|
|
2010-07-18 17:32:56 -04:00
|
|
|
# Generate a token checking if one does not already exist in the database.
|
2010-03-29 10:13:19 -04:00
|
|
|
def confirmation_token
|
2010-07-18 17:32:56 -04:00
|
|
|
generate_token(:confirmation_token)
|
2010-03-29 10:13:19 -04:00
|
|
|
end
|
|
|
|
|
2009-11-22 19:32:54 -05:00
|
|
|
Devise::Models.config(self, :confirm_within)
|
|
|
|
end
|
2009-09-17 10:06:46 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|