authlogic 3.4.0 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4fed624511b6b7a6b441cb6dd3147085b19ffb04
4
- data.tar.gz: 9b7d99ff708b9f25edb9abdae86e854f19fc47e6
3
+ metadata.gz: 565581e21dba66d898a0aab8b407f73338a21b31
4
+ data.tar.gz: c9ba53aa14afd2a419f003791181f49fbacaa230
5
5
  SHA512:
6
- metadata.gz: 53b498bb6fd6de0e49988fac47604ec34ffe5fb2beacb2520450e512133c1e7dd4cd70c91373414baa9b6cb4d4098e01921719b8a2e1e8d00ead21a3c8d8a9e8
7
- data.tar.gz: 158dcd58ebf39d0c24806178c709344f8b12e85b6ad58fbb67d0f12103343ce9c6b2ab2045f0a76aa8c8acb1e6c6057626f44191cee63522f8a263ca7080c487
6
+ metadata.gz: fa27f90194dfe0df4e786238be81a7c0479fc0c8d5ddcff0612e23240ba17143efaa6f4a2aaa93bb9f61a87369e22ef811e048fbc99b0cd0fc4a12dee4082325
7
+ data.tar.gz: 5e55ec2fd8877e5800ca3b860273e5088423e0924fc94bdd5669d144e48444e55fe2e433808c18d513265e5838ec44eb47c06a8783cc7751c1835aa197ff73af
@@ -1,6 +1,6 @@
1
1
  = Authlogic
2
2
 
3
- ** Please note the latest version is compatible with rails 3.2 only. Please see the rails2 branch for Rails 2 compatibility.
3
+ ** Authlogic plans to support rails 3 and 4 for the foreseeable future
4
4
 
5
5
  Authlogic is a clean, simple, and unobtrusive ruby authentication solution.
6
6
 
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "authlogic"
6
- s.version = "3.4.0"
6
+ s.version = "3.4.1"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Ben Johnson"]
9
9
  s.email = ["bjohnson@binarylogic.com"]
@@ -62,7 +62,7 @@ module Authlogic
62
62
  # merge options into it. Checkout the convenience function merge_validates_format_of_email_field_options to merge
63
63
  # options.</b>
64
64
  #
65
- # * <tt>Default:</tt> {:with => Authlogic::Regex.email, :message => lambda {I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}}
65
+ # * <tt>Default:</tt> {:with => Authlogic::Regex.email, :message => Proc.new {I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}}
66
66
  # * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
67
67
  def validates_format_of_email_field_options(value = nil)
68
68
  rw_config(:validates_format_of_email_field_options, value, {:with => Authlogic::Regex.email, :message => Proc.new{I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}})
@@ -90,21 +90,19 @@ module Authlogic
90
90
  end
91
91
 
92
92
  # This method allows you to find a record with the given login. If you notice, with Active Record you have the
93
- # validates_uniqueness_of validation function. They give you a :case_sensitive option. I handle this in the same
94
- # manner that they handle that. If you are using the login field and set false for the :case_sensitive option in
95
- # validates_uniqueness_of_login_field_options this method will modify the query to look something like:
93
+ # UniquenessValidator class. They give you a :case_sensitive option. I handle this in the same
94
+ # manner that they handle that. If you are using the login field, set false for the :case_sensitive option in
95
+ # validates_uniqueness_of_login_field_options and the column doesn't have a case-insensitive collation,
96
+ # this method will modify the query to look something like:
96
97
  #
97
- # where("LOWER(#{quoted_table_name}.#{login_field}) = ?", login.downcase).first
98
+ # "LOWER(#{quoted_table_name}.#{login_field}) = LOWER(#{login})"
98
99
  #
99
- # If you don't specify this it calls the good old find_by_* method:
100
+ # If you don't specify this it just uses a regular case-sensitive search (with the binary modifier if necessary):
100
101
  #
101
- # find_by_login(login)
102
+ # "BINARY #{login_field} = #{login}"
102
103
  #
103
104
  # The above also applies for using email as your login, except that you need to set the :case_sensitive in
104
105
  # validates_uniqueness_of_email_field_options to false.
105
- #
106
- # The only reason I need to do the above is for Postgres and SQLite since they perform case sensitive searches with the
107
- # find_by_* methods.
108
106
  def find_by_smart_case_login_field(login)
109
107
  if login_field
110
108
  find_with_case(login_field, login, validates_uniqueness_of_login_field_options[:case_sensitive] != false)
@@ -115,11 +113,14 @@ module Authlogic
115
113
 
116
114
  private
117
115
  def find_with_case(field, value, sensitivity = true)
118
- if sensitivity
119
- send("find_by_#{field}", value)
116
+ relation = if not sensitivity
117
+ connection.case_insensitive_comparison(arel_table, field.to_s, columns_hash[field.to_s], value)
120
118
  else
121
- where("LOWER(#{quoted_table_name}.#{field}) = ?", value.mb_chars.downcase).first
119
+ value = connection.case_sensitive_modifier(value) if value
120
+ relation = arel_table[field.to_s].eq(value)
122
121
  end
122
+
123
+ where(relation).first
123
124
  end
124
125
  end
125
126
 
@@ -52,7 +52,7 @@ module Authlogic
52
52
 
53
53
  # Class level methods for the perishable token
54
54
  module ClassMethods
55
- # Use this methdo to find a record with a perishable token. This method does 2 things for you:
55
+ # Use this method to find a record with a perishable token. This method does 2 things for you:
56
56
  #
57
57
  # 1. It ignores blank tokens
58
58
  # 2. It enforces the perishable_token_valid_for configuration option.
@@ -0,0 +1,63 @@
1
+ module Authlogic
2
+ module ControllerAdapters
3
+ # Adapter for authlogic to make it function as a Rack middleware.
4
+ # First you'll have write your own Rack adapter where you have to set your cookie domain.
5
+ #
6
+ # class YourRackAdapter < Authlogic::ControllerAdapters::RackAdapter
7
+ # def cookie_domain
8
+ # 'your_cookie_domain_here.com'
9
+ # end
10
+ # end
11
+ #
12
+ # Next you need to set up a rack middleware like this:
13
+ #
14
+ # class AuthlogicMiddleware
15
+ # def initialize(app)
16
+ # @app = app
17
+ # end
18
+ #
19
+ # def call(env)
20
+ # YourRackAdapter.new(env)
21
+ # @app.call(env)
22
+ # end
23
+ # end
24
+ #
25
+ # And that is all! Now just load this middleware into rack:
26
+ #
27
+ # use AuthlogicMiddleware
28
+ #
29
+ # Authlogic will expect a User and a UserSession object to be present:
30
+ #
31
+ # class UserSession < Authlogic::Session::Base
32
+ # # Authlogic options go here
33
+ # end
34
+ #
35
+ # class User < ActiveRecord::Base
36
+ # acts_as_authentic
37
+ # end
38
+ #
39
+ class RackAdapter < AbstractAdapter
40
+
41
+ def initialize(env)
42
+ # We use the Rack::Request object as the controller object.
43
+ # For this to work, we have to add some glue.
44
+ request = Rack::Request.new(env)
45
+
46
+ request.instance_eval do
47
+ def request; self; end
48
+ def remote_ip; self.ip; end
49
+ end
50
+
51
+ super(request)
52
+ Authlogic::Session::Base.controller = self
53
+ end
54
+
55
+ # Rack Requests stores cookies with not just the value, but also with flags and expire information in the hash.
56
+ # Authlogic does not like this, so we drop everything except the cookie value
57
+ def cookies
58
+ controller.cookies.map{|key, value_hash| {key => value_hash[:value]} }.inject(:merge) || {}
59
+ end
60
+ end
61
+ end
62
+
63
+ end
@@ -1,8 +1,4 @@
1
- begin
2
- require "bcrypt"
3
- rescue LoadError
4
- "sudo gem install bcrypt-ruby"
5
- end
1
+ require "bcrypt"
6
2
 
7
3
  module Authlogic
8
4
  module CryptoProviders
@@ -21,16 +17,16 @@ module Authlogic
21
17
  #
22
18
  # Benchmark.bm(18) do |x|
23
19
  # x.report("BCrypt (cost = 10:") { 100.times { BCrypt::Password.create("mypass", :cost => 10) } }
24
- # x.report("BCrypt (cost = 2:") { 100.times { BCrypt::Password.create("mypass", :cost => 2) } }
20
+ # x.report("BCrypt (cost = 4:") { 100.times { BCrypt::Password.create("mypass", :cost => 4) } }
25
21
  # x.report("Sha512:") { 100.times { Digest::SHA512.hexdigest("mypass") } }
26
22
  # x.report("Sha1:") { 100.times { Digest::SHA1.hexdigest("mypass") } }
27
23
  # end
28
24
  #
29
- # user system total real
30
- # BCrypt (cost = 10): 10.780000 0.060000 10.840000 ( 11.100289)
31
- # BCrypt (cost = 2): 0.180000 0.000000 0.180000 ( 0.181914)
32
- # Sha512: 0.000000 0.000000 0.000000 ( 0.000829)
33
- # Sha1: 0.000000 0.000000 0.000000 ( 0.000395)
25
+ # user system total real
26
+ # BCrypt (cost = 10): 37.360000 0.020000 37.380000 ( 37.558943)
27
+ # BCrypt (cost = 4): 0.680000 0.000000 0.680000 ( 0.677460)
28
+ # Sha512: 0.000000 0.000000 0.000000 ( 0.000672)
29
+ # Sha1: 0.000000 0.000000 0.000000 ( 0.000454)
34
30
  #
35
31
  # You can play around with the cost to get that perfect balance
36
32
  # between performance and security. A default cost of 10 is the
@@ -50,24 +46,30 @@ module Authlogic
50
46
  class BCrypt
51
47
  class << self
52
48
  # This is the :cost option for the BCrpyt library. The higher the cost the more secure it is and the longer is take the generate a hash. By default this is 10.
53
- # Set this to whatever you want, play around with it to get that perfect balance between security and performance.
49
+ # Set this to any value >= the engine's minimum (currently 4), play around with it to get that perfect balance between security and performance.
54
50
  def cost
55
51
  @cost ||= 10
56
52
  end
57
- attr_writer :cost
58
-
53
+
54
+ def cost=(val)
55
+ if val < ::BCrypt::Engine::MIN_COST
56
+ raise ArgumentError.new("Authlogic's bcrypt cost cannot be set below the engine's min cost (#{::BCrypt::Engine::MIN_COST})")
57
+ end
58
+ @cost = val
59
+ end
60
+
59
61
  # Creates a BCrypt hash for the password passed.
60
62
  def encrypt(*tokens)
61
63
  ::BCrypt::Password.create(join_tokens(tokens), :cost => cost)
62
64
  end
63
-
65
+
64
66
  # Does the hash match the tokens? Uses the same tokens that were used to encrypt.
65
67
  def matches?(hash, *tokens)
66
68
  hash = new_from_hash(hash)
67
69
  return false if hash.blank?
68
70
  hash == join_tokens(tokens)
69
71
  end
70
-
72
+
71
73
  # This method is used as a flag to tell Authlogic to "resave" the password upon a successful login, using the new cost
72
74
  def cost_matches?(hash)
73
75
  hash = new_from_hash(hash)
@@ -77,12 +79,12 @@ module Authlogic
77
79
  hash.cost == cost
78
80
  end
79
81
  end
80
-
82
+
81
83
  private
82
84
  def join_tokens(tokens)
83
85
  tokens.flatten.join
84
86
  end
85
-
87
+
86
88
  def new_from_hash(hash)
87
89
  begin
88
90
  ::BCrypt::Password.new(hash)
@@ -1,8 +1,4 @@
1
- begin
2
- require "scrypt"
3
- rescue LoadError
4
- "sudo gem install scrypt"
5
- end
1
+ require "scrypt"
6
2
 
7
3
  module Authlogic
8
4
  module CryptoProviders
@@ -67,7 +63,7 @@ module Authlogic
67
63
  def join_tokens(tokens)
68
64
  tokens.flatten.join
69
65
  end
70
-
66
+
71
67
  def new_from_hash(hash)
72
68
  begin
73
69
  ::SCrypt::Password.new(hash)
@@ -9,7 +9,7 @@ module Authlogic
9
9
  klass.extend ClassMethods
10
10
  klass.send(:include, InstanceMethods)
11
11
  end
12
-
12
+
13
13
  module ClassMethods
14
14
  # How to name the attributes of Authlogic, works JUST LIKE ActiveRecord, but instead it uses the following
15
15
  # namespace:
@@ -20,24 +20,14 @@ module Authlogic
20
20
  options[:default] ||= attribute_key_name.to_s.humanize
21
21
  I18n.t("attributes.#{name.underscore}.#{attribute_key_name}", options)
22
22
  end
23
-
23
+
24
24
  # How to name the class, works JUST LIKE ActiveRecord, except it uses the following namespace:
25
25
  #
26
26
  # authlogic.models.user_session
27
27
  def human_name(*args)
28
28
  I18n.t("models.#{name.underscore}", {:count => 1, :default => name.humanize})
29
29
  end
30
-
31
- # For rails < 2.3, mispelled
32
- def self_and_descendents_from_active_record
33
- [self]
34
- end
35
-
36
- # For rails >= 2.3, mispelling fixed
37
- def self_and_descendants_from_active_record
38
- [self]
39
- end
40
-
30
+
41
31
  # For rails >= 3.0
42
32
  def model_name
43
33
  if defined?(::ActiveModel)
@@ -55,7 +45,7 @@ module Authlogic
55
45
  ancestors.select { |x| x.respond_to?(:model_name) }
56
46
  end
57
47
  end
58
-
48
+
59
49
  module InstanceMethods
60
50
  # Don't use this yourself, this is to just trick some of the helpers since this is the method it calls.
61
51
  def new_record?
@@ -69,7 +59,7 @@ module Authlogic
69
59
  def destroyed?
70
60
  record.nil?
71
61
  end
72
-
62
+
73
63
  def to_key
74
64
  new_record? ? nil : record.to_key
75
65
  end
@@ -8,7 +8,7 @@ module Authlogic
8
8
  # last_request_at Updates every time the user logs in, either by explicitly logging in, or logging in by cookie, session, or http auth
9
9
  # current_login_at Updates with the current time when an explicit login is made.
10
10
  # last_login_at Updates with the value of current_login_at before it is reset.
11
- # current_login_ip Updates with the request remote_ip when an explicit login is made.
11
+ # current_login_ip Updates with the request ip when an explicit login is made.
12
12
  # last_login_ip Updates with the value of current_login_ip before it is reset.
13
13
  module MagicColumns
14
14
  def self.included(klass)
@@ -21,7 +21,7 @@ module Authlogic
21
21
  before_save :set_last_request_at, :if => :set_last_request_at?
22
22
  end
23
23
  end
24
-
24
+
25
25
  # Configuration for the magic columns feature.
26
26
  module Config
27
27
  # Every time a session is found the last_request_at field for that record is updatd with the current time, if that field exists.
@@ -36,7 +36,7 @@ module Authlogic
36
36
  end
37
37
  alias_method :last_request_at_threshold=, :last_request_at_threshold
38
38
  end
39
-
39
+
40
40
  # The methods available for an Authlogic::Session::Base object that make up the magic columns feature.
41
41
  module InstanceMethods
42
42
  private
@@ -46,22 +46,22 @@ module Authlogic
46
46
  attempted_record.failed_login_count += 1
47
47
  end
48
48
  end
49
-
49
+
50
50
  def update_info
51
51
  record.login_count = (record.login_count.blank? ? 1 : record.login_count + 1) if record.respond_to?(:login_count)
52
52
  record.failed_login_count = 0 if record.respond_to?(:failed_login_count)
53
-
53
+
54
54
  if record.respond_to?(:current_login_at)
55
55
  record.last_login_at = record.current_login_at if record.respond_to?(:last_login_at)
56
56
  record.current_login_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
57
57
  end
58
-
58
+
59
59
  if record.respond_to?(:current_login_ip)
60
60
  record.last_login_ip = record.current_login_ip if record.respond_to?(:last_login_ip)
61
- record.current_login_ip = controller.request.remote_ip
61
+ record.current_login_ip = controller.request.ip
62
62
  end
63
63
  end
64
-
64
+
65
65
  # This method lets authlogic know whether it should allow the last_request_at field to be updated
66
66
  # with the current time (Time.now). One thing to note here is that it also checks for the existence of a
67
67
  # last_request_update_allowed? method in your controller. This allows you to control this method pragmatically
@@ -81,11 +81,11 @@ module Authlogic
81
81
  return controller.last_request_update_allowed? if controller.responds_to_last_request_update_allowed?
82
82
  record.last_request_at.blank? || last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
83
83
  end
84
-
84
+
85
85
  def set_last_request_at
86
86
  record.last_request_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
87
87
  end
88
-
88
+
89
89
  def last_request_at_threshold
90
90
  self.class.last_request_at_threshold
91
91
  end
@@ -35,8 +35,8 @@ module Authlogic
35
35
  # Allow finding by persistence token, because when records are created the session is maintained in a before_save, when there is no id.
36
36
  # This is done for performance reasons and to save on queries.
37
37
  record = record_id.nil? ?
38
- search_for_record("find_by_persistence_token", persistence_token) :
39
- search_for_record("find_by_#{klass.primary_key}", record_id)
38
+ search_for_record("find_by_persistence_token", persistence_token.to_s) :
39
+ search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
40
40
  self.unauthorized_record = record if record && record.persistence_token == persistence_token
41
41
  valid?
42
42
  else
@@ -2,15 +2,15 @@ module Authlogic
2
2
  module TestCase
3
3
  class MockRequest # :nodoc:
4
4
  attr_accessor :controller
5
-
5
+
6
6
  def initialize(controller)
7
7
  self.controller = controller
8
8
  end
9
-
10
- def remote_ip
9
+
10
+ def ip
11
11
  (controller && controller.respond_to?(:env) && controller.env.is_a?(Hash) && controller.env['REMOTE_ADDR']) || "1.1.1.1"
12
12
  end
13
-
13
+
14
14
  private
15
15
  def method_missing(*args, &block)
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authlogic
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Johnson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-03 00:00:00.000000000 Z
11
+ date: 2014-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -169,6 +169,7 @@ files:
169
169
  - lib/authlogic/authenticates_many/association.rb
170
170
  - lib/authlogic/authenticates_many/base.rb
171
171
  - lib/authlogic/controller_adapters/abstract_adapter.rb
172
+ - lib/authlogic/controller_adapters/rack_adapter.rb
172
173
  - lib/authlogic/controller_adapters/rails_adapter.rb
173
174
  - lib/authlogic/controller_adapters/sinatra_adapter.rb
174
175
  - lib/authlogic/crypto_providers/aes256.rb