Module: Authgasm::ActsAsAuthentic::ClassMethods
- Defined in:
- lib/authgasm/acts_as_authentic.rb
Overview
Acts As Authentic
Provides and “acts_as” method to include in your models to help with authentication. See method below.
Instance Method Summary collapse
-
#acts_as_authentic(options = {}) ⇒ Object
Call this method in your model to add in basic authentication madness:.
Instance Method Details
#acts_as_authentic(options = {}) ⇒ Object
Call this method in your model to add in basic authentication madness:
-
Adds various validations for the login field
-
Adds various validations for the password field
-
Handles password encryption
-
Adds usefule methods to dealing with authentication
Methods
For example purposes lets assume you have a User model.
Class method name Description
User.unique_token returns unique token generated by your :crypto_provider
User.crypto_provider The class that you set in your :crypto_provider option
User.forget_all! Resets all records so they will not be remembered on their next visit. Basically makes their invalid
Named Scopes
User.logged_in Find all users who are logged in, based on your :logged_in_timeout option
User.logged_out Same as above, but logged out
Isntace method name
user.password= Method name based on the :password_field option. This is used to set the password. Pass the *raw* password to this
user.confirm_password= Confirms the password, needed to change the password
user.valid_password?(pass) Based on the valid of :password_field. Determines if the password passed is valid. The password could be encrypted or raw.
user.randomize_password! Basically resets the password to a random password using only letters and numbers
user.logged_in? Based on the :logged_in_timeout option. Tells you if the user is logged in or not
user.forget! Changes their remember token, making their invalid.
Options
-
session_class:default: “#nameSession”, the related session class. Used so that you don’t have to repeat yourself here. A lot of the configuration will be based off of the configuration values of this class. -
crypto_provider:default: Authgasm::Sha256CryptoProvider, class that provides Sha256 encryption. What ultimately encrypts your password. -
crypto_provider_type:default: options.respond_to?(:decrypt) ? :encryption : :hash. You can explicitly set this if you wish. Since encryptions and hashes are handled different this is the flag Authgasm uses. -
login_field:default: options.login_field, the name of the field used for logging in -
login_field_type:default: options == :email ? :email : :login, tells authgasm how to validation the field, what regex to use, etc. -
password_field:default: options.password_field, the name of the field to set the password, NOT the field the encrypted password is stored -
crypted_password_field:default: depends on which columns are present, checks: crypted_password, encrypted_password, password_hash, pw_hash, if none are present defaults to crypted_password. This is the name of column that your encrypted password is stored. -
password_salt_field:default: depends on which columns are present, checks: password_salt, pw_salt, salt, if none are present defaults to password_salt. This is the name of the field your salt is stored, only relevant for a hash crypto provider. -
remember_token_field:default: options.remember_token_field, the name of the field your remember token is stored. What the cookie stores so the session can be “remembered” -
logged_in_timeout:default: 10.minutes, this allows you to specify a time the determines if a user is logged in or out. Useful if you want to count how many users are currently logged in. -
session_ids:default: [nil], the sessions that we want to automatically reset when a user is created or updated so you don’t have to worry about this. Set to [] to disable. Should be an array of ids. See Authgasm::Session::Base#initialize for information on ids. The order is important. The first id should be your main session, the session they need to log into first. This is generally nil, meaning so explicitly set id.
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 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 |
# File 'lib/authgasm/acts_as_authentic.rb', line 49 def acts_as_authentic( = {}) # Setup default options [:session_class] ||= "#{name}Session".constantize [:crypto_provider] ||= Sha256CryptoProvider [:crypto_provider_type] ||= [:crypto_provider].respond_to?(:decrypt) ? :encryption : :hash [:login_field] ||= [:session_class].login_field [:login_field_type] ||= [:login_field] == :email ? :email : :login [:password_field] ||= [:session_class].password_field [:crypted_password_field] ||= (columns.include?("crypted_password") && :crypted_password) || (columns.include?("encrypted_password") && :encrypted_password) || (columns.include?("password_hash") && :password_hash) || (columns.include?("pw_hash") && :pw_hash) || :crypted_password [:password_salt_field] ||= (columns.include?("password_salt") && :password_salt) || (columns.include?("pw_salt") && :pw_salt) || (columns.include?("salt") && :salt) || :password_salt [:remember_token_field] ||= [:session_class].remember_token_field [:logged_in_timeout] ||= 10.minutes [:session_ids] ||= [nil] # Validations case [:login_field_type] when :email validates_length_of [:login_field], :within => 6..100 email_name_regex = '[\w\.%\+\-]+' domain_head_regex = '(?:[A-Z0-9\-]+\.)+' domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)' email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i validates_format_of [:login_field], :with => email_regex, :message => "should look like an email address." else validates_length_of [:login_field], :within => 2..100 validates_format_of [:login_field], :with => /\A\w[\w\.\-_@]+\z/, :message => "use only letters, numbers, and .-_@ please." end validates_uniqueness_of [:login_field] validate :validate_password validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count") if column_names.include?("last_click_at") named_scope :logged_in, lambda { {:conditions => ["last_click_at > ?", [:logged_in_timeout].ago]} } named_scope :logged_out, lambda { {:conditions => ["last_click_at <= ?", [:logged_in_timeout].ago]} } end after_create :create_sessions! after_update :update_sessions! # Attributes attr_writer "confirm_#{options[:password_field]}" attr_accessor "tried_to_set_#{options[:password_field]}" attr_protected "tried_to_set_#{options[:password_field]}" # Class methods class_eval " def self.unique_token\n crypto_provider.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)\n end\n \n def self.crypto_provider\n \#{options[:crypto_provider]}\n end\n \n def self.forget_all!\n # Paginate these to save on memory\n records = nil\n i = 0\n begin\n records = find(:all, :limit => 50, :offset => i)\n records.each { |record| records.update_attribute(:\#{options[:remember_token_field]}, unique_token) }\n i += 50\n end while !records.blank?\n end\n end_eval\n \n # Instance methods\n if column_names.include?(\"last_click_at\")\n class_eval <<-\"end_eval\", __FILE__, __LINE__\n def logged_in?\n !last_click_at.nil? && last_click_at > \#{options[:logged_in_timeout].to_i}.seconds.ago\n end\n end_eval\n end\n \n case options[:crypto_provider_type]\n when :hash\n class_eval <<-\"end_eval\", __FILE__, __LINE__\n def \#{options[:password_field]}=(pass)\n return if pass.blank?\n self.tried_to_set_\#{options[:password_field]} = true\n @\#{options[:password_field]} = pass\n self.\#{options[:remember_token_field]} = self.class.unique_token\n self.\#{options[:password_salt_field]} = self.class.unique_token\n self.\#{options[:crypted_password_field]} = crypto_provider.encrypt(@\#{options[:password_field]} + \#{options[:password_salt_field]})\n end\n \n def valid_\#{options[:password_field]}?(attempted_password)\n return false if attempted_password.blank?\n attempted_password == \#{options[:crypted_password_field]} || \#{options[:crypted_password_field]} == crypto_provider.encrypt(attempted_password + \#{options[:password_salt_field]})\n end\n end_eval\n when :encryption\n class_eval <<-\"end_eval\", __FILE__, __LINE__\n def \#{options[:password_field]}=(pass)\n return if pass.blank?\n self.tried_to_set_\#{options[:password_field]} = true\n @\#{options[:password_field]} = pass\n self.\#{options[:remember_token_field]} = self.class.unique_token\n self.\#{options[:crypted_password_field]} = crypto_provider.encrypt(@\#{options[:password_field]})\n end\n \n def valid_\#{options[:password_field]}?(attemtped_password)\n return false if attempted_password.blank?\n attempted_password == \#{options[:crypted_password_field]} || \#{options[:crypted_password_field]} = crypto_provider.decrypt(attempted_password)\n end\n end_eval\n end\n \n class_eval <<-\"end_eval\", __FILE__, __LINE__\n def \#{options[:password_field]}; end\n def confirm_\#{options[:password_field]}; end\n \n def crypto_provider\n self.class.crypto_provider\n end\n \n def forget!\n update_attribute(:\#{options[:remember_token_field]}, self.class.unique_token)\n end\n \n def randomize_\#{options[:password_field]}!\n chars = (\"a\"..\"z\").to_a + (\"A\"..\"Z\").to_a + (\"0\"..\"9\").to_a\n newpass = \"\"\n 1.upto(10) { |i| newpass << chars[rand(chars.size-1)] }\n self.\#{options[:password_field]} = newpass\n self.confirm_\#{options[:password_field]} = newpass\n end\n \n def save_from_session(*args)\n @saving_from_session = true\n result = save(*args)\n @saving_from_session = false\n result\n end\n \n protected\n def create_sessions!\n return if !\#{options[:session_class]}.activated? || \#{options[:session_ids].inspect}.blank?\n \n # We only want to automatically login into the first session, since this is the main session. The other sessions are sessions\n # that need to be created after logging into the main session.\n session_id = \#{options[:session_ids].inspect}.first\n \n # If we are already logged in, ignore this completely. All that we care about is updating ourself.\n next if \#{options[:session_class]}.find(*[session_id].compact)\n \n # Log me in\n args = [self, session_id].compact\n \#{options[:session_class]}.create(*args)\n end\n \n def update_sessions!\n return if @saving_from_session || !\#{options[:session_class]}.activated?\n \n \#{options[:session_ids].inspect}.each do |session_id|\n session = \#{options[:session_class]}.find(*[session_id].compact)\n \n # Ignore if we can't find the session or the session isn't this record\n next if !session || session.record != self\n \n # We know we are logged in and this is our record, update the session\n session.save\n end\n end\n \n def tried_to_set_password?\n tried_to_set_password == true\n end\n \n def validate_password\n if new_record? || tried_to_set_\#{options[:password_field]}?\n if @\#{options[:password_field]}.blank?\n errors.add(:\#{options[:password_field]}, \"can not be blank\")\n else\n errors.add(:confirm_\#{options[:password_field]}, \"did not match\") if @confirm_\#{options[:password_field]} != @\#{options[:password_field]}\n end\n end\n end\n end_eval\nend\n", __FILE__, __LINE__ |