/
config.rb
230 lines (218 loc) · 16 KB
/
config.rb
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
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
module Authlogic
module ORMAdapters
module ActiveRecordAdapter
module ActsAsAuthentic
# = Config
#
# Allows you to set various configuration when calling acts_as_authentic. Pass your configuration like the following:
#
# class User < ActiveRecord::Base
# acts_as_authentic :my_option => "my value"
# end
#
# === Class Methods
#
# * <tt>acts_as_authentic_config</tt> - returns a hash of the acts_as_authentic configuration, including the defaults
#
# === General Options
#
# * <tt>session_class</tt> - default: "#{name}Session",
# This is the related session class. A lot of the configuration will be based off of the configuration values of this class.
#
# * <tt>crypto_provider</tt> - default: Authlogic::CryptoProviders::Sha512,
# This is the class that provides your encryption. By default Authlogic provides its own crypto provider that uses Sha512 encrypton.
#
# * <tt>transition_from_crypto_provider</tt> - default: nil,
# This will transition your users to a new encryption algorithm. Let's say you are using Sha1 and you want to transition to Sha512. Just set the
# :crypto_provider option to Authlogic::CryptoProviders::Sha512 and then set this option to Authlogic::CryptoProviders::Sha1. Every time a user
# logs in their password will be resaved with the new algorithm and all new registrations will use the new algorithm as well.
#
# * <tt>act_like_restful_authentication</tt> - default: false,
# If you are migrating from restful_authentication you will want to set this to true, this way your users will still be able to log in and it will seems as
# if nothing has changed. If you don't do this none of your users will be able to log in. If you are starting a new project I do not recommend enabling this
# as the password encryption algorithm used in restful_authentication (Sha1) is not as secure as the one used in authlogic (Sha512). IF you REALLY want to be secure
# checkout Authlogic::CryptoProviders::BCrypt.
#
# * <tt>transition_from_restful_authentication</tt> - default: false,
# This works just like :transition_from_crypto_provider, but it makes some special exceptions so that your users will transition from restful_authentication, since
# restful_authentication does things a little different than Authlogic.
#
# * <tt>login_field</tt> - default: :login, :username, or :email, depending on which column is present, if none are present defaults to :login
# The name of the field used for logging in. Only specify if you aren't using any of the defaults.
#
# * <tt>login_field_type</tt> - default: options[:login_field] == :email ? :email : :login,
# Tells authlogic how to validation the field, what regex to use, etc. If the field name is email it will automatically use :email,
# otherwise it uses :login.
#
# * <tt>password_field</tt> - default: :password,
# This is the name of the field to set the password, *NOT* the field the encrypted password is stored. Defaults the what the configuration
#
# * <tt>crypted_password_field</tt> - default: :crypted_password, :encrypted_password, :password_hash, :pw_hash, depends on which columns are present, if none are present defaults to nil
# The name of the database field where your encrypted password is stored.
#
# * <tt>password_salt_field</tt> - default: :password_salt, :pw_salt, or :salt, depending on which column is present, defaults to :password_salt if none are present,
# This is the name of the field in your database that stores your password salt.
#
# * <tt>email_field</tt> - default: :email, depending on if it is present, if :email is not present defaults to nil
# The name of the field used to store the email address. Only specify this if you arent using this as your :login_field.
#
# * <tt>single_access_token_field</tt> - default: :single_access_token, :feed_token, or :feeds_token, depending on which column is present, if none are present defaults to nil
# This is the name of the field to login with single access, mainly used for private feed access. Only specify if the name of the field is different
# then the defaults. See the "Single Access" section in the README for more details on how single access works.
#
# * <tt>change_single_access_token_with_password</tt> - default: false,
# When a user changes their password do you want the single access token to change as well? That's what this configuration option is all about.
#
# * <tt>perishable_token_field</tt> - default: :perishable_token, :password_reset_token, :pw_reset_token, :reset_password_token, or :reset_pw_token, depending on which column is present, if none are present defaults to nil
# This is the name of the field in your database that stores your perishable token. The token you should use to confirm your users or allow a password reset. Authlogic takes care
# of maintaining this for you and making sure it changes when needed. Use this token for whatever you want, but keep in mind it is temporary, hence the term "perishable".
#
# * <tt>perishable_token_valid_for</tt> - default: 10.minutes,
# Authlogic gives you a sepcial method for finding records by the perishable token (see Authlogic::ORMAdapters::ActiveRecordAdapter::ActcsAsAuthentic::Perishability). In this method
# it checks for the age of the token. If the token is older than whatever you specify here, a record will NOT be returned. This way the tokens are perishable, thus making this system much
# more secure.
#
# * <tt>persistence_field</tt> - default: :persistence_token, :remember_token, or :cookie_tokien, depending on which column is present,
# defaults to :persistence_token if none are present,
# This is the name of the field your persistence token is stored. The persistence token is a unique token that is stored in the users cookie and
# session. This way you have complete control of when sessions expire and you don't have to change passwords to expire sessions. This also
# ensures that stale sessions can not be persisted. By stale, I mean sessions that are logged in using an outdated password.
#
# * <tt>logged_in_timeout</tt> - default: 10.minutes,
# This is a nifty feature to tell if a user is logged in or not. It's based on activity. So if the user in inactive longer than
# the value passed here they are assumed "logged out". This uses the last_request_at field, this field must be present for this option to take effect.
#
# * <tt>session_ids</tt> - 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 the Authlogic::Session documentation 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. When you don't specify an id
# in your session you are really just inexplicitly saying you want to use the id of nil.
#
# === Validation Options
#
# * <tt>validate_fields</tt> - default: true,
# Tells Authlogic if it should validate ANY of the fields: login_field, email_field, and password_field. If set to false, no validations will be set for any of these fields.
#
# * <tt>validate_login_field</tt> - default: true,
# Tells authlogic if it should validate the :login_field. If set to false, no validations will be set for this field at all.
#
# * <tt>validate_email_field</tt> - default: true,
# Tells Authlogic if it should validate the email field. If set to false, no validations will be set for this field at all.
#
# * <tt>validate_password_field</tt> - default: :password,
# Tells authlogic if it should validate the :password_field. If set to false, no validations will be set for this field at all.
#
# * <tt>scope</tt> - default: nil,
# This scopes validations. If all of your users belong to an account you might want to scope everything to the account. Just pass :account_id
#
# * <tt>validation_options</tt> - default: {},
# Options to pass to ALL validations. These are the options ActiveRecord supplies with their validation methods, see the ActiveRecord documentation for more details.
#
# * <tt>login_field_validation_options</tt> - default: {},
# The same as :validation_options but these are only applied to validations that pertain to the :login_field
#
# * <tt>login_field_validates_length_of_options</tt> - default: :login_field_type == :email ? {:within => 6..100} : {:within => 2..100},
# These options are applied to the validates_length_of call for the :login_field
#
# * <tt>login_field_validates_format_of_options</tt> - default: :login_field_type == :email ? {:with => standard_email_regex, :message => "should look like an email address."} : {:with => standard_login_regex, :message => "should use only letters, numbers, spaces, and .-_@ please."},
# These options are applied to the validates_format_of call for the :login_field
#
# * <tt>login_field_validates_uniqueness_of_options</tt> - default: {:allow_blank => true},
# These options are applied to the validates_uniqueness_of call for the :login_field, the :allow_blank => true just prevents the error message when you have options login fields
# such as an OpenID field. The other validations will make sure the field is not actaully blank.
#
# * <tt>password_field_validation_options</tt> - default: {},
# The same as :validation_options but these are only applied to validations that pertain to the :password_field
#
# * <tt>password_field_validates_presence_of_options</tt> - default: {:on => :create},
# These options are applied to the validates_presence_of call for the :password_field
#
# * <tt>login_field_validates_confirmation_of_options</tt> - default: {},
# These options are applied to the validates_confirmation_of call for the :password_field
#
# * <tt>email_field_validation_options</tt> - default: {},
# The same as :validation_options but these are only applied to validations that pertain to the :email_field
#
# * <tt>email_field_validates_length_of_options</tt> - default: same as :login_field if :login_field_type == :email,
# These options are applied to the validates_length_of call for the :email_field
#
# * <tt>email_field_validates_format_of_options</tt> - default: same as :login_field if :login_field_type == :email,
# These options are applied to the validates_format_of call for the :email_field
#
# * <tt>email_field_validates_uniqueness_of_options</tt> - default: same as :login_field if :login_field_type == :email,
# These options are applied to the validates_uniqueness_of call for the :email_field
module Config
def first_column_to_exist(*columns_to_check) # :nodoc:
columns_to_check.each { |column_name| return column_name.to_sym if column_names.include?(column_name.to_s) }
columns_to_check.first ? columns_to_check.first.to_sym : nil
end
def acts_as_authentic_with_config(options = {})
# Stop all configuration if the DB is not set up
begin
column_names
rescue Exception
return
end
# Base configuration
options[:session_class] ||= "#{name}Session"
options[:crypto_provider] ||= CryptoProviders::Sha512
options[:login_field] ||= first_column_to_exist(:login, :username, :email)
options[:login_field_type] ||= options[:login_field] == :email ? :email : :login
options[:password_field] ||= :password
options[:crypted_password_field] ||= first_column_to_exist(:crypted_password, :encrypted_password, :password_hash, :pw_hash)
options[:password_salt_field] ||= first_column_to_exist(:password_salt, :pw_salt, :salt)
options[:email_field] = first_column_to_exist(nil, :email) unless options.key?(:email_field)
options[:email_field] = nil if options[:email_field] == options[:login_field]
options[:persistence_token_field] ||= options[:remember_token_field] || first_column_to_exist(:persistence_token, :remember_token, :cookie_token)
options[:single_access_token_field] ||= first_column_to_exist(nil, :single_access_token, :feed_token, :feeds_token)
options[:perishable_token_field] ||= options[:password_reset_token_field] || first_column_to_exist(nil, :perishable_token, :password_reset_token, :pw_reset_token, :reset_password_token, :reset_pw_token, :activation_token)
options[:perishable_token_valid_for] ||= 10.minutes
options[:perishable_token_valid_for] = options[:perishable_token_valid_for].to_i
options[:logged_in_timeout] ||= 10.minutes
options[:logged_in_timeout] = options[:logged_in_timeout].to_i
options[:session_ids] ||= [nil]
# Validation configuration
options[:validate_fields] = true unless options.key?(:validate_fields)
options[:validate_login_field] = true unless options.key?(:validate_login_field)
options[:validate_password_field] = true unless options.key?(:validate_password_field)
options[:validate_email_field] = true unless options.key?(:validate_email_field)
options[:validation_options] ||= {}
[:login, :password, :email].each do |field_name|
field_key = "#{field_name}_field_validation_options".to_sym
options[field_key] = options[:validation_options].merge(options[field_key] || {})
validation_types = field_name == :password ? [:presence, :confirmation] : [:length, :format, :uniqueness]
validation_types.each do |validation_type|
validation_key = "#{field_name}_field_validates_#{validation_type}_of_options".to_sym
options[validation_key] = options[field_key].merge(options[validation_key] || {})
end
end
if options[:scope]
options[:login_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
options[:email_field_validates_uniqueness_of_options][:scope] ||= options[:scope]
end
if options[:act_like_restful_authentication] || options[:transition_from_restful_authentication]
crypto_provider_key = options[:act_like_restful_authentication] ? :crypto_provider : :transition_from_crypto_provider
options[crypto_provider_key] = CryptoProviders::Sha1
if !defined?(REST_AUTH_SITE_KEY) || REST_AUTH_SITE_KEY.nil?
class_eval("::REST_AUTH_SITE_KEY = nil") unless defined?(REST_AUTH_SITE_KEY)
options[crypto_provider_key].stretches = 1
end
end
class_eval <<-"end_eval", __FILE__, __LINE__
def self.acts_as_authentic_config
#{options.inspect}
end
end_eval
acts_as_authentic_without_config(options)
end
end
end
end
end
end
ActiveRecord::Base.class_eval do
class << self
include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::Config
alias_method_chain :acts_as_authentic, :config
end
end