lib/models/phone.rb in devise_phone-0.0.16 vs lib/models/phone.rb in devise_phone-0.0.17

- old
+ new

@@ -1,215 +1,114 @@ require "devise_phone/hooks" module Devise module Models - # SmsActivable is responsible to verify if an account is already confirmed to - # sign in, and to send sms with confirmation instructions. - # Confirmation instructions are sent to the user phone after creating a - # record and when manually requested by a new confirmation instruction request. - # - # == Options - # - # Confirmable adds the following options to devise_for: - # - # * +sms_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 0 days, so the user must confirm before entering. - # If you want to allow user to use parts of the site and block others override - # sms_confirmation_required? and check manually on selected pages using the - # require_sms_activated! helper or sms_confirmed? property on record - # - # == Examples - # - # User.find(1).sms_confirm! # returns true unless it's already confirmed - # User.find(1).sms_confirmed? # true/false - # User.find(1).send_sms_token # manually send token - # module Phone extend ActiveSupport::Concern included do - before_create :set_phone_attributes, :if => :phone_verification_needed? - after_create :generate_verification_code_and_send_sms, :if => :phone_verification_needed? + before_create :set_unverified_phone_attributes, :if => :phone_verification_needed? + # after_create :private_generate_verification_code_and_send_sms, :if => :phone_verification_needed? + # before_save :remember_old_phone_number + after_save :private_generate_verification_code_and_send_sms, :if => :regenerate_phone_verification_needed? end - # # Confirm a user by setting it's sms_confirmed_at to actual time. If the user - # # is already confirmed, add en error to email field - # def confirm_sms! - # unless_sms_confirmed do - # self.sms_confirmation_token = nil - # self.sms_confirmed_at = Time.now - # save(:validate => false) - # end - # end - - # # Verifies whether a user is sms-confirmed or not - # def confirmed_sms? - # !!sms_confirmed_at - # end - - # Send confirmation token by sms def generate_verification_code_and_send_sms - if(self.phone_number?) - self.phone_verification_code = generate_phone_verification_code - ::Devise.sms_sender.send_sms_verification_code_to(self) + if(phone_verification_needed?) + private_generate_verification_code_and_send_sms + end + self.save! + end + + def verify_phone_number_with_code_entered(code_entered) + if phone_verification_needed? && (code_entered == self.phone_verification_code) + mark_phone_as_verified! + true else - # self.errors.add(:sms_confirmation_token, :no_phone_associated) false end end - # # Resend sms confirmation token. This method does not need to generate a new token. - # def resend_sms_token - # unless_sms_confirmed { send_sms_token } - # end + private - # Overwrites active? from Devise::Models::Activatable for sms confirmation - # by verifying whether a 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. + def private_generate_verification_code_and_send_sms + self.phone_verification_code = generate_phone_verification_code + set_unverified_phone_attributes + if phone_number.present? + send_sms_verification_code + end + end - # def active? - # !sms_confirmation_required? || confirmed_sms? || confirmation_sms_period_valid? - # end - # # The message to be shown if the account is inactive. - # def inactive_message - # !confirmed_sms? ? I18n.t(:"devise.sms_activations.unconfirmed_sms") : super - # end + def mark_phone_as_verified! + update!(phone_number_verified: true, + phone_verification_code: nil, + phone_verification_code_sent_at: nil, + phone_verified_at: DateTime.now) + end - # # If you don't want confirmation to be sent on create, neither a code - # # to be generated, call skip_sms_confirmation! - # def skip_sms_confirmation! - # self.sms_confirmed_at = Time.now - # end - - protected - - # Callback to overwrite if an sms confirmation is required or not. + # check if phone verification is needed and set errors here def phone_verification_needed? - phone_number.present? && !phone_number_verified + if phone_number.blank? + self.errors.add(:phone_verification_code, :empty_phone_number_field) + false + elsif phone_number_verified + self.errors.add(:phone_verification_code, :phone_verification_not_needed) + false + else + true + end end - # def sms_confirmation_required? - # !confirmed_sms? - # end + def regenerate_phone_verification_needed? + if phone_number.present? + if phone_number_changed? + true + else + false + end + # self.errors.add(:phone_verification_code, :empty_phone_number_field) + # false + else + false + end + end - # 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. - # - # Example: - # - # # sms_confirm_within = 1.day and sms_confirmation_sent_at = today - # confirmation_period_valid? # returns true - # - # # sms_confirm_within = 5.days and sms_confirmation_sent_at = 4.days.ago - # confirmation_period_valid? # returns true - # - # # sms_confirm_within = 5.days and sms_confirmation_sent_at = 5.days.ago - # confirmation_period_valid? # returns false - # - # # sms_confirm_within = 0.days - # confirmation_period_valid? # will always return false - # - # def confirmation_sms_period_valid? - # sms_confirmation_sent_at && sms_confirmation_sent_at.utc >= self.class.sms_confirm_within.ago - # end - - # # Checks whether the record is confirmed or not, yielding to the block - # # if it's already confirmed, otherwise adds an error to email. - # def unless_sms_confirmed - # unless confirmed_sms? - # yield - # else - # self.errors.add(:sms_confirmation_token, :sms_already_confirmed) - # false - # end - # end - - # Generates a new random token for confirmation, and stores the time - # this token is being generated - def set_phone_attributes - + # set attributes to user indicating the phone number is unverified + def set_unverified_phone_attributes self.phone_number_verified = false self.phone_verification_code_sent_at = DateTime.now self.phone_verified_at = nil # removes all white spaces, hyphens, and parenthesis - self.phone_number.gsub!(/[\s\-\(\)]+/, '') + if self.phone_number + self.phone_number.gsub!(/[\s\-\(\)]+/, '') + end end + # return 4 digits random code 0-9 def generate_phone_verification_code - # begin - verification_code = SecureRandom.hex(3) - # end while self.class.exists?(phone_verification_code: verification_code) + verification_code = SecureRandom.random_number(10 ** 4).to_s.rjust(4,'0') verification_code end - # def generate_sms_token! - # generate_sms_token && save(:validate => false) - # end + # sends a message to number indicated in the secrets.yml + def send_sms_verification_code + number_to_send_to = self.phone_number + verification_code = self.phone_verification_code - module ClassMethods - # # Attempt to find a user by it's email. If a record is found, send a new - # # sms token instructions to it. If not user is found, returns a new user - # # with an email not found error. - # # Options must contain the user email - # def send_sms_token(attributes={}) - # sms_confirmable = find_or_initialize_with_errors(sms_confirmation_keys, attributes, :not_found) - # sms_confirmable.resend_sms_token if sms_confirmable.persisted? - # sms_confirmable - # end + twilio_sid = Rails.application.config.twilio[:sid] + twilio_token = Rails.application.config.twilio[:token] + twilio_phone_number = Rails.application.config.twilio[:phone_number] + twilio_message_body = I18n.t("devise.phone.message_body", :verification_code => verification_code) - # # Find a user by it's sms confirmation token and try to confirm it. - # # If no user is found, returns a new user with an error. - # # If the user is already confirmed, create an error for the user - # # Options must have the sms_confirmation_token - # def confirm_by_sms_token(sms_confirmation_token) - # sms_confirmable = find_or_initialize_with_error_by(:sms_confirmation_token, sms_confirmation_token) - # sms_confirmable.confirm_sms! if sms_confirmable.persisted? - # sms_confirmable - # end - - def mark_phone_as_verified! - update!(phone_number_verified: true, - phone_verification_code: nil, - phone_verification_code_sent_at: nil, - phone_verified_at: DateTime.now) - end - - def verify_phone_number_with_code_entered(code_entered) - if self.phone_verification_code == code_entered - mark_phone_as_verified! - end - end - - def send_verification_code - self.set_phone_attributes - if self.save! - send_sms_for_phone_verification - end - end - - # # Generates a small token that can be used conveniently on SMS's. - # # The token is 5 chars long and uppercased. - - # def generate_small_token(column) - # loop do - # token = Devise.friendly_token[0,5].upcase - # break token unless to_adapter.find_first({ column => token }) - # end - # end - - # # Generate an sms token checking if one does not already exist in the database. - # def sms_confirmation_token - # generate_small_token(:sms_confirmation_token) - # end - - # Devise::Models.config(self, :sms_confirm_within, :sms_confirmation_keys) + @twilio_client = Twilio::REST::Client.new twilio_sid, twilio_token + + @twilio_client.account.messages.create( + :from => "+1#{twilio_phone_number}", + :to => number_to_send_to, + :body => twilio_message_body + ) end + end end end