Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

file 148 lines (126 sloc) 4.451 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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
module Thincloud::Authentication
  # Public: This class represents a User identity (name, email, login provider)
  class Identity < ::OmniAuth::Identity::Models::ActiveRecord
    include ActiveModel::ForbiddenAttributesProtection # strong_parameters

    belongs_to :user

    validates :name, presence: true
    validates :email, presence: true, uniqueness: true, format: /@/
    validates :password, presence: { if: :password_required? },
      confirmation: { if: :password_confirmation_required? }

    # Ensure that a `verification_token` exists for new records.
    after_initialize do
      self.verification_token = SecureRandom.urlsafe_base64 if new_record?
      self.resetting_identity_password = false
    end

    # Only validate password if the 'provider' is 'identity'.
    before_validation do
      self.password_digest = 0 unless identity_provider?
    end

    # Public: Use a helpful attribute name when displaying errors.
    def self.human_attribute_name(attr, options={})
      attr == :password_digest ? "Password" : super
    end

    # Public: Find an `Identity` by OmniAuth parameters.
    #
    # omniauth - An instance of `OmniAuth::AuthHash`
    #
    # Returns: An instance of `Identity` or `nil`.
    def self.find_omniauth(omniauth)
      if omniauth["uid"].present?
        find_by_provider_and_uid omniauth["provider"], omniauth["uid"]
      end
    end

    # Public: Mark the `Identity` as having been verified.
    #
    # token - A String containing the `verification_token` to look up.
    #
    # Returns: An instance of the found `Identity`.
    # Raises: ActiveRecord::RecordNotFound if the `token` cannot be retrieved.
    # ActiveRecord::RecordInvalid if the record cannot be saved.
    def self.verify!(token)
      find_by_verification_token!(token).tap do |identity|
        # ensure 'uid' exists, needed for 'identity' provider
        identity.uid = identity.id if identity.uid.blank?
        identity.verification_token = nil
        identity.verified_at = Time.zone.now
        identity.save!
      end
    end

    # Public: Shim to overcome odd behavior seen during testing with SQLite
    def uid
      read_attribute :uid
    end

    # Public: Indicate if the `Identity` has been verified.
    #
    # Returns: Boolean.
    def verified?
      verification_token.blank? && verified_at.present?
    end

    # Public: Apply attributes returned from OmniAuth.
    #
    # omniauth - An instance of `OmniAuth::AuthHash`.
    def apply_omniauth(omniauth)
      info = omniauth["info"]

      user_name = %Q(#{info["first_name"]} #{info["last_name"]})
      user_name.gsub!(/\s+/, " ").strip!

      self.provider = omniauth["provider"]
      self.uid = omniauth["uid"]
      self.name = user_name if self.name.blank?
      self.email = info["email"] if info["email"] && self.email.blank?
      self
    end

    # Public: Generate a password reset token
    #
    # Returns: true
    #
    # Raises: ActiveRecord::RecordInvalid
    def generate_password_reset!
      self.password_reset_token = SecureRandom.urlsafe_base64
      self.password_reset_sent_at = Time.zone.now
      save_with_identity_password_reset!
    end

    # Public: Clear password reset fields, reset password_required? requirement
    #
    # Returns: true
    #
    # Raises: ActiveRecord::RecordInvalid
    def clear_password_reset!
      self.password_reset_token = nil
      self.password_reset_sent_at = nil
      save!
    end

    # Public: Determine if the provider is 'identity'
    #
    # Returns: true or false
    def identity_provider?
      provider == "identity"
    end

    # Public: Determine if the password must be provided
    #
    # Returns: true or false
    def password_required?
      (identity_provider? && check_identity_password?) && (
        new_record? || password_reset_token.present?
      )
    end

    # Public: Determine if the password confirmation must be provided
    #
    # Returns: true or false
    def password_confirmation_required?
      password_required? || (
        password.present? || password_confirmation.present?
      )
    end

    private

    attr_accessor :resetting_identity_password

    def check_identity_password?
      !resetting_identity_password
    end

    def save_with_identity_password_reset!
      self.resetting_identity_password = true
      save!
    ensure
      self.resetting_identity_password = false
    end

  end
end
Something went wrong with that request. Please try again.