From codesite-noreply at google.com Wed Aug 8 09:22:21 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Wed, 08 Aug 2007 06:22:21 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r211 - in trunk:
. lib/active_ldap/association
Message-ID:
Author: koutou
Date: Wed Aug 8 06:21:20 2007
New Revision: 211
Modified:
trunk/README
trunk/lib/active_ldap/association/belongs_to.rb
Log:
* supported :primary_key => "dn" with belongs_to.
Thanks to Perry Smith!!!
Modified: trunk/README
==============================================================================
--- trunk/README (original)
+++ trunk/README Wed Aug 8 06:21:20 2007
@@ -99,3 +99,4 @@
* Iain Pople: Bug reports and API improvement ideas.
* Christoph Lipp: Tell us character escape syntax.
* Kevin McCarthy: Patches.
+* Perry Smith: Patches.
Modified: trunk/lib/active_ldap/association/belongs_to.rb
==============================================================================
--- trunk/lib/active_ldap/association/belongs_to.rb (original)
+++ trunk/lib/active_ldap/association/belongs_to.rb Wed Aug 8 06:21:20 2007
@@ -30,10 +30,15 @@
def find_target
value = @owner[@options[:foreign_key_name]]
raise EntryNotFound if value.nil?
- filter = {primary_key => value}
- result = foreign_class.find(:all, :filter => filter, :limit => 1)
- raise EntryNotFound if result.empty?
- result.first
+ key = primary_key
+ if key == "dn"
+ result = foreign_class.find(value)
+ else
+ filter = {key => value}
+ result = foreign_class.find(:all, :filter => filter, :limit => 1).first
+ end
+ raise EntryNotFound if result.nil?
+ result
end
end
end
From codesite-noreply at google.com Wed Aug 8 09:49:24 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Wed, 08 Aug 2007 06:49:24 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r212 -
trunk/lib/active_ldap/association
Message-ID:
Author: koutou
Date: Wed Aug 8 06:48:43 2007
New Revision: 212
Added:
trunk/lib/active_ldap/association/has_many_utils.rb
Modified:
trunk/lib/active_ldap/association/has_many.rb
trunk/lib/active_ldap/association/has_many_wrap.rb
Log:
* cleanup.
Modified: trunk/lib/active_ldap/association/has_many.rb
==============================================================================
--- trunk/lib/active_ldap/association/has_many.rb (original)
+++ trunk/lib/active_ldap/association/has_many.rb Wed Aug 8 06:48:43 2007
@@ -1,8 +1,11 @@
require 'active_ldap/association/collection'
+require 'active_ldap/association/has_many_utils'
module ActiveLdap
module Association
class HasMany < Collection
+ include HasManyUtils
+
private
def insert_entry(entry)
entry[primary_key] = @owner[@options[:foreign_key_name]]
@@ -10,20 +13,25 @@
end
def find_target
+ collect_targets(:foreign_key_name)
foreign_base_key = primary_key
- components = @owner[@options[:foreign_key_name], true].collect do |value|
- key = val = nil
- if foreign_base_key == "dn"
- key, val = value.split(",")[0].split("=") unless value.empty?
- else
- key, val = foreign_base_key, value
+ return [] if foreign_base_key
+
+ values = @owner[@options[:foreign_key_name], true]
+
+ components = values.reject do |value|
+ value.nil?
+ end
+ unless foreign_base_key == "dn"
+ components = values.collect do |value|
+ [foreign_base_key, value]
end
- [key, val]
- end.reject do |key, val|
- key.nil? or val.nil?
end
- if components.empty?
- []
+
+ return [] if components.empty?
+
+ if foreign_base_key == "dn"
+ foreign_class.find(components)
else
foreign_class.find(:all, :filter => [:or, *components])
end
Added: trunk/lib/active_ldap/association/has_many_utils.rb
==============================================================================
--- (empty file)
+++ trunk/lib/active_ldap/association/has_many_utils.rb Wed Aug 8 06:48:43 2007
@@ -0,0 +1,34 @@
+module ActiveLdap
+ module Association
+ module HasManyUtils
+ private
+ def collect_targets(requested_target_key, need_requested_targets=false)
+ foreign_base_key = primary_key
+ return [] if foreign_base_key.nil?
+
+ requested_targets = @owner[@options[requested_target_key], true]
+
+ components = requested_targets.reject(&:nil?)
+ unless foreign_base_key == "dn"
+ components = components.collect do |value|
+ [foreign_base_key, value]
+ end
+ end
+
+ if components.empty?
+ targets = []
+ elsif foreign_base_key == "dn"
+ targets = foreign_class.find(components)
+ else
+ targets = foreign_class.find(:all, :filter => [:or, *components])
+ end
+
+ if need_requested_targets
+ [targets, requested_targets]
+ else
+ targets
+ end
+ end
+ end
+ end
+end
Modified: trunk/lib/active_ldap/association/has_many_wrap.rb
==============================================================================
--- trunk/lib/active_ldap/association/has_many_wrap.rb (original)
+++ trunk/lib/active_ldap/association/has_many_wrap.rb Wed Aug 8 06:48:43 2007
@@ -1,8 +1,11 @@
require 'active_ldap/association/collection'
+require 'active_ldap/association/has_many_utils'
module ActiveLdap
module Association
class HasManyWrap < Collection
+ include HasManyUtils
+
private
def insert_entry(entry)
old_value = @owner[@options[:wrap], true]
@@ -24,28 +27,16 @@
end
def find_target
- foreign_base_key = primary_key
- requested_targets = @owner[@options[:wrap], true]
-
- components = requested_targets.collect do |value|
- key = val = nil
- if foreign_base_key == "dn"
- key, val = value.split(",")[0].split("=") unless value.empty?
- else
- key, val = foreign_base_key, value
- end
- [key, val]
- end.reject do |key, val|
- key.nil? or val.nil?
- end
- return [] if components.empty?
+ targets, requested_targets = collect_targets(:wrap, true)
+ raise EntryNotFound if targets.nil?
- klass = foreign_class
found_targets = {}
- klass.find(:all, :filter => [:or, *components]).each do |target|
+ foreign_base_key = primary_key
+ targets.each do |target|
found_targets[target.send(foreign_base_key)] ||= target
end
+ klass = foreign_class
requested_targets.collect do |name|
found_targets[name] || klass.new(name)
end
From codesite-noreply at google.com Wed Aug 8 09:54:25 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Wed, 08 Aug 2007 06:54:25 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r213 -
trunk/lib/active_ldap/association
Message-ID:
Author: koutou
Date: Wed Aug 8 06:53:44 2007
New Revision: 213
Modified:
trunk/lib/active_ldap/association/has_many.rb
trunk/lib/active_ldap/association/has_many_wrap.rb
Log:
* removed garbages in the previous commit.
Modified: trunk/lib/active_ldap/association/has_many.rb
==============================================================================
--- trunk/lib/active_ldap/association/has_many.rb (original)
+++ trunk/lib/active_ldap/association/has_many.rb Wed Aug 8 06:53:44 2007
@@ -14,27 +14,6 @@
def find_target
collect_targets(:foreign_key_name)
- foreign_base_key = primary_key
- return [] if foreign_base_key
-
- values = @owner[@options[:foreign_key_name], true]
-
- components = values.reject do |value|
- value.nil?
- end
- unless foreign_base_key == "dn"
- components = values.collect do |value|
- [foreign_base_key, value]
- end
- end
-
- return [] if components.empty?
-
- if foreign_base_key == "dn"
- foreign_class.find(components)
- else
- foreign_class.find(:all, :filter => [:or, *components])
- end
end
def delete_entries(entries)
Modified: trunk/lib/active_ldap/association/has_many_wrap.rb
==============================================================================
--- trunk/lib/active_ldap/association/has_many_wrap.rb (original)
+++ trunk/lib/active_ldap/association/has_many_wrap.rb Wed Aug 8 06:53:44 2007
@@ -28,7 +28,7 @@
def find_target
targets, requested_targets = collect_targets(:wrap, true)
- raise EntryNotFound if targets.nil?
+ return [] if targets.nil?
found_targets = {}
foreign_base_key = primary_key
From codesite-noreply at google.com Thu Aug 9 08:38:16 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Thu, 09 Aug 2007 05:38:16 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r214 - in trunk:
. lib/active_ldap/adapter
Message-ID: <00163600d06e04374388529db323f1c@google.com>
Author: koutou
Date: Thu Aug 9 05:38:08 2007
New Revision: 214
Modified:
trunk/README
trunk/lib/active_ldap/adapter/base.rb
Log:
* added nil check.
Reported by Perry Smith. Thanks!
Modified: trunk/README
==============================================================================
--- trunk/README (original)
+++ trunk/README Thu Aug 9 05:38:08 2007
@@ -99,4 +99,4 @@
* Iain Pople: Bug reports and API improvement ideas.
* Christoph Lipp: Tell us character escape syntax.
* Kevin McCarthy: Patches.
-* Perry Smith: Patches.
+* Perry Smith: Patches and bug reports.
Modified: trunk/lib/active_ldap/adapter/base.rb
==============================================================================
--- trunk/lib/active_ldap/adapter/base.rb (original)
+++ trunk/lib/active_ldap/adapter/base.rb Thu Aug 9 05:38:08 2007
@@ -95,8 +95,7 @@
'ldapSyntaxes',
#'extendedAttributeInfo', # if we need RANGE-LOWER/UPPER.
]
- key = 'subschemaSubentry'
- base ||= root_dse([key], options)[0][key][0]
+ base ||= root_dse_values('subschemaSubentry', options)[0]
base ||= 'cn=schema'
dn, attributes = search(:base => base,
:scope => :base,
@@ -248,10 +247,8 @@
# Get all SASL mechanisms
mechanisms = operation(options) do
- key = "supportedSASLMechanisms"
- root_dse([key])[0][key]
+ root_dse_values("supportedSASLMechanisms")
end
- mechanisms ||= []
if options.has_key?(:sasl_quiet)
sasl_quiet = options[:sasl_quiet]
@@ -463,6 +460,12 @@
reconnect_attempts = options[:reconnect_attempts] || 0
retry_limit < 0 or reconnect_attempts < (retry_limit - 1)
+ end
+
+ def root_dse_values(key, options={})
+ dse = root_dse([key], options)[0]
+ return [] if dse.nil?
+ dse[key] || dse[key.downcase] || []
end
end
end
From codesite-noreply at google.com Fri Aug 10 08:45:59 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Fri, 10 Aug 2007 05:45:59 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r215 -
trunk/lib/active_ldap/association
Message-ID: <00163600d06e043757c1cce75557428@google.com>
Author: koutou
Date: Fri Aug 10 05:45:53 2007
New Revision: 215
Modified:
trunk/lib/active_ldap/association/belongs_to_many.rb
Log:
* cleanup.
Modified: trunk/lib/active_ldap/association/belongs_to_many.rb
==============================================================================
--- trunk/lib/active_ldap/association/belongs_to_many.rb (original)
+++ trunk/lib/active_ldap/association/belongs_to_many.rb Fri Aug 10 05:45:53 2007
@@ -27,16 +27,14 @@
end
def find_target
- key = @options[:many]
values = @owner[@options[:foreign_key_name], true].compact
+ return [] if values.empty?
+
+ key = @options[:many]
components = values.collect do |value|
[key, value]
end
- if components.empty?
- []
- else
- foreign_class.find(:all, :filter => [:or, *components])
- end
+ foreign_class.find(:all, :filter => [:or, *components])
end
end
end
From codesite-noreply at google.com Sat Aug 11 05:58:58 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 02:58:58 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r217 - in trunk:
lib/active_ldap test
Message-ID: <00c09ffb4bcf0437698a565a0229e0d@google.com>
Author: koutou
Date: Sat Aug 11 02:58:21 2007
New Revision: 217
Modified:
trunk/lib/active_ldap/base.rb
trunk/lib/active_ldap/connection.rb
trunk/test/al-test-utils.rb
trunk/test/test_connection_per_dn.rb
Log:
* clear association cache if establish_connection success.
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 02:58:21 2007
@@ -720,6 +720,7 @@
@connection = nil
connection.connect
@connection = connection
+ clear_association_cache
rescue ActiveLdap::Error
remove_connection
@connection = before_connection
Modified: trunk/lib/active_ldap/connection.rb
==============================================================================
--- trunk/lib/active_ldap/connection.rb (original)
+++ trunk/lib/active_ldap/connection.rb Sat Aug 11 02:58:21 2007
@@ -15,6 +15,12 @@
@active_connection_name ||= determine_active_connection_name
end
+ def remove_active_connections!
+ active_connections.keys.each do |key|
+ remove_connection(key)
+ end
+ end
+
def clear_active_connections!
connections = active_connections
connections.each do |key, connection|
Modified: trunk/test/al-test-utils.rb
==============================================================================
--- trunk/test/al-test-utils.rb (original)
+++ trunk/test/al-test-utils.rb Sat Aug 11 02:58:21 2007
@@ -64,7 +64,7 @@
end
def teardown
- ActiveLdap::Base.clear_active_connections!
+ ActiveLdap::Base.remove_active_connections!
super
end
end
@@ -187,7 +187,7 @@
@user_index += 1
uid = config[:uid] || "temp-user#{@user_index}"
ensure_delete_user(uid) do
- password = config[:password] || "password"
+ password = config[:password] || "password#{@user_index}"
uid_number = config[:uid_number] || default_uid
gid_number = config[:gid_number] || default_gid
home_directory = config[:home_directory] || "/nonexistent"
@@ -240,7 +240,10 @@
def ensure_delete_user(uid)
yield(uid)
ensure
- @user_class.delete(uid) if @user_class.exists?(uid)
+ if @user_class.exists?(uid)
+ @user_class.find(uid).remove_connection
+ @user_class.delete(uid)
+ end
end
def ensure_delete_group(cn)
Modified: trunk/test/test_connection_per_dn.rb
==============================================================================
--- trunk/test/test_connection_per_dn.rb (original)
+++ trunk/test/test_connection_per_dn.rb Sat Aug 11 02:58:21 2007
@@ -6,86 +6,73 @@
priority :must
def test_establish_connection
make_temporary_user do |user, password|
- begin
- assert_equal(user.class.connection, user.connection)
- assert_raises(ActiveLdap::AuthenticationError) do
- user.establish_connection(:bind_dn => nil,
- :allow_anonymous => false,
- :retry_limit => 0)
- end
- assert_equal(user.class.connection, user.connection)
-
- assert_nothing_raised do
- user.establish_connection(:bind_dn => nil,
- :allow_anonymous => true)
- end
- assert_not_equal(user.class.connection, user.connection)
+ assert_equal(user.class.connection, user.connection)
+ assert_raises(ActiveLdap::AuthenticationError) do
+ user.establish_connection(:bind_dn => nil,
+ :allow_anonymous => false,
+ :retry_limit => 0)
+ end
+ assert_equal(user.class.connection, user.connection)
- assert_equal(user.connection, user.class.find(user.dn).connection)
- assert_equal(user.connection, user.find(user.dn).connection)
- ensure
- user.remove_connection
+ assert_nothing_raised do
+ user.establish_connection(:bind_dn => nil,
+ :allow_anonymous => true)
end
+ assert_not_equal(user.class.connection, user.connection)
+
+ assert_equal(user.connection, user.class.find(user.dn).connection)
+ assert_equal(user.connection, user.find(user.dn).connection)
end
end
def test_find
make_temporary_user do |user, password|
- begin
- make_temporary_user do |user2, password2|
- user.establish_connection(:bind_dn => user.dn,
- :password => password)
- assert_not_equal(user.class.connection, user.connection)
+ make_temporary_user do |user2, password2|
+ user.establish_connection(:bind_dn => user.dn,
+ :password => password)
+ assert_not_equal(user.class.connection, user.connection)
- found_user2 = user.find(user2.dn)
- assert_not_equal(user2.connection, found_user2.connection)
- assert_equal(user.connection, found_user2.connection)
-
- assert_equal(found_user2.class.connection,
- found_user2.class.find(found_user2.dn).connection)
-
- found_user2.establish_connection(:bind_dn => user2.dn,
- :password => password2)
- assert_not_equal(user.connection, found_user2.connection)
- assert_equal(user2.connection, found_user2.connection)
- end
- ensure
- user.remove_connection
+ found_user2 = user.find(user2.dn)
+ assert_not_equal(user2.connection, found_user2.connection)
+ assert_equal(user.connection, found_user2.connection)
+
+ assert_equal(found_user2.class.connection,
+ found_user2.class.find(found_user2.dn).connection)
+
+ found_user2.establish_connection(:bind_dn => user2.dn,
+ :password => password2)
+ assert_not_equal(user.connection, found_user2.connection)
+ assert_equal(user2.connection, found_user2.connection)
end
end
end
def test_associations
make_temporary_user do |user, password|
- begin
- make_temporary_group do |group1|
- make_temporary_group do |group2|
- user.groups = [group1]
- assert_equal(group1.connection, user.connection)
-
- user.establish_connection(:bind_dn => user.dn,
- :password => password)
- assert_not_equal(user.class.connection, user.connection)
- assert_not_equal(group1.connection, user.connection)
-
- assert_raise(ActiveLdap::LdapError::InsufficientAccess) do
- user.groups << group2
- end
- assert_equal([group1.cn], user.groups.collect(&:cn))
-
- assert_not_equal(group1.connection, user.connection)
- assert_not_equal(user.groups[0].connection, user.connection)
- user.reload
- assert_equal(user.groups[0].connection, user.connection)
-
- found_user = user.class.find(user.dn)
- assert_equal(user.connection, found_user.connection)
- assert_equal(found_user.connection,
- found_user.groups[0].connection)
+ make_temporary_group do |group1|
+ make_temporary_group do |group2|
+ user.groups = [group1]
+ assert_equal(group1.connection, user.connection)
+
+ user.establish_connection(:bind_dn => user.dn,
+ :password => password)
+ assert_not_equal(user.class.connection, user.connection)
+ assert_not_equal(group1.connection, user.connection)
+ assert_equal(user.groups[0].connection, user.connection)
+
+ assert_raise(ActiveLdap::LdapError::InsufficientAccess) do
+ user.groups << group2
end
+ assert_equal([group1.cn], user.groups.collect(&:cn))
+
+ assert_not_equal(group1.connection, user.connection)
+ assert_equal(user.groups[0].connection, user.connection)
+
+ found_user = user.class.find(user.dn)
+ assert_equal(user.connection, found_user.connection)
+ assert_equal(found_user.connection,
+ found_user.groups[0].connection)
end
- ensure
- user.remove_connection
end
end
end
From codesite-noreply at google.com Sat Aug 11 06:02:58 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 03:02:58 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r218 -
trunk/lib/active_ldap
Message-ID: <00163600d06e04376998a69c0729dde@google.com>
Author: koutou
Date: Sat Aug 11 03:02:44 2007
New Revision: 218
Modified:
trunk/lib/active_ldap/connection.rb
Log:
* fixed wrong condition.
Modified: trunk/lib/active_ldap/connection.rb
==============================================================================
--- trunk/lib/active_ldap/connection.rb (original)
+++ trunk/lib/active_ldap/connection.rb Sat Aug 11 03:02:44 2007
@@ -95,10 +95,10 @@
end
def remove_connection(klass_or_key=self)
- if klass_or_key.is_a?(String)
- key = klass_or_key
- else
+ if klass_or_key.is_a?(Module)
key = active_connection_key(klass_or_key)
+ else
+ key = klass_or_key
end
config = configuration(key)
conn = active_connections[key]
From codesite-noreply at google.com Sat Aug 11 07:44:02 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 04:44:02 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r219 - in
trunk/lib: . active_ldap
Message-ID: <00163600d06e04376b020e81872d1a7@google.com>
Author: koutou
Date: Sat Aug 11 04:42:51 2007
New Revision: 219
Modified:
trunk/lib/active_ldap.rb
trunk/lib/active_ldap/base.rb
trunk/lib/active_ldap/configuration.rb
trunk/lib/active_ldap/connection.rb
trunk/lib/active_ldap/operations.rb
Log:
* marked :ldap_scop is deprecated. Use :scope instead.
Modified: trunk/lib/active_ldap.rb
==============================================================================
--- trunk/lib/active_ldap.rb (original)
+++ trunk/lib/active_ldap.rb Sat Aug 11 04:42:51 2007
@@ -177,7 +177,7 @@
# class Group < ActiveLdap::Base
# ldap_mapping :dn_attribute => 'cn',
# :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
-# :scope => LDAP::LDAP_SCOPE_ONELEVEL
+# :scope => :one
# end
#
# As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
@@ -473,7 +473,7 @@
# * :method indicates whether to use :ssl, :tls, or :plain
# * :retries - indicates the number of attempts to reconnect that will be undertaken when a stale connection occurs. -1 means infinite.
# * :retry_wait - seconds to wait before retrying a connection
-# * :ldap_scope - dictates how to find objects. (Default: ONELEVEL)
+# * :scope - dictates how to find objects. (Default: :one)
# * :timeout - time in seconds - defaults to disabled. This CAN interrupt search() requests. Be warned.
# * :retry_on_timeout - whether to reconnect when timeouts occur. Defaults to true
# See lib/configuration.rb for defaults for each option
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 04:42:51 2007
@@ -201,7 +201,7 @@
end
class_local_attr_accessor false, :prefix, :base, :dn_attribute
- class_local_attr_accessor true, :ldap_scope
+ class_local_attr_accessor true, :scope
class_local_attr_accessor true, :required_classes, :recommended_classes
class << self
@@ -234,7 +234,7 @@
# :sasl_quiet - if true, sets @sasl_quiet on the Ruby/LDAP connection
# :method - whether to use :ssl, :tls, or :plain (unencrypted)
# :retry_wait - seconds to wait before retrying a connection
- # :ldap_scope - dictates how to find objects. ONELEVEL by default to
+ # :scope - dictates how to find objects. ONELEVEL by default to
# avoid dn_attr collisions across OUs. Think before changing.
# :timeout - time in seconds - defaults to disabled. This CAN interrupt
# search() requests. Be warned.
@@ -276,7 +276,7 @@
self.dn_attribute = dn_attribute
self.prefix = prefix
- self.ldap_scope = scope
+ self.scope = scope
self.required_classes = classes
self.recommended_classes = recommended_classes
@@ -303,17 +303,16 @@
end.join(",")
end
- alias_method :ldap_scope_without_validation=, :ldap_scope=
- def ldap_scope=(scope)
- validate_ldap_scope(scope)
- self.ldap_scope_without_validation = scope
+ alias_method :scope_without_validation=, :scope=
+ def scope=(scope)
+ validate_scope(scope)
+ self.scope_without_validation = scope
end
- def validate_ldap_scope(scope)
+ def validate_scope(scope)
scope = scope.to_sym if scope.is_a?(String)
return if scope.nil? or scope.is_a?(Symbol)
- raise ConfigurationError,
- ":ldap_scope '#{scope.inspect}' must be a Symbol"
+ raise ConfigurationError, "scope '#{scope.inspect}' must be a Symbol"
end
def base_class
@@ -388,7 +387,7 @@
end
end
- self.ldap_scope = :sub
+ self.scope = :sub
self.required_classes = ['top']
self.recommended_classes = []
@@ -817,7 +816,7 @@
@attr_aliases = {} # aliases of @attr_methods
@last_oc = false # for use in other methods for "caching"
@base = nil
- @ldap_scope = nil
+ @scope = nil
@connection ||= nil
end
@@ -880,15 +879,15 @@
@base = object_local_base
end
- alias_method :ldap_scope_of_class, :ldap_scope
- def ldap_scope
- @ldap_scope || ldap_scope_of_class
+ alias_method :scope_of_class, :scope
+ def scope
+ @scope || scope_of_class
end
- undef_method :ldap_scope=
- def ldap_scope=(scope)
- self.class.validate_ldap_scope(scope)
- @ldap_scope = scope
+ undef_method :scope=
+ def scope=(scope)
+ self.class.validate_scope(scope)
+ @scope = scope
end
# get_attribute
Modified: trunk/lib/active_ldap/configuration.rb
==============================================================================
--- trunk/lib/active_ldap/configuration.rb (original)
+++ trunk/lib/active_ldap/configuration.rb Sat Aug 11 04:42:51 2007
@@ -79,7 +79,7 @@
@@defined_configurations.delete_if {|key, value| value == config}
end
- CONNECTION_CONFIGURATION_KEYS = [:base, :ldap_scope, :adapter]
+ CONNECTION_CONFIGURATION_KEYS = [:base, :adapter]
def remove_connection_related_configuration(config)
config.reject do |key, value|
CONNECTION_CONFIGURATION_KEYS.include?(key)
@@ -93,8 +93,15 @@
when :base
# Scrub before inserting
target.base = value.gsub(/['}{#]/, '')
- when :ldap_scope
- target.ldap_scope = value
+ when :scope, :ldap_scope
+ if key == :ldap_scope
+ logger.warning do
+ ":ldap_scope configuration option is deprecated. " +
+ "Use :scope instead."
+ end
+ end
+ target.scope = value
+ configuration[:scope] = value
else
configuration[key] = value
end
Modified: trunk/lib/active_ldap/connection.rb
==============================================================================
--- trunk/lib/active_ldap/connection.rb (original)
+++ trunk/lib/active_ldap/connection.rb Sat Aug 11 04:42:51 2007
@@ -71,6 +71,12 @@
unless Adapter::Base.respond_to?(adapter_method)
raise AdapterNotFound.new(adapter)
end
+ if config.has_key?(:ldap_scope)
+ logger.warning do
+ ":ldap_scope connection option is deprecated. Use :scope instead."
+ end
+ config[:scope] ||= config.delete(:ldap_scope)
+ end
config = remove_connection_related_configuration(config)
Adapter::Base.send(adapter_method, config)
end
Modified: trunk/lib/active_ldap/operations.rb
==============================================================================
--- trunk/lib/active_ldap/operations.rb (original)
+++ trunk/lib/active_ldap/operations.rb Sat Aug 11 04:42:51 2007
@@ -43,9 +43,15 @@
filter ||= "(#{attr}=#{escape_filter_value(value, true)})"
filter = [:and, filter, *object_class_filters(classes)]
_base = [prefix, base].compact.reject{|x| x.empty?}.join(",")
+ if options.has_key?(:ldap_scope)
+ logger.warning do
+ ":ldap_scope search option is deprecated. Use :scope instead."
+ end
+ options[:scope] ||= options[:ldap_scope]
+ end
search_options = {
:base => _base,
- :scope => options[:scope] || ldap_scope,
+ :scope => options[:scope] || scope,
:filter => filter,
:limit => options[:limit],
:attributes => options[:attributes],
@@ -281,7 +287,7 @@
module LDIF
def dump(options={})
ldifs = []
- options = {:base => base, :scope => ldap_scope}.merge(options)
+ options = {:base => base, :scope => scope}.merge(options)
conn = options[:connection] || connection
conn.search(options) do |dn, attributes|
ldifs << to_ldif(dn, attributes)
@@ -332,7 +338,7 @@
end
def delete_all(filter=nil, options={})
- options = {:base => base, :scope => ldap_scope}.merge(options)
+ options = {:base => base, :scope => scope}.merge(options)
options = options.merge(:filter => filter) if filter
conn = options[:connection] || connection
targets = conn.search(options).collect do |dn, attributes|
From codesite-noreply at google.com Sat Aug 11 07:53:02 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 04:53:02 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r220 -
trunk/benchmark
Message-ID: <00c09ffb4bcf04376b224674072d49a@google.com>
Author: koutou
Date: Sat Aug 11 04:52:43 2007
New Revision: 220
Modified:
trunk/benchmark/bench-al.rb
Log:
* catch unwilling result.
Modified: trunk/benchmark/bench-al.rb
==============================================================================
--- trunk/benchmark/bench-al.rb (original)
+++ trunk/benchmark/bench-al.rb Sat Aug 11 04:52:43 2007
@@ -63,7 +63,10 @@
next if dc_class.exists?(value, :prefix => "dc=#{value}")
dc = dc_class.new(value)
dc.o = dc.dc
- dc.save
+ begin
+ dc.save
+ rescue ActiveLdap::OperationNotPermitted
+ end
end
if ActiveLdap::Base.search.empty?
From codesite-noreply at google.com Sat Aug 11 05:36:58 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 02:36:58 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r216 - in trunk:
lib lib/active_ldap lib/active_ldap/adapter
lib/active_ldap/association test
Message-ID: <00c09ff793780437693ba1aa1329b27@google.com>
Author: koutou
Date: Sat Aug 11 02:36:28 2007
New Revision: 216
Added:
trunk/lib/active_ldap/operations.rb
trunk/test/test_connection_per_dn.rb
Modified:
trunk/lib/active_ldap.rb
trunk/lib/active_ldap/adapter/base.rb
trunk/lib/active_ldap/association/belongs_to.rb
trunk/lib/active_ldap/association/belongs_to_many.rb
trunk/lib/active_ldap/association/collection.rb
trunk/lib/active_ldap/association/has_many_utils.rb
trunk/lib/active_ldap/association/proxy.rb
trunk/lib/active_ldap/associations.rb
trunk/lib/active_ldap/attributes.rb
trunk/lib/active_ldap/base.rb
trunk/lib/active_ldap/configuration.rb
trunk/lib/active_ldap/connection.rb
Log:
* supported connection per DN.
Modified: trunk/lib/active_ldap.rb
==============================================================================
--- trunk/lib/active_ldap.rb (original)
+++ trunk/lib/active_ldap.rb Sat Aug 11 02:36:28 2007
@@ -931,6 +931,7 @@
require 'active_ldap/associations'
require 'active_ldap/configuration'
require 'active_ldap/connection'
+require 'active_ldap/operations'
require 'active_ldap/attributes'
require 'active_ldap/object_class'
require 'active_ldap/distinguished_name'
@@ -946,6 +947,7 @@
ActiveLdap::Base.class_eval do
include ActiveLdap::Configuration
include ActiveLdap::Connection
+ include ActiveLdap::Operations
include ActiveLdap::Attributes
include ActiveLdap::ObjectClass
include ActiveLdap::Associations
Modified: trunk/lib/active_ldap/adapter/base.rb
==============================================================================
--- trunk/lib/active_ldap/adapter/base.rb (original)
+++ trunk/lib/active_ldap/adapter/base.rb Sat Aug 11 02:36:28 2007
@@ -9,7 +9,8 @@
:retry_wait, :bind_dn, :password,
:password_block, :try_sasl,
:sasl_mechanisms, :sasl_quiet,
- :allow_anonymous, :store_password]
+ :allow_anonymous, :store_password,
+ :scope]
def initialize(configuration={})
@connection = nil
@configuration = configuration.dup
@@ -116,7 +117,7 @@
def search(options={})
filter = parse_filter(options[:filter]) || 'objectClass=*'
attrs = options[:attributes] || []
- scope = ensure_scope(options[:scope])
+ scope = ensure_scope(options[:scope] || @scope)
base = options[:base]
limit = options[:limit] || 0
limit = nil if limit <= 0
Modified: trunk/lib/active_ldap/association/belongs_to.rb
==============================================================================
--- trunk/lib/active_ldap/association/belongs_to.rb (original)
+++ trunk/lib/active_ldap/association/belongs_to.rb Sat Aug 11 02:36:28 2007
@@ -8,6 +8,7 @@
@target = @owner[@options[:foreign_key_name]] = nil
else
@target = (Proxy === entry ? entry.target : entry)
+ infect_connection(@target)
unless entry.new_entry?
@owner[@options[:foreign_key_name]] = entry[primary_key]
end
@@ -32,10 +33,11 @@
raise EntryNotFound if value.nil?
key = primary_key
if key == "dn"
- result = foreign_class.find(value)
+ result = foreign_class.find(value, find_options)
else
filter = {key => value}
- result = foreign_class.find(:all, :filter => filter, :limit => 1).first
+ options = find_options(:filter => filter, :limit => 1)
+ result = foreign_class.find(:all, options).first
end
raise EntryNotFound if result.nil?
result
Modified: trunk/lib/active_ldap/association/belongs_to_many.rb
==============================================================================
--- trunk/lib/active_ldap/association/belongs_to_many.rb (original)
+++ trunk/lib/active_ldap/association/belongs_to_many.rb Sat Aug 11 02:36:28 2007
@@ -34,7 +34,8 @@
components = values.collect do |value|
[key, value]
end
- foreign_class.find(:all, :filter => [:or, *components])
+ options = find_options(:filter => [:or, *components])
+ foreign_class.find(:all, options)
end
end
end
Modified: trunk/lib/active_ldap/association/collection.rb
==============================================================================
--- trunk/lib/active_ldap/association/collection.rb (original)
+++ trunk/lib/active_ldap/association/collection.rb Sat Aug 11 02:36:28 2007
@@ -69,7 +69,10 @@
load_target
flatten_deeper(entries).each do |entry|
- result &&= insert_entry(entry) unless @owner.new_entry?
+ unless @owner.new_entry?
+ infect_connection(entry)
+ result &&= insert_entry(entry)
+ end
@target << entry
end
Modified: trunk/lib/active_ldap/association/has_many_utils.rb
==============================================================================
--- trunk/lib/active_ldap/association/has_many_utils.rb (original)
+++ trunk/lib/active_ldap/association/has_many_utils.rb Sat Aug 11 02:36:28 2007
@@ -18,9 +18,10 @@
if components.empty?
targets = []
elsif foreign_base_key == "dn"
- targets = foreign_class.find(components)
+ targets = foreign_class.find(components, find_options)
else
- targets = foreign_class.find(:all, :filter => [:or, *components])
+ options = find_options(:filter => [:or, *components])
+ targets = foreign_class.find(:all, options)
end
if need_requested_targets
Modified: trunk/lib/active_ldap/association/proxy.rb
==============================================================================
--- trunk/lib/active_ldap/association/proxy.rb (original)
+++ trunk/lib/active_ldap/association/proxy.rb Sat Aug 11 02:36:28 2007
@@ -84,6 +84,19 @@
loaded if target
target
end
+
+ def find_options(options={})
+ if @owner.connection != @owner.class.connection
+ {:connection => @owner.connection}.merge(options)
+ else
+ options
+ end
+ end
+
+ def infect_connection(target)
+ conn = @owner.instance_variable_get("@connection")
+ target.connection = conn if conn
+ end
end
end
end
Modified: trunk/lib/active_ldap/associations.rb
==============================================================================
--- trunk/lib/active_ldap/associations.rb (original)
+++ trunk/lib/active_ldap/associations.rb Sat Aug 11 02:36:28 2007
@@ -13,6 +13,8 @@
def self.append_features(base)
super
base.extend(ClassMethods)
+ base.class_inheritable_array(:associations)
+ base.associations = []
end
module ClassMethods
@@ -122,6 +124,7 @@
define_method("__make_#{name}") do
make_association.call(self)
end
+ associations << name
association_reader(name, &make_association)
association_writer(name, &make_association)
end
@@ -156,6 +159,13 @@
:extend]
def validate_has_many_options(options)
options.assert_valid_keys(VALID_HAS_MANY_OPTIONS)
+ end
+ end
+
+ def clear_association_cache
+ return if new_record?
+ (self.class.associations || []).each do |association|
+ instance_variable_set("@#{association}", nil)
end
end
end
Modified: trunk/lib/active_ldap/attributes.rb
==============================================================================
--- trunk/lib/active_ldap/attributes.rb (original)
+++ trunk/lib/active_ldap/attributes.rb Sat Aug 11 02:36:28 2007
@@ -1,7 +1,11 @@
module ActiveLdap
module Attributes
def self.included(base)
- base.extend(ClassMethods)
+ base.class_eval do
+ extend(ClassMethods)
+ extend(Normalize)
+ include(Normalize)
+ end
end
module ClassMethods
@@ -15,7 +19,9 @@
result + ancestor.instance_eval {@attr_protected ||= []}
end
end
+ end
+ module Normalize
def normalize_attribute_name(name)
name.to_s.downcase
end
@@ -55,7 +61,7 @@
else
values.each do |value|
if value.is_a?(Hash)
- suffix, real_value = extract_subtypes(value)
+ suffix, real_value = extract_attribute_options(value)
new_name = name + suffix
result[new_name] ||= []
result[new_name].concat(real_value)
@@ -92,8 +98,9 @@
end
# Contents MUST be a String or an Array
if !value.has_key?('binary') and schema.binary_required?(name)
- suffix, real_value = extract_subtypes(value)
- name, values = make_subtypes(name + suffix + ';binary', real_value)
+ suffix, real_value = extract_attribute_options(value)
+ name, values =
+ normalize_attribute_options("#{name}#{suffix};binary", real_value)
values
else
[value]
@@ -129,51 +136,39 @@
normalize_attribute_value_of_string(name, new_value)
end
-
- # make_subtypes
+ # normalize_attribute_options
#
- # Makes the Hashized value from the full attributename
+ # Makes the Hashized value from the full attribute name
# e.g. userCertificate;binary => "some_bin"
# becomes userCertificate => {"binary" => "some_bin"}
- def make_subtypes(attr, value)
- logger.debug {"stub: called make_subtypes(#{attr.inspect}, " +
- "#{value.inspect})"}
+ def normalize_attribute_options(attr, value)
+ logger.debug {"stub: called normalize_attribute_options" +
+ "(#{attr.inspect}, #{value.inspect})"}
return [attr, value] unless attr.match(/;/)
- ret_attr, *subtypes = attr.split(/;/)
- return [ret_attr, [make_subtypes_helper(subtypes, value)]]
- end
-
- # make_subtypes_helper
- #
- # This is a recursive function for building
- # nested hashed from multi-subtyped values
- def make_subtypes_helper(subtypes, value)
- logger.debug {"stub: called make_subtypes_helper" +
- "(#{subtypes.inspect}, #{value.inspect})"}
- return value if subtypes.size == 0
- return {subtypes[0] => make_subtypes_helper(subtypes[1..-1], value)}
+ ret_attr, *options = attr.split(/;/)
+ [ret_attr,
+ [options.reverse.inject(value) {|result, option| {option => result}}]]
end
- # extract_subtypes
+ # extract_attribute_options
#
# Extracts all of the subtypes from a given set of nested hashes
# and returns the attribute suffix and the final true value
- def extract_subtypes(value)
- logger.debug {"stub: called extract_subtypes(#{value.inspect})"}
- subtype = ''
+ def extract_attribute_options(value)
+ logger.debug {"stub: called extract_attribute_options(#{value.inspect})"}
+ options = ''
ret_val = value
if value.class == Hash
- subtype = ';' + value.keys[0]
+ options = ';' + value.keys[0]
ret_val = value[value.keys[0]]
- subsubtype = ''
if ret_val.class == Hash
- subsubtype, ret_val = extract_subtypes(ret_val)
+ sub_options, ret_val = extract_attribute_options(ret_val)
+ options += sub_options
end
- subtype += subsubtype
end
ret_val = [ret_val] unless ret_val.class == Array
- return subtype, ret_val
+ [options, ret_val]
end
end
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 02:36:28 2007
@@ -168,9 +168,6 @@
VALID_LDAP_MAPPING_OPTIONS = [:dn_attribute, :prefix, :scope,
:classes, :recommended_classes]
- VALID_SEARCH_OPTIONS = [:attribute, :value, :filter, :prefix,
- :classes, :scope, :limit, :attributes,
- :sort_by, :order]
cattr_accessor :logger
cattr_accessor :configurations
@@ -186,7 +183,7 @@
target = superclass
value = nil
loop do
- break nil unless target.respond_to?("#{sym}")
+ break nil unless target.respond_to?(:#{sym})
value = target.#{sym}
break if value
target = target.superclass
@@ -262,47 +259,6 @@
end
end
- def search(options={}, &block)
- validate_search_options(options)
- attr = options[:attribute]
- value = options[:value] || '*'
- filter = options[:filter]
- prefix = options[:prefix]
- classes = options[:classes]
-
- value = value.first if value.is_a?(Array) and value.first.size == 1
- if filter.nil? and !value.is_a?(String)
- raise ArgumentError, "Search value must be a String"
- end
-
- _attr, value, _prefix = split_search_value(value)
- attr ||= _attr || dn_attribute || "objectClass"
- prefix ||= _prefix
- filter ||= "(#{attr}=#{escape_filter_value(value, true)})"
- filter = [:and, filter, *object_class_filters(classes)]
- _base = [prefix, base].compact.reject{|x| x.empty?}.join(",")
- search_options = {
- :base => _base,
- :scope => options[:scope] || ldap_scope,
- :filter => filter,
- :limit => options[:limit],
- :attributes => options[:attributes],
- :sort_by => options[:sort_by],
- :order => options[:order],
- }
- connection.search(search_options) do |dn, attrs|
- attributes = {}
- attrs.each do |key, value|
- normalized_attr, normalized_value = make_subtypes(key, value)
- attributes[normalized_attr] ||= []
- attributes[normalized_attr].concat(normalized_value)
- end
- value = [dn, attributes]
- value = yield(value) if block_given?
- value
- end
- end
-
# This class function is used to setup all mappings between the subclass
# and ldap for use in activeldap
#
@@ -349,161 +305,15 @@
alias_method :ldap_scope_without_validation=, :ldap_scope=
def ldap_scope=(scope)
- scope = scope.to_sym if scope.is_a?(String)
- if scope.nil? or scope.is_a?(Symbol)
- self.ldap_scope_without_validation = scope
- else
- raise ConfigurationError,
- ":ldap_scope '#{scope.inspect}' must be a Symbol"
- end
- end
-
- def dump(options={})
- ldifs = []
- options = {:base => base, :scope => ldap_scope}.merge(options)
- connection.search(options) do |dn, attributes|
- ldifs << to_ldif(dn, attributes)
- end
- ldifs.join("\n")
- end
-
- def to_ldif(dn, attributes)
- connection.to_ldif(dn, unnormalize_attributes(attributes))
- end
-
- def load(ldifs)
- connection.load(ldifs)
- end
-
- def destroy(targets, options={})
- targets = [targets] unless targets.is_a?(Array)
- targets.each do |target|
- find(target, options).destroy
- end
- end
-
- def destroy_all(filter=nil, options={})
- targets = []
- if filter.is_a?(Hash)
- options = options.merge(filter)
- filter = nil
- end
- options = options.merge(:filter => filter) if filter
- find(:all, options).sort_by do |target|
- target.dn.reverse
- end.reverse.each do |target|
- target.destroy
- end
+ validate_ldap_scope(scope)
+ self.ldap_scope_without_validation = scope
end
- def delete(targets, options={})
- targets = [targets] unless targets.is_a?(Array)
- targets = targets.collect do |target|
- ensure_dn_attribute(ensure_base(target))
- end
- connection.delete(targets, options)
- end
-
- def delete_all(filter=nil, options={})
- options = {:base => base, :scope => ldap_scope}.merge(options)
- options = options.merge(:filter => filter) if filter
- targets = connection.search(options).collect do |dn, attributes|
- dn
- end.sort_by do |dn|
- dn.reverse
- end.reverse
-
- connection.delete(targets)
- end
-
- def add(dn, entries, options={})
- unnormalized_entries = entries.collect do |type, key, value|
- [type, key, unnormalize_attribute(key, value)]
- end
- connection.add(dn, unnormalized_entries, options)
- end
-
- def modify(dn, entries, options={})
- unnormalized_entries = entries.collect do |type, key, value|
- [type, key, unnormalize_attribute(key, value)]
- end
- connection.modify(dn, unnormalized_entries, options)
- end
-
- # find
- #
- # Finds the first match for value where |value| is the value of some
- # |field|, or the wildcard match. This is only useful for derived classes.
- # usage: Subclass.find(:attribute => "cn", :value => "some*val")
- # Subclass.find('some*val')
- def find(*args)
- options = extract_options_from_args!(args)
- args = [:first] if args.empty? and !options.empty?
- case args.first
- when :first
- find_initial(options)
- when :all
- options[:value] ||= args[1]
- find_every(options)
- else
- find_from_dns(args, options)
- end
- end
-
- def exists?(dn, options={})
- prefix = /^#{Regexp.escape(truncate_base(ensure_dn_attribute(dn)))}/ #
- dn_suffix = nil
- not search({:value => dn}.merge(options)).find do |_dn,|
- if prefix.match(_dn)
- begin
- dn_suffix ||= DN.parse(base)
- dn_prefix = DN.parse(_dn) - dn_suffix
- true
- rescue DistinguishedNameInvalid, ArgumentError
- false
- end
- else
- false
- end
- end.nil?
- end
-
- def update(dn, attributes, options={})
- if dn.is_a?(Array)
- i = -1
- dns = dn
- dns.collect do |dn|
- i += 1
- update(dn, attributes[i], options)
- end
- else
- object = find(dn, options)
- object.update_attributes(attributes)
- object
- end
- end
-
- def update_all(attributes, filter=nil, options={})
- search_options = options
- if filter
- if filter.is_a?(String) and /[=\(\)&\|]/ !~ filter
- search_options = search_options.merge(:value => filter)
- else
- search_options = search_options.merge(:filter => filter)
- end
- end
- targets = search(search_options).collect do |dn, attrs|
- dn
- end
-
- entries = attributes.collect do |name, value|
- normalized_name, normalized_value = normalize_attribute(name, value)
- [:replace, normalized_name,
- unnormalize_attribute(normalized_name, normalized_value)]
- end
- targets.each do |dn|
- connection.modify(dn, entries, options)
- end
+ def validate_ldap_scope(scope)
+ scope = scope.to_sym if scope.is_a?(String)
+ return if scope.nil? or scope.is_a?(Symbol)
+ raise ConfigurationError,
+ ":ldap_scope '#{scope.inspect}' must be a Symbol"
end
def base_class
@@ -523,172 +333,6 @@
options.assert_valid_keys(VALID_LDAP_MAPPING_OPTIONS)
end
- def validate_search_options(options)
- options.assert_valid_keys(VALID_SEARCH_OPTIONS)
- end
-
- def extract_options_from_args!(args)
- args.last.is_a?(Hash) ? args.pop : {}
- end
-
- def object_class_filters(classes=nil)
- (classes || required_classes).collect do |name|
- ["objectClass", escape_filter_value(name, true)]
- end
- end
-
- def find_initial(options)
- find_every(options.merge(:limit => 1)).first
- end
-
- def normalize_sort_order(value)
- case value.to_s
- when /\Aasc(?:end)?\z/i
- :ascend
- when /\Adesc(?:end)?\z/i
- :descend
- else
- raise ArgumentError, "Invalid order: #{value.inspect}"
- end
- end
-
- def find_every(options)
- options = options.dup
- sort_by = options.delete(:sort_by)
- order = options.delete(:order)
- limit = options.delete(:limit) if sort_by or order
-
- results = search(options).collect do |dn, attrs|
- instantiate([dn, attrs])
- end
- return results if sort_by.nil? and order.nil?
-
- sort_by ||= "dn"
- if sort_by.downcase == "dn"
- results = results.sort_by {|result| DN.parse(result.dn)}
- else
- results = results.sort_by {|result| result.send(sort_by)}
- end
-
- results.reverse! if normalize_sort_order(order || "ascend") == :descend
- results = results[0, limit] if limit
- results
- end
-
- def find_from_dns(dns, options)
- expects_array = dns.first.is_a?(Array)
- return [] if expects_array and dns.first.empty?
-
- dns = dns.flatten.compact.uniq
-
- case dns.size
- when 0
- raise EntryNotFound, "Couldn't find #{name} without a DN"
- when 1
- result = find_one(dns.first, options)
- expects_array ? [result] : result
- else
- find_some(dns, options)
- end
- end
-
- def find_one(dn, options)
- attr, value, prefix = split_search_value(dn)
- filter = [attr || dn_attribute, escape_filter_value(value, true)]
- filter = [:and, filter, options[:filter]] if options[:filter]
- options = {:prefix => prefix}.merge(options.merge(:filter => filter))
- result = find_initial(options)
- if result
- result
- else
- message = "Couldn't find #{name} with DN=#{dn}"
- message << " #{options[:filter]}" if options[:filter]
- raise EntryNotFound, message
- end
- end
-
- def find_some(dns, options)
- dn_filters = dns.collect do |dn|
- attr, value, prefix = split_search_value(dn)
- attr ||= dn_attribute
- filter = [attr, escape_filter_value(value, true)]
- if prefix
- filter = [:and,
- filter,
- [dn, "*,#{escape_filter_value(prefix)},#{base}"]]
- end
- filter
- end
- filter = [:or, *dn_filters]
- filter = [:and, filter, options[:filter]] if options[:filter]
- result = find_every(options.merge(:filter => filter))
- if result.size == dns.size
- result
- else
- message = "Couldn't find all #{name} with DNs (#{dns.join(', ')})"
- message << " #{options[:filter]}"if options[:filter]
- raise EntryNotFound, message
- end
- end
-
- def split_search_value(value)
- attr = prefix = nil
- begin
- dn = DN.parse(value)
- attr, value = dn.rdns.first.to_a.first
- rest = dn.rdns[1..-1]
- prefix = DN.new(*rest).to_s unless rest.empty?
- rescue DistinguishedNameInvalid
- begin
- dn = DN.parse("DUMMY=#{value}")
- _, value = dn.rdns.first.to_a.first
- rest = dn.rdns[1..-1]
- prefix = DN.new(*rest).to_s unless rest.empty?
- rescue DistinguishedNameInvalid
- end
- end
-
- prefix = nil if prefix == base
- prefix = truncate_base(prefix) if prefix
- [attr, value, prefix]
- end
-
- def escape_filter_value(value, without_asterisk=false)
- value.gsub(/[\*\(\)\\\0]/) do |x|
- if without_asterisk and x == "*"
- x
- else
- "\\%02x" % x[0]
- end
- end
- end
-
- def ensure_dn(target)
- attr, value, prefix = split_search_value(target)
- "#{attr || dn_attribute}=#{value},#{prefix || base}"
- end
-
- def ensure_dn_attribute(target)
- "#{dn_attribute}=" +
- target.gsub(/^\s*#{Regexp.escape(dn_attribute)}\s*=\s*/i, '')
- end
-
- def ensure_base(target)
- [truncate_base(target), base].join(',')
- end
-
- def truncate_base(target)
- if /,/ =~ target
- begin
- (DN.parse(target) - DN.parse(base)).to_s
- rescue DistinguishedNameInvalid, ArgumentError
- target
- end
- else
- target
- end
- end
-
def ensure_logger
@@logger ||= configuration[:logger]
# Setup default logger to console
@@ -702,8 +346,9 @@
configuration[:logger] ||= @@logger
end
- def instantiate(entry)
- dn, attributes = entry
+ def instantiate(args)
+ dn, attributes, options = args
+ options ||= {}
if self.class == Class
klass = self.ancestors[0].to_s.split(':').last
real_klass = self.ancestors[0]
@@ -713,6 +358,8 @@
end
obj = real_klass.allocate
+ conn = options[:connection] || connection
+ obj.connection = conn if conn != connection
obj.instance_eval do
initialize_by_ldap_data(dn, attributes)
end
@@ -883,6 +530,10 @@
end
end
+ def delete(options={})
+ super(dn, options)
+ end
+
# save
#
# Save and validate this object into LDAP
@@ -997,7 +648,7 @@
end
def to_ldif
- self.class.to_ldif(dn, normalize_data(@data))
+ super(dn, normalize_data(@data))
end
def to_xml(options={})
@@ -1030,7 +681,8 @@
alias_method :has_attribute?, :have_attribute?
def reload
- _, attributes = self.class.search(:value => id).find do |_dn, _attributes|
+ clear_association_cache
+ _, attributes = search(:value => id).find do |_dn, _attributes|
dn == _dn
end
raise EntryNotFound, "Can't find dn '#{dn}' to reload" if attributes.nil?
@@ -1061,6 +713,21 @@
end
end
+ def establish_connection(config={})
+ super
+ before_connection = @connection
+ begin
+ @connection = nil
+ connection.connect
+ @connection = connection
+ rescue ActiveLdap::Error
+ remove_connection
+ @connection = before_connection
+ raise
+ end
+ true
+ end
+
private
def extract_object_class(attributes)
classes = []
@@ -1094,6 +761,18 @@
yield self if block_given?
end
+ def instantiate(args)
+ dn, attributes, options = args
+ options ||= {}
+
+ obj = self.class.allocate
+ obj.connection = options[:connection] || @connection
+ obj.instance_eval do
+ initialize_by_ldap_data(dn, attributes)
+ end
+ obj
+ end
+
def to_real_attribute_name(name, allow_normalized_name=false)
ensure_apply_object_class
name = name.to_s
@@ -1123,7 +802,7 @@
logger.debug {"stub: enforce_type called"}
ensure_apply_object_class
# Enforce attribute value formatting
- result = self.class.normalize_attribute(key, value)[1]
+ result = normalize_attribute(key, value)[1]
logger.debug {"stub: enforce_types done"}
result
end
@@ -1137,6 +816,8 @@
@attr_aliases = {} # aliases of @attr_methods
@last_oc = false # for use in other methods for "caching"
@base = nil
+ @ldap_scope = nil
+ @connection ||= nil
end
# apply_object_class
@@ -1198,6 +879,17 @@
@base = object_local_base
end
+ alias_method :ldap_scope_of_class, :ldap_scope
+ def ldap_scope
+ @ldap_scope || ldap_scope_of_class
+ end
+
+ undef_method :ldap_scope=
+ def ldap_scope=(scope)
+ self.class.validate_ldap_scope(scope)
+ @ldap_scope = scope
+ end
+
# get_attribute
#
# Return the value of the attribute called by method_missing?
@@ -1359,12 +1051,12 @@
result
end
- def collect_modified_entries(ldap_data, data)
- entries = []
- # Now that all the subtypes will be treated as unique attributes
+ def collect_modified_attributes(ldap_data, data)
+ attributes = []
+ # Now that all the options will be treated as unique attributes
# we can see what's changed and add anything that is brand-spankin'
# new.
- logger.debug {'#collect_modified_entries: traversing ldap_data ' +
+ logger.debug {'#collect_modified_attributes: traversing ldap_data ' +
'determining replaces and deletes'}
ldap_data.each do |k, v|
value = data[k] || []
@@ -1376,60 +1068,59 @@
# Since some types do not have equality matching rules,
# delete doesn't work
# Replacing with nothing is equivalent.
- logger.debug {"#save: removing attribute from existing entry: #{k}"}
+ logger.debug {"#save: removing attribute: #{k}"}
if !data.has_key?(k) and schema.binary_required?(k)
value = [{'binary' => []}]
end
else
# Ditched delete then replace because attribs with no equality
# match rules will fails
- logger.debug {"#collect_modified_entries: updating attribute of" +
- " existing entry: #{k}: #{value.inspect}"}
+ logger.debug {"#collect_modified_attributes: updating attribute:" +
+ " #{k}: #{value.inspect}"}
end
- entries.push([:replace, k, value])
+ attributes.push([:replace, k, value])
end
- logger.debug {'#collect_modified_entries: finished traversing' +
+ logger.debug {'#collect_modified_attributes: finished traversing' +
' ldap_data'}
- logger.debug {'#collect_modified_entries: traversing data ' +
+ logger.debug {'#collect_modified_attributes: traversing data ' +
'determining adds'}
data.each do |k, v|
value = v || []
next if ldap_data.has_key?(k) or value.empty?
# Detect subtypes and account for them
- logger.debug {"#save: adding attribute to existing entry: " +
- "#{k}: #{value.inspect}"}
+ logger.debug {"#save: adding attribute: #{k}: #{value.inspect}"}
# REPLACE will function like ADD, but doesn't hit EQUALITY problems
# TODO: Added equality(attr) to Schema
- entries.push([:replace, k, value])
+ attributes.push([:replace, k, value])
end
- entries
+ attributes
end
- def collect_all_entries(data)
+ def collect_all_attributes(data)
dn_attr = to_real_attribute_name(dn_attribute)
dn_value = data[dn_attr]
- logger.debug {'#collect_all_entries: adding all attribute value pairs'}
- logger.debug {"#collect_all_entries: adding " +
+ logger.debug {'#collect_all_attributes: adding all attribute value pairs'}
+ logger.debug {"#collect_all_attributes: adding " +
"#{dn_attr.inspect} = #{dn_value.inspect}"}
- entries = []
- entries.push([:add, dn_attr, dn_value])
+ attributes = []
+ attributes.push([:add, dn_attr, dn_value])
oc_value = data['objectClass']
- logger.debug {"#collect_all_entries: adding objectClass = " +
+ logger.debug {"#collect_all_attributes: adding objectClass = " +
"#{oc_value.inspect}"}
- entries.push([:add, 'objectClass', oc_value])
+ attributes.push([:add, 'objectClass', oc_value])
data.each do |key, value|
next if value.empty? or key == 'objectClass' or key == dn_attr
- logger.debug {"#collect_all_entries: adding attribute to new " +
- "entry: #{key.inspect}: #{value.inspect}"}
- entries.push([:add, key, value])
+ logger.debug {"#collect_all_attributes: adding attribute: " +
+ "#{key.inspect}: #{value.inspect}"}
+ attributes.push([:add, key, value])
end
- entries
+ attributes
end
def check_configuration
@@ -1446,14 +1137,14 @@
def prepare_data_for_saving
logger.debug {"stub: save called"}
- # Expand subtypes to real ldap_data entries
+ # Expand subtypes to real ldap_data attributes
# We can't reuse @ldap_data because an exception would leave
# an object in an unknown state
logger.debug {"#save: expanding subtypes in @ldap_data"}
ldap_data = normalize_data(@ldap_data)
logger.debug {'#save: subtypes expanded for @ldap_data'}
- # Expand subtypes to real data entries, but leave @data alone
+ # Expand subtypes to real data attributes, but leave @data alone
logger.debug {'#save: expanding subtypes for @data'}
bad_attrs = @data.keys - attribute_names
data = normalize_data(@data, bad_attrs)
@@ -1480,9 +1171,9 @@
def create
prepare_data_for_saving do |data, ldap_data|
- entries = collect_all_entries(data)
+ attributes = collect_all_attributes(data)
logger.debug {"#create: adding #{dn}"}
- self.class.add(dn, entries)
+ add_entry(dn, attributes)
logger.debug {"#create: add successful"}
@new_entry = false
true
@@ -1491,10 +1182,10 @@
def update
prepare_data_for_saving do |data, ldap_data|
- entries = collect_modified_entries(ldap_data, data)
+ attributes = collect_modified_attributes(ldap_data, data)
logger.debug {'#update: traversing data complete'}
logger.debug {"#update: modifying #{dn}"}
- self.class.modify(dn, entries)
+ modify_entry(dn, attributes)
logger.debug {'#update: modify successful'}
true
end
Modified: trunk/lib/active_ldap/configuration.rb
==============================================================================
--- trunk/lib/active_ldap/configuration.rb (original)
+++ trunk/lib/active_ldap/configuration.rb Sat Aug 11 02:36:28 2007
@@ -86,15 +86,15 @@
end
end
- def merge_configuration(config)
+ def merge_configuration(config, target=self)
configuration = default_configuration
config.symbolize_keys.each do |key, value|
case key
when :base
# Scrub before inserting
- self.base = value.gsub(/['}{#]/, '')
+ target.base = value.gsub(/['}{#]/, '')
when :ldap_scope
- self.ldap_scope = value
+ target.ldap_scope = value
else
configuration[key] = value
end
Modified: trunk/lib/active_ldap/connection.rb
==============================================================================
--- trunk/lib/active_ldap/connection.rb (original)
+++ trunk/lib/active_ldap/connection.rb Sat Aug 11 02:36:28 2007
@@ -47,18 +47,10 @@
def connection=(adapter)
if adapter.is_a?(Adapter::Base)
- @schema = nil
active_connections[active_connection_name] = adapter
elsif adapter.is_a?(Hash)
config = adapter
- adapter = (config[:adapter] || "ldap")
- normalized_adapter = adapter.downcase.gsub(/-/, "_")
- adapter_method = "#{normalized_adapter}_connection"
- unless Adapter::Base.respond_to?(adapter_method)
- raise AdapterNotFound.new(adapter)
- end
- config = remove_connection_related_configuration(config)
- self.connection = Adapter::Base.send(adapter_method, config)
+ self.connection = instantiate_adapter(config)
elsif adapter.nil?
raise ConnectionNotEstablished
else
@@ -66,6 +58,17 @@
end
end
+ def instantiate_adapter(config)
+ adapter = (config[:adapter] || "ldap")
+ normalized_adapter = adapter.downcase.gsub(/-/, "_")
+ adapter_method = "#{normalized_adapter}_connection"
+ unless Adapter::Base.respond_to?(adapter_method)
+ raise AdapterNotFound.new(adapter)
+ end
+ config = remove_connection_related_configuration(config)
+ Adapter::Base.send(adapter_method, config)
+ end
+
def connected?
active_connections[active_connection_name] ? true : false
end
@@ -85,8 +88,12 @@
conn
end
- def remove_connection(klass=self)
- key = active_connection_key(klass)
+ def remove_connection(klass_or_key=self)
+ if klass_or_key.is_a?(String)
+ key = klass_or_key
+ else
+ key = active_connection_key(klass_or_key)
+ end
config = configuration(key)
conn = active_connections[key]
remove_configuration_by_configuration(config)
@@ -107,7 +114,7 @@
# Return the schema object
def schema
- @schema ||= connection.schema
+ connection.schema
end
private
@@ -127,16 +134,50 @@
end
end
+ def establish_connection(config=nil)
+ config = self.class.ensure_configuration(config)
+ config = self.class.configuration.merge(config)
+ config = self.class.merge_configuration(config, self)
+
+ remove_connection
+ self.class.define_configuration(dn, config)
+ end
+
+ def remove_connection
+ self.class.remove_connection(dn)
+ end
+
def connection
- self.class.connection
+ conn = @connection
+ conn ||= self.class.active_connections[dn] || retrieve_connection if id
+ conn || self.class.connection
+ end
+
+ def connection=(adapter)
+ if adapter.nil? or adapter.is_a?(Adapter::Base)
+ @connection = adapter
+ elsif adapter.is_a?(Hash)
+ config = adapter
+ @connection = self.class.instantiate_adapter(config)
+ else
+ establish_connection(adapter)
+ end
+ end
+
+ def retrieve_connection
+ conn = self.class.active_connections[dn]
+ return conn if conn
+
+ config = self.class.configuration(dn)
+ return nil unless config
+
+ conn = self.class.instantiate_adapter(config)
+ @connection = self.class.active_connections[dn] = conn
+ conn
end
- # schema
- #
- # Returns the value of self.class.schema
- # This is just syntactic sugar
def schema
- self.class.schema
+ connection.schema
end
end
end
Added: trunk/lib/active_ldap/operations.rb
==============================================================================
--- (empty file)
+++ trunk/lib/active_ldap/operations.rb Sat Aug 11 02:36:28 2007
@@ -0,0 +1,405 @@
+module ActiveLdap
+ module Operations
+ class << self
+ def included(base)
+ super
+ base.class_eval do
+ extend(Common)
+ extend(Find)
+ extend(LDIF)
+ extend(Delete)
+ extend(Update)
+
+ include(Common)
+ include(Find)
+ include(LDIF)
+ include(Delete)
+ include(Update)
+ end
+ end
+ end
+
+ module Common
+ VALID_SEARCH_OPTIONS = [:attribute, :value, :filter, :prefix,
+ :classes, :scope, :limit, :attributes,
+ :sort_by, :order, :connection]
+
+ def search(options={}, &block)
+ validate_search_options(options)
+ attr = options[:attribute]
+ value = options[:value] || '*'
+ filter = options[:filter]
+ prefix = options[:prefix]
+ classes = options[:classes]
+
+ value = value.first if value.is_a?(Array) and value.first.size == 1
+ if filter.nil? and !value.is_a?(String)
+ raise ArgumentError, "Search value must be a String"
+ end
+
+ _attr, value, _prefix = split_search_value(value)
+ attr ||= _attr || dn_attribute || "objectClass"
+ prefix ||= _prefix
+ filter ||= "(#{attr}=#{escape_filter_value(value, true)})"
+ filter = [:and, filter, *object_class_filters(classes)]
+ _base = [prefix, base].compact.reject{|x| x.empty?}.join(",")
+ search_options = {
+ :base => _base,
+ :scope => options[:scope] || ldap_scope,
+ :filter => filter,
+ :limit => options[:limit],
+ :attributes => options[:attributes],
+ :sort_by => options[:sort_by],
+ :order => options[:order],
+ }
+
+ conn = options[:connection] || connection
+ conn.search(search_options) do |dn, attrs|
+ attributes = {}
+ attrs.each do |key, value|
+ normalized_attr, normalized_value =
+ normalize_attribute_options(key, value)
+ attributes[normalized_attr] ||= []
+ attributes[normalized_attr].concat(normalized_value)
+ end
+ value = [dn, attributes]
+ value = yield(value) if block_given?
+ value
+ end
+ end
+
+ def exist?(dn, options={})
+ prefix = /^#{Regexp.escape(truncate_base(ensure_dn_attribute(dn)))}/ #
+ dn_suffix = nil
+ not search({:value => dn}.merge(options)).find do |_dn,|
+ if prefix.match(_dn)
+ begin
+ dn_suffix ||= DN.parse(base)
+ dn_prefix = DN.parse(_dn) - dn_suffix
+ true
+ rescue DistinguishedNameInvalid, ArgumentError
+ false
+ end
+ else
+ false
+ end
+ end.nil?
+ end
+ alias_method :exists?, :exist?
+
+ private
+ def validate_search_options(options)
+ options.assert_valid_keys(VALID_SEARCH_OPTIONS)
+ end
+
+ def extract_options_from_args!(args)
+ args.last.is_a?(Hash) ? args.pop : {}
+ end
+
+ def ensure_dn_attribute(target)
+ "#{dn_attribute}=" +
+ target.gsub(/^\s*#{Regexp.escape(dn_attribute)}\s*=\s*/i, '')
+ end
+
+ def ensure_base(target)
+ [truncate_base(target), base].join(',')
+ end
+
+ def truncate_base(target)
+ if /,/ =~ target
+ begin
+ (DN.parse(target) - DN.parse(base)).to_s
+ rescue DistinguishedNameInvalid, ArgumentError
+ target
+ end
+ else
+ target
+ end
+ end
+
+ def object_class_filters(classes=nil)
+ (classes || required_classes).collect do |name|
+ ["objectClass", escape_filter_value(name, true)]
+ end
+ end
+
+ def escape_filter_value(value, without_asterisk=false)
+ value.gsub(/[\*\(\)\\\0]/) do |x|
+ if without_asterisk and x == "*"
+ x
+ else
+ "\\%02x" % x[0]
+ end
+ end
+ end
+
+ def split_search_value(value)
+ attr = prefix = nil
+ begin
+ dn = DN.parse(value)
+ attr, value = dn.rdns.first.to_a.first
+ rest = dn.rdns[1..-1]
+ prefix = DN.new(*rest).to_s unless rest.empty?
+ rescue DistinguishedNameInvalid
+ begin
+ dn = DN.parse("DUMMY=#{value}")
+ _, value = dn.rdns.first.to_a.first
+ rest = dn.rdns[1..-1]
+ prefix = DN.new(*rest).to_s unless rest.empty?
+ rescue DistinguishedNameInvalid
+ end
+ end
+
+ prefix = nil if prefix == base
+ prefix = truncate_base(prefix) if prefix
+ [attr, value, prefix]
+ end
+ end
+
+ module Find
+ # find
+ #
+ # Finds the first match for value where |value| is the value of some
+ # |field|, or the wildcard match. This is only useful for derived classes.
+ # usage: Subclass.find(:attribute => "cn", :value => "some*val")
+ # Subclass.find('some*val')
+ def find(*args)
+ options = extract_options_from_args!(args)
+ args = [:first] if args.empty? and !options.empty?
+ case args.first
+ when :first
+ find_initial(options)
+ when :all
+ options[:value] ||= args[1]
+ find_every(options)
+ else
+ find_from_dns(args, options)
+ end
+ end
+
+ private
+ def find_initial(options)
+ find_every(options.merge(:limit => 1)).first
+ end
+
+ def normalize_sort_order(value)
+ case value.to_s
+ when /\Aasc(?:end)?\z/i
+ :ascend
+ when /\Adesc(?:end)?\z/i
+ :descend
+ else
+ raise ArgumentError, "Invalid order: #{value.inspect}"
+ end
+ end
+
+ def find_every(options)
+ options = options.dup
+ sort_by = options.delete(:sort_by)
+ order = options.delete(:order)
+ limit = options.delete(:limit) if sort_by or order
+
+ results = search(options).collect do |dn, attrs|
+ instantiate([dn, attrs, {:connection => options[:connection]}])
+ end
+ return results if sort_by.nil? and order.nil?
+
+ sort_by ||= "dn"
+ if sort_by.downcase == "dn"
+ results = results.sort_by {|result| DN.parse(result.dn)}
+ else
+ results = results.sort_by {|result| result.send(sort_by)}
+ end
+
+ results.reverse! if normalize_sort_order(order || "ascend") == :descend
+ results = results[0, limit] if limit
+ results
+ end
+
+ def find_from_dns(dns, options)
+ expects_array = dns.first.is_a?(Array)
+ return [] if expects_array and dns.first.empty?
+
+ dns = dns.flatten.compact.uniq
+
+ case dns.size
+ when 0
+ raise EntryNotFound, "Couldn't find #{name} without a DN"
+ when 1
+ result = find_one(dns.first, options)
+ expects_array ? [result] : result
+ else
+ find_some(dns, options)
+ end
+ end
+
+ def find_one(dn, options)
+ attr, value, prefix = split_search_value(dn)
+ filter = [attr || dn_attribute, escape_filter_value(value, true)]
+ filter = [:and, filter, options[:filter]] if options[:filter]
+ options = {:prefix => prefix}.merge(options.merge(:filter => filter))
+ result = find_initial(options)
+ if result
+ result
+ else
+ message = "Couldn't find #{name} with DN=#{dn}"
+ message << " #{options[:filter]}" if options[:filter]
+ raise EntryNotFound, message
+ end
+ end
+
+ def find_some(dns, options)
+ dn_filters = dns.collect do |dn|
+ attr, value, prefix = split_search_value(dn)
+ attr ||= dn_attribute
+ filter = [attr, escape_filter_value(value, true)]
+ if prefix
+ filter = [:and,
+ filter,
+ [dn, "*,#{escape_filter_value(prefix)},#{base}"]]
+ end
+ filter
+ end
+ filter = [:or, *dn_filters]
+ filter = [:and, filter, options[:filter]] if options[:filter]
+ result = find_every(options.merge(:filter => filter))
+ if result.size == dns.size
+ result
+ else
+ message = "Couldn't find all #{name} with DNs (#{dns.join(', ')})"
+ message << " #{options[:filter]}"if options[:filter]
+ raise EntryNotFound, message
+ end
+ end
+
+ def ensure_dn(target)
+ attr, value, prefix = split_search_value(target)
+ "#{attr || dn_attribute}=#{value},#{prefix || base}"
+ end
+ end
+
+ module LDIF
+ def dump(options={})
+ ldifs = []
+ options = {:base => base, :scope => ldap_scope}.merge(options)
+ conn = options[:connection] || connection
+ conn.search(options) do |dn, attributes|
+ ldifs << to_ldif(dn, attributes)
+ end
+ ldifs.join("\n")
+ end
+
+ def to_ldif(dn, attributes, options={})
+ conn = options[:connection] || connection
+ conn.to_ldif(dn, unnormalize_attributes(attributes))
+ end
+
+ def load(ldifs, options={})
+ conn = options[:connection] || connection
+ conn.load(ldifs)
+ end
+ end
+
+ module Delete
+ def destroy(targets, options={})
+ targets = [targets] unless targets.is_a?(Array)
+ targets.each do |target|
+ find(target, options).destroy
+ end
+ end
+
+ def destroy_all(filter=nil, options={})
+ targets = []
+ if filter.is_a?(Hash)
+ options = options.merge(filter)
+ filter = nil
+ end
+ options = options.merge(:filter => filter) if filter
+ find(:all, options).sort_by do |target|
+ target.dn.reverse
+ end.reverse.each do |target|
+ target.destroy
+ end
+ end
+
+ def delete(targets, options={})
+ targets = [targets] unless targets.is_a?(Array)
+ targets = targets.collect do |target|
+ ensure_dn_attribute(ensure_base(target))
+ end
+ conn = options[:connection] || connection
+ conn.delete(targets, options)
+ end
+
+ def delete_all(filter=nil, options={})
+ options = {:base => base, :scope => ldap_scope}.merge(options)
+ options = options.merge(:filter => filter) if filter
+ conn = options[:connection] || connection
+ targets = conn.search(options).collect do |dn, attributes|
+ dn
+ end.sort_by do |dn|
+ dn.reverse
+ end.reverse
+
+ conn.delete(targets)
+ end
+ end
+
+ module Update
+ def add_entry(dn, attributes, options={})
+ unnormalized_attributes = attributes.collect do |type, key, value|
+ [type, key, unnormalize_attribute(key, value)]
+ end
+ conn = options[:connection] || connection
+ conn.add(dn, unnormalized_attributes, options)
+ end
+
+ def modify_entry(dn, attributes, options={})
+ unnormalized_attributes = attributes.collect do |type, key, value|
+ [type, key, unnormalize_attribute(key, value)]
+ end
+ conn = options[:connection] || connection
+ conn.modify(dn, unnormalized_attributes, options)
+ end
+
+ def update(dn, attributes, options={})
+ if dn.is_a?(Array)
+ i = -1
+ dns = dn
+ dns.collect do |dn|
+ i += 1
+ update(dn, attributes[i], options)
+ end
+ else
+ object = find(dn, options)
+ object.update_attributes(attributes)
+ object
+ end
+ end
+
+ def update_all(attributes, filter=nil, options={})
+ search_options = options.dup
+ if filter
+ if filter.is_a?(String) and /[=\(\)&\|]/ !~ filter
+ search_options = search_options.merge(:value => filter)
+ else
+ search_options = search_options.merge(:filter => filter)
+ end
+ end
+ targets = search(search_options).collect do |dn, attrs|
+ dn
+ end
+
+ unnormalized_attributes = attributes.collect do |name, value|
+ normalized_name, normalized_value = normalize_attribute(name, value)
+ [:replace, normalized_name,
+ unnormalize_attribute(normalized_name, normalized_value)]
+ end
+ conn = options[:connection] || connection
+ targets.each do |dn|
+ conn.modify(dn, unnormalized_attributes, options)
+ end
+ end
+ end
+ end
+end
Added: trunk/test/test_connection_per_dn.rb
==============================================================================
--- (empty file)
+++ trunk/test/test_connection_per_dn.rb Sat Aug 11 02:36:28 2007
@@ -0,0 +1,92 @@
+require 'al-test-utils'
+
+class TestConnectionPerDN < Test::Unit::TestCase
+ include AlTestUtils
+
+ priority :must
+ def test_establish_connection
+ make_temporary_user do |user, password|
+ begin
+ assert_equal(user.class.connection, user.connection)
+ assert_raises(ActiveLdap::AuthenticationError) do
+ user.establish_connection(:bind_dn => nil,
+ :allow_anonymous => false,
+ :retry_limit => 0)
+ end
+ assert_equal(user.class.connection, user.connection)
+
+ assert_nothing_raised do
+ user.establish_connection(:bind_dn => nil,
+ :allow_anonymous => true)
+ end
+ assert_not_equal(user.class.connection, user.connection)
+
+ assert_equal(user.connection, user.class.find(user.dn).connection)
+ assert_equal(user.connection, user.find(user.dn).connection)
+ ensure
+ user.remove_connection
+ end
+ end
+ end
+
+ def test_find
+ make_temporary_user do |user, password|
+ begin
+ make_temporary_user do |user2, password2|
+ user.establish_connection(:bind_dn => user.dn,
+ :password => password)
+ assert_not_equal(user.class.connection, user.connection)
+
+ found_user2 = user.find(user2.dn)
+ assert_not_equal(user2.connection, found_user2.connection)
+ assert_equal(user.connection, found_user2.connection)
+
+ assert_equal(found_user2.class.connection,
+ found_user2.class.find(found_user2.dn).connection)
+
+ found_user2.establish_connection(:bind_dn => user2.dn,
+ :password => password2)
+ assert_not_equal(user.connection, found_user2.connection)
+ assert_equal(user2.connection, found_user2.connection)
+ end
+ ensure
+ user.remove_connection
+ end
+ end
+ end
+
+ def test_associations
+ make_temporary_user do |user, password|
+ begin
+ make_temporary_group do |group1|
+ make_temporary_group do |group2|
+ user.groups = [group1]
+ assert_equal(group1.connection, user.connection)
+
+ user.establish_connection(:bind_dn => user.dn,
+ :password => password)
+ assert_not_equal(user.class.connection, user.connection)
+ assert_not_equal(group1.connection, user.connection)
+
+ assert_raise(ActiveLdap::LdapError::InsufficientAccess) do
+ user.groups << group2
+ end
+ assert_equal([group1.cn], user.groups.collect(&:cn))
+
+ assert_not_equal(group1.connection, user.connection)
+ assert_not_equal(user.groups[0].connection, user.connection)
+ user.reload
+ assert_equal(user.groups[0].connection, user.connection)
+
+ found_user = user.class.find(user.dn)
+ assert_equal(user.connection, found_user.connection)
+ assert_equal(found_user.connection,
+ found_user.groups[0].connection)
+ end
+ end
+ ensure
+ user.remove_connection
+ end
+ end
+ end
+end
From codesite-noreply at google.com Sat Aug 11 23:55:32 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 20:55:32 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r221 -
trunk/lib/active_ldap
Message-ID: <163600d6b30437789467459c1e686@google.com>
Author: koutou
Date: Sat Aug 11 20:55:12 2007
New Revision: 221
Modified:
trunk/lib/active_ldap/base.rb
trunk/lib/active_ldap/connection.rb
trunk/lib/active_ldap/operations.rb
Log:
* improved API.
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 20:55:12 2007
@@ -713,7 +713,10 @@
end
def establish_connection(config={})
- super
+ if config.is_a?(Hash)
+ config = {:bind_dn => dn, :allow_anonymous => false}.merge(config)
+ end
+ super(config)
before_connection = @connection
begin
@connection = nil
Modified: trunk/lib/active_ldap/connection.rb
==============================================================================
--- trunk/lib/active_ldap/connection.rb (original)
+++ trunk/lib/active_ldap/connection.rb Sat Aug 11 20:55:12 2007
@@ -165,6 +165,10 @@
conn || self.class.connection
end
+ def connected?
+ connection != self.class.connection
+ end
+
def connection=(adapter)
if adapter.nil? or adapter.is_a?(Adapter::Base)
@connection = adapter
Modified: trunk/lib/active_ldap/operations.rb
==============================================================================
--- trunk/lib/active_ldap/operations.rb (original)
+++ trunk/lib/active_ldap/operations.rb Sat Aug 11 20:55:12 2007
@@ -93,6 +93,10 @@
end
alias_method :exists?, :exist?
+ def count(options={})
+ search(options).size
+ end
+
private
def validate_search_options(options)
options.assert_valid_keys(VALID_SEARCH_OPTIONS)
From codesite-noreply at google.com Sun Aug 12 00:45:34 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 21:45:34 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r222 -
trunk/lib/active_ldap
Message-ID:
Author: koutou
Date: Sat Aug 11 21:45:04 2007
New Revision: 222
Modified:
trunk/lib/active_ldap/attributes.rb
trunk/lib/active_ldap/base.rb
Log:
* removed needless attributes= constraint.
* supported retrieving unique attribute names.
Modified: trunk/lib/active_ldap/attributes.rb
==============================================================================
--- trunk/lib/active_ldap/attributes.rb (original)
+++ trunk/lib/active_ldap/attributes.rb Sat Aug 11 21:45:04 2007
@@ -181,9 +181,9 @@
end
targets.collect do |key, value|
- [to_real_attribute_name(key), value]
+ [to_real_attribute_name(key) || key, value]
end.reject do |key, value|
- key.nil? or needless_attributes[key]
+ needless_attributes[key]
end
end
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 21:45:04 2007
@@ -463,10 +463,17 @@
#
# Return attribute methods so that a program can determine available
# attributes dynamically without schema awareness
- def attribute_names
+ def attribute_names(normalize=false)
logger.debug {"stub: attribute_names called"}
ensure_apply_object_class
- return @attr_methods.keys
+ names = @attr_methods.keys
+ if normalize
+ names.collect do |name|
+ to_real_attribute_name(name)
+ end.uniq
+ else
+ names
+ end
end
def attribute_present?(name)
@@ -616,7 +623,7 @@
# Updates a given attribute and saves immediately
def update_attribute(name, value)
- set_attribute(name, value) if have_attribute?(name)
+ send("#{name}=", value)
save
end
@@ -627,6 +634,11 @@
save
end
+ def update_attributes!(attrs)
+ self.attributes = attrs
+ save!
+ end
+
# This returns the key value pairs in @data with all values
# cloned
def attributes
@@ -642,7 +654,7 @@
def attributes=(hash_or_assoc)
targets = remove_attributes_protected_from_mass_assignment(hash_or_assoc)
targets.each do |key, value|
- set_attribute(key, value) if have_attribute?(key)
+ send("#{key}=", value)
end
end
From codesite-noreply at google.com Sun Aug 12 00:53:34 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 21:53:34 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r223 - in
trunk/lib/active_ldap: . adapter
Message-ID: <163600d06e04377963fc81d220b54@google.com>
Author: koutou
Date: Sat Aug 11 21:52:28 2007
New Revision: 223
Modified:
trunk/lib/active_ldap/adapter/base.rb
trunk/lib/active_ldap/attributes.rb
trunk/lib/active_ldap/base.rb
trunk/lib/active_ldap/validations.rb
Log:
* removed needless log messages:
benchmark(before):
user system total real
AL 0.770000 0.040000 0.810000 ( 1.131281)
AL(No Obj) 0.070000 0.000000 0.070000 ( 0.174508)
LDAP 0.010000 0.000000 0.010000 ( 0.023868)
benchamrk(after):
user system total real
AL 0.760000 0.040000 0.800000 ( 0.989990)
AL(No Obj) 0.020000 0.000000 0.020000 ( 0.140160)
LDAP 0.010000 0.000000 0.010000 ( 0.005545)
Entries processed by Ruby/ActiveLdap: 100
Entries processed by Ruby/ActiveLdap (without object creation): 100
Entries processed by Ruby/LDAP: 100
Modified: trunk/lib/active_ldap/adapter/base.rb
==============================================================================
--- trunk/lib/active_ldap/adapter/base.rb (original)
+++ trunk/lib/active_ldap/adapter/base.rb Sat Aug 11 21:52:28 2007
@@ -70,7 +70,6 @@
end
def bind_as_anonymous(options={})
- @logger.info {"Attempting anonymous authentication"}
operation(options) do
yield
end
@@ -136,7 +135,7 @@
end
rescue LdapError
# Do nothing on failure
- @logger.debug {"Ignore error #{$!.class}(#{$!.message}) " +
+ @logger.info {"Ignore error #{$!.class}(#{$!.message}) " +
"for #{filter} and attrs #{attrs.inspect}"}
end
@@ -280,7 +279,6 @@
bound?
end
rescue LdapError::InvalidDnSyntax
- @logger.debug {"DN is invalid: #{bind_dn}"}
raise DistinguishedNameInvalid.new(bind_dn)
rescue LdapError::InvalidCredentials
false
@@ -436,9 +434,11 @@
connect(options)
break
rescue => detail
- @logger.error {"Reconnect to server failed: #{detail.exception}"}
- @logger.error {"Reconnect to server failed backtrace:\n" +
- detail.backtrace.join("\n")}
+ @logger.error do
+ "Reconnect to server failed: #{detail.exception}\n" +
+ "Reconnect to server failed backtrace:\n" +
+ detail.backtrace.join("\n")
+ end
# Do not loop if forced
raise ConnectionError, detail.message if force
end
Modified: trunk/lib/active_ldap/attributes.rb
==============================================================================
--- trunk/lib/active_ldap/attributes.rb (original)
+++ trunk/lib/active_ldap/attributes.rb Sat Aug 11 21:52:28 2007
@@ -30,8 +30,6 @@
# Hashes are for subtypes
# Arrays are for multiple entries
def normalize_attribute(name, value)
- logger.debug {"stub: called normalize_attribute" +
- "(#{name.inspect}, #{value.inspect})"}
if name.nil?
raise RuntimeError, 'The first argument, name, must not be nil. ' +
'Please report this as a bug!'
@@ -142,8 +140,6 @@
# e.g. userCertificate;binary => "some_bin"
# becomes userCertificate => {"binary" => "some_bin"}
def normalize_attribute_options(attr, value)
- logger.debug {"stub: called normalize_attribute_options" +
- "(#{attr.inspect}, #{value.inspect})"}
return [attr, value] unless attr.match(/;/)
ret_attr, *options = attr.split(/;/)
@@ -156,7 +152,6 @@
# Extracts all of the subtypes from a given set of nested hashes
# and returns the attribute suffix and the final true value
def extract_attribute_options(value)
- logger.debug {"stub: called extract_attribute_options(#{value.inspect})"}
options = ''
ret_val = value
if value.class == Hash
Modified: trunk/lib/active_ldap/base.rb
==============================================================================
--- trunk/lib/active_ldap/base.rb (original)
+++ trunk/lib/active_ldap/base.rb Sat Aug 11 21:52:28 2007
@@ -464,7 +464,6 @@
# Return attribute methods so that a program can determine available
# attributes dynamically without schema awareness
def attribute_names(normalize=false)
- logger.debug {"stub: attribute_names called"}
ensure_apply_object_class
names = @attr_methods.keys
if normalize
@@ -499,7 +498,6 @@
#
# Return the authoritative dn
def dn
- logger.debug {"stub: dn called"}
dn_value = id
if dn_value.nil?
raise DistinguishedNameNotSetError.new,
@@ -527,7 +525,6 @@
#
# Delete this entry from LDAP
def destroy
- logger.debug {"stub: delete called"}
begin
self.class.delete(dn)
@new_entry = true
@@ -563,29 +560,23 @@
# using class_eval instead of using method_missing. This would
# give tab completion in irb.
def method_missing(name, *args, &block)
- logger.debug {"stub: called method_missing" +
- "(#{name.inspect}, #{args.inspect})"}
ensure_apply_object_class
key = name.to_s
case key
when /=$/
real_key = $PREMATCH
- logger.debug {"method_missing: have_attribute? #{real_key}"}
if have_attribute?(real_key, ['objectClass'])
if args.size != 1
raise ArgumentError,
"wrong number of arguments (#{args.size} for 1)"
end
- logger.debug {"method_missing: calling set_attribute" +
- "(#{real_key}, #{args.inspect})"}
return set_attribute(real_key, *args, &block)
end
when /(?:(_before_type_cast)|(\?))?$/
real_key = $PREMATCH
before_type_cast = !$1.nil?
query = !$2.nil?
- logger.debug {"method_missing: have_attribute? #{real_key}"}
if have_attribute?(real_key, ['objectClass'])
if args.size > 1
raise ArgumentError,
@@ -814,12 +805,9 @@
# This means that if you set userCertificate to somebinary value, it will
# wrap it up correctly.
def enforce_type(key, value)
- logger.debug {"stub: enforce_type called"}
ensure_apply_object_class
# Enforce attribute value formatting
- result = normalize_attribute(key, value)[1]
- logger.debug {"stub: enforce_types done"}
- result
+ normalize_attribute(key, value)[1]
end
def init_instance_variables
@@ -843,7 +831,6 @@
# removing defined attributes that are no longer valid
# given the new objectclasses.
def apply_object_class(val)
- logger.debug {"stub: objectClass=(#{val.inspect}) called"}
new_oc = val
new_oc = [val] if new_oc.class != Array
new_oc = new_oc.uniq
@@ -885,7 +872,6 @@
alias_method :base_of_class, :base
def base
- logger.debug {"stub: called base"}
[@base, base_of_class].compact.join(",")
end
@@ -909,14 +895,10 @@
#
# Return the value of the attribute called by method_missing?
def get_attribute(name, force_array=false)
- logger.debug {"stub: called get_attribute" +
- "(#{name.inspect}, #{force_array.inspect}"}
get_attribute_before_type_cast(name, force_array)
end
def get_attribute_as_query(name, force_array=false)
- logger.debug {"stub: called get_attribute_as_query" +
- "(#{name.inspect}, #{force_array.inspect}"}
value = get_attribute_before_type_cast(name, force_array)
if force_array
value.collect {|x| !false_value?(x)}
@@ -931,8 +913,6 @@
end
def get_attribute_before_type_cast(name, force_array=false)
- logger.debug {"stub: called get_attribute_before_type_cast" +
- "(#{name.inspect}, #{force_array.inspect}"}
attr = to_real_attribute_name(name)
value = @data[attr] || []
@@ -948,9 +928,6 @@
#
# Set the value of the attribute called by method_missing?
def set_attribute(name, value)
- logger.debug {"stub: called set_attribute" +
- "(#{name.inspect}, #{value.inspect})"}
-
# Get the attr and clean up the input
attr = to_real_attribute_name(name)
raise UnknownAttribute.new(name) if attr.nil?
@@ -959,11 +936,7 @@
value, @base = split_dn_value(value)
end
- logger.debug {"set_attribute(#{name.inspect}, #{value.inspect}): " +
- "method maps to #{attr}"}
-
# Enforce LDAP-pleasing values
- logger.debug {"value = #{value.inspect}, value.class = #{value.class}"}
real_value = value
# Squash empty values
if value.class == Array
@@ -979,7 +952,6 @@
@data[attr] = enforce_type(attr, real_value)
# Return the passed in value
- logger.debug {"stub: exiting set_attribute"}
@data[attr]
end
@@ -1007,19 +979,12 @@
# Make a method entry for _every_ alias of a valid attribute and map it
# onto the first attribute passed in.
def define_attribute_methods(attr)
- logger.debug {"stub: called define_attribute_methods(#{attr.inspect})"}
return if @attr_methods.has_key?(attr)
schema.attribute_aliases(attr).each do |ali|
- logger.debug {"associating #{ali} --> #{attr}"}
@attr_methods[ali] = attr
- logger.debug {"associating #{Inflector.underscore(ali)}" +
- " --> #{attr}"}
@attr_aliases[Inflector.underscore(ali)] = attr
- logger.debug {"associating #{normalize_attribute_name(ali)}" +
- " --> #{attr}"}
@normalized_attr_names[normalize_attribute_name(ali)] = attr
end
- logger.debug {"stub: leaving define_attribute_methods(#{attr.inspect})"}
end
# array_of
@@ -1027,8 +992,6 @@
# Returns the array form of a value, or not an array if
# false is passed in.
def array_of(value, to_a=true)
- logger.debug {"stub: called array_of" +
- "(#{value.inspect}, #{to_a.inspect})"}
case value
when Array
if to_a or value.size > 1
@@ -1071,8 +1034,6 @@
# Now that all the options will be treated as unique attributes
# we can see what's changed and add anything that is brand-spankin'
# new.
- logger.debug {'#collect_modified_attributes: traversing ldap_data ' +
- 'determining replaces and deletes'}
ldap_data.each do |k, v|
value = data[k] || []
@@ -1083,28 +1044,20 @@
# Since some types do not have equality matching rules,
# delete doesn't work
# Replacing with nothing is equivalent.
- logger.debug {"#save: removing attribute: #{k}"}
if !data.has_key?(k) and schema.binary_required?(k)
value = [{'binary' => []}]
end
else
# Ditched delete then replace because attribs with no equality
# match rules will fails
- logger.debug {"#collect_modified_attributes: updating attribute:" +
- " #{k}: #{value.inspect}"}
end
attributes.push([:replace, k, value])
end
- logger.debug {'#collect_modified_attributes: finished traversing' +
- ' ldap_data'}
- logger.debug {'#collect_modified_attributes: traversing data ' +
- 'determining adds'}
data.each do |k, v|
value = v || []
next if ldap_data.has_key?(k) or value.empty?
# Detect subtypes and account for them
- logger.debug {"#save: adding attribute: #{k}: #{value.inspect}"}
# REPLACE will function like ADD, but doesn't hit EQUALITY problems
# TODO: Added equality(attr) to Schema
attributes.push([:replace, k, value])
@@ -1116,22 +1069,15 @@
def collect_all_attributes(data)
dn_attr = to_real_attribute_name(dn_attribute)
dn_value = data[dn_attr]
- logger.debug {'#collect_all_attributes: adding all attribute value pairs'}
- logger.debug {"#collect_all_attributes: adding " +
- "#{dn_attr.inspect} = #{dn_value.inspect}"}
attributes = []
attributes.push([:add, dn_attr, dn_value])
oc_value = data['objectClass']
- logger.debug {"#collect_all_attributes: adding objectClass = " +
- "#{oc_value.inspect}"}
attributes.push([:add, 'objectClass', oc_value])
data.each do |key, value|
next if value.empty? or key == 'objectClass' or key == dn_attr
- logger.debug {"#collect_all_attributes: adding attribute: " +
- "#{key.inspect}: #{value.inspect}"}
attributes.push([:add, key, value])
end
@@ -1150,46 +1096,33 @@
end
def prepare_data_for_saving
- logger.debug {"stub: save called"}
-
# Expand subtypes to real ldap_data attributes
# We can't reuse @ldap_data because an exception would leave
# an object in an unknown state
- logger.debug {"#save: expanding subtypes in @ldap_data"}
ldap_data = normalize_data(@ldap_data)
- logger.debug {'#save: subtypes expanded for @ldap_data'}
# Expand subtypes to real data attributes, but leave @data alone
- logger.debug {'#save: expanding subtypes for @data'}
bad_attrs = @data.keys - attribute_names
data = normalize_data(@data, bad_attrs)
- logger.debug {'#save: subtypes expanded for @data'}
success = yield(data, ldap_data)
if success
- logger.debug {"#save: resetting @ldap_data to a dup of @data"}
@ldap_data = Marshal.load(Marshal.dump(data))
# Delete items disallowed by objectclasses.
# They should have been removed from ldap.
- logger.debug {'#save: removing attributes from @ldap_data not ' +
- 'sent in data'}
bad_attrs.each do |remove_me|
@ldap_data.delete(remove_me)
end
- logger.debug {'#save: @ldap_data reset complete'}
end
- logger.debug {'stub: save exited'}
success
end
def create
prepare_data_for_saving do |data, ldap_data|
attributes = collect_all_attributes(data)
- logger.debug {"#create: adding #{dn}"}
add_entry(dn, attributes)
- logger.debug {"#create: add successful"}
@new_entry = false
true
end
@@ -1198,10 +1131,7 @@
def update
prepare_data_for_saving do |data, ldap_data|
attributes = collect_modified_attributes(ldap_data, data)
- logger.debug {'#update: traversing data complete'}
- logger.debug {"#update: modifying #{dn}"}
modify_entry(dn, attributes)
- logger.debug {'#update: modify successful'}
true
end
end
Modified: trunk/lib/active_ldap/validations.rb
==============================================================================
--- trunk/lib/active_ldap/validations.rb (original)
+++ trunk/lib/active_ldap/validations.rb Sat Aug 11 21:52:28 2007
@@ -37,8 +37,6 @@
# Basic validation:
# - Verify that every 'MUST' specified in the schema has a value defined
def validate_required_values
- logger.debug {"stub: validate_required_values called"}
-
# Make sure all MUST attributes have a value
@musts.each do |object_class, attributes|
attributes.each do |required_attribute|
@@ -60,7 +58,6 @@
end
end
end
- logger.debug {"stub: validate_required_values finished"}
end
private
From codesite-noreply at google.com Sun Aug 12 02:31:45 2007
From: codesite-noreply at google.com (codesite-noreply at google.com)
Date: Sat, 11 Aug 2007 23:31:45 -0700
Subject: [Ruby-activeldap-commit] [ruby-activeldap commit] r224 - in
al-admin/trunk: app/controllers app/helpers app/models
app/views/account app/views/layo...
Message-ID: <163600d1b504377ac31d4a362754c@google.com>
Author: koutou
Date: Sat Aug 11 23:30:20 2007
New Revision: 224
Added:
al-admin/trunk/app/controllers/account_controller.rb
al-admin/trunk/app/controllers/users_controller.rb
al-admin/trunk/app/controllers/welcome_controller.rb
al-admin/trunk/app/helpers/account_helper.rb
al-admin/trunk/app/helpers/users_helper.rb
al-admin/trunk/app/helpers/welcome_helper.rb
al-admin/trunk/app/models/ldap_user.rb
al-admin/trunk/app/models/user.rb
al-admin/trunk/app/views/account/
al-admin/trunk/app/views/account/index.rhtml
al-admin/trunk/app/views/account/login.rhtml
al-admin/trunk/app/views/account/signup.rhtml
al-admin/trunk/app/views/layouts/application.rhtml
al-admin/trunk/app/views/users/
al-admin/trunk/app/views/users/_entry.rhtml
al-admin/trunk/app/views/users/_form.rhtml
al-admin/trunk/app/views/users/edit.rhtml
al-admin/trunk/app/views/users/index.rhtml
al-admin/trunk/app/views/users/show.rhtml
al-admin/trunk/app/views/welcome/
al-admin/trunk/app/views/welcome/index.rhtml
al-admin/trunk/db/migrate/
al-admin/trunk/db/migrate/001_create_users.rb
al-admin/trunk/lib/authenticated_system.rb
al-admin/trunk/lib/authenticated_test_helper.rb
al-admin/trunk/public/stylesheets/rails.css
al-admin/trunk/public/stylesheets/screen.css
al-admin/trunk/test/fixtures/users.yml
al-admin/trunk/test/functional/account_controller_test.rb
al-admin/trunk/test/functional/users_controller_test.rb
al-admin/trunk/test/functional/welcome_controller_test.rb
al-admin/trunk/test/run-test.sh (contents, props changed)
al-admin/trunk/test/unit/user_test.rb
Removed:
al-admin/trunk/public/index.html
Modified:
al-admin/trunk/app/controllers/application.rb
al-admin/trunk/config/boot.rb
al-admin/trunk/config/environment.rb
al-admin/trunk/config/routes.rb
al-admin/trunk/vendor/plugins/ (props changed)
Log:
* implemeneted login by LDAP.
Added: al-admin/trunk/app/controllers/account_controller.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/controllers/account_controller.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,49 @@
+class AccountController < ApplicationController
+ # say something nice, you goof! something sweet.
+ def index
+ if logged_in?
+ redirect_to(top_path)
+ else
+ redirect_to(:action => 'login')
+ end
+ end
+
+ def login
+ return unless request.post?
+ self.current_user = User.authenticate(params[:login], params[:password])
+ if logged_in?
+ if params[:remember_me] == "1"
+ current_user.remember_me
+ cookies[:auth_token] = {
+ :value => current_user.remember_token,
+ :expires => current_user.remember_token_expires_at
+ }
+ end
+ redirect_back_or_default(top_url)
+ flash[:notice] = "Logged in successfully"
+ else
+ flash[:notice] = "Login or Password is incorrect"
+ end
+ end
+
+ def signup
+ @user = LdapUser.new(params[:user])
+ return unless request.post?
+ if @user.save
+ @system_user = User.create(:login => @user.id)
+ unless @system_user.new_record?
+ self.current_user = @system_user
+ redirect_back_or_default(top_path)
+ flash[:notice] = "Thanks for signing up!"
+ end
+ end
+ end
+
+ def logout
+ current_user.forget_me if logged_in?
+ cookies.delete :auth_token
+ reset_session
+ flash[:notice] = "You have been logged out."
+ redirect_back_or_default(top_path)
+ end
+end
Modified: al-admin/trunk/app/controllers/application.rb
==============================================================================
--- al-admin/trunk/app/controllers/application.rb (original)
+++ al-admin/trunk/app/controllers/application.rb Sat Aug 11 23:30:20 2007
@@ -2,6 +2,9 @@
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
+ include AuthenticatedSystem
+ before_filter :login_from_cookie
+
# Pick a unique cookie name to distinguish our session data from others'
session :session_key => '_al-admin_session_id'
end
Added: al-admin/trunk/app/controllers/users_controller.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/controllers/users_controller.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,36 @@
+class UsersController < ApplicationController
+ verify :method => :post, :only => [:update],
+ :redirect_to => {:action => :index}
+
+ def index
+ @users = find(:all)
+ end
+
+ def show
+ @user = find(params[:id])
+ end
+
+ def edit
+ @user = find(params[:id])
+ end
+
+ def update
+ @user = find(params[:id])
+ previous_user_password = @user.user_password
+ if @user.update_attributes(params[:user])
+ if previous_user_password != @user.user_password
+ @user.establish_connection(:password => @user.password)
+ end
+ flash[:notice] = 'User was successfully updated.'
+ redirect_to :action => 'show', :id => @user
+ else
+ @user.password = @user.password_confirmation = nil
+ render :action => 'edit'
+ end
+ end
+
+ private
+ def find(*args)
+ current_user.ldap_user.find(*args)
+ end
+end
Added: al-admin/trunk/app/controllers/welcome_controller.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/controllers/welcome_controller.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,5 @@
+class WelcomeController < ApplicationController
+ def index
+ redirect_to(login_path) unless logged_in?
+ end
+end
Added: al-admin/trunk/app/helpers/account_helper.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/helpers/account_helper.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,2 @@
+module AccountHelper
+end
\ No newline at end of file
Added: al-admin/trunk/app/helpers/users_helper.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/helpers/users_helper.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,2 @@
+module UsersHelper
+end
Added: al-admin/trunk/app/helpers/welcome_helper.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/helpers/welcome_helper.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,2 @@
+module WelcomeHelper
+end
Added: al-admin/trunk/app/models/ldap_user.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/models/ldap_user.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,46 @@
+require 'active_ldap/user_password'
+
+class LdapUser < ActiveLdap::Base
+ ldap_mapping :prefix => "ou=Users",
+ :classes => ["posixAccount"],
+ :dn_attribute => "uid"
+
+ attr_accessor :password
+
+ validates_presence_of :password, :if => :password_required?
+ validates_presence_of :password_confirmation, :if => :password_required?
+ validates_length_of :password, :within => 4..40, :if => :password_required?
+ validates_confirmation_of :password, :if => :password_required?
+ before_save :encrypt_password
+
+ class << self
+ def authenticate(dn, password)
+ user = find(dn)
+ user.authenticated?(password) ? user : nil
+ rescue ActiveLdap::EntryNotFound
+ nil
+ end
+ end
+
+ def authenticated?(password)
+ establish_connection(:password => password)
+ true
+ rescue ActiveLdap::AuthenticationError
+ false
+ end
+
+ private
+ def encrypt_password
+ return if password.blank?
+ if /\A\{([A-Z][A-Z\d]+)\}/ =~ userPassword.to_s
+ hash_type = $1.downcase
+ self.user_password = ActiveLdap::UserPassword.send(hash_type, password)
+ else
+ self.user_password = password
+ end
+ end
+
+ def password_required?
+ !password.blank?
+ end
+end
Added: al-admin/trunk/app/models/user.rb
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/models/user.rb Sat Aug 11 23:30:20 2007
@@ -0,0 +1,60 @@
+require 'digest/sha1'
+class User < ActiveRecord::Base
+ validates_presence_of :login
+ validates_presence_of :dn
+ validates_uniqueness_of :login, :dn, :case_sensitive => false
+ before_validation :find_dn
+
+ # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
+ def self.authenticate(login, password)
+ u = find_by_login(login) # need to get the salt
+ if u.nil?
+ u = new
+ u.login = login
+ u = nil unless u.save
+ end
+ u && u.authenticated?(password) ? u : nil
+ end
+
+ def authenticated?(password)
+ return false if ldap_user.nil?
+ ldap_user.authenticated?(password)
+ end
+
+ def ldap_user
+ @ldap_user ||= LdapUser.find(dn)
+ end
+
+ def remember_token?
+ remember_token_expires_at && Time.now.utc < remember_token_expires_at
+ end
+
+ # These create and unset the fields required for remembering users between browser closes
+ def remember_me
+ self.remember_token_expires_at = 2.weeks.from_now.utc
+ self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
+ save(false)
+ end
+
+ def forget_me
+ self.remember_token_expires_at = nil
+ self.remember_token = nil
+ save(false)
+ LdapUser.remove_connection(dn) if dn
+ @ldap_user = nil
+ end
+
+ private
+ def find_dn
+ if login.blank?
+ self.dn = nil
+ else
+ begin
+ ldap_user = LdapUser.find(login)
+ self.dn = ldap_user.dn
+ rescue ActiveLdap::EntryNotFound
+ self.dn = nil
+ end
+ end
+ end
+end
Added: al-admin/trunk/app/views/account/index.rhtml
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/views/account/index.rhtml Sat Aug 11 23:30:20 2007
@@ -0,0 +1,56 @@
+
In the Caboose.
+
+<% content_for 'poem' do -%>
+"Train delayed? and what's to say?"
+"Blocked by last night's snow they say."
+Seven hours or so to wait;
+Well, that's pleasant! but there's the freight.
+Depot loafing no one fancies,
+We'll try the caboose and take our chances.
+
+Cool this morning in Watertown,
+Somewhat frosty___mercury down;
+Enter caboose___roaring fire,
+With never an air-hole; heat so dire
+That we shrivel and pant; we are roasted through-
+Outside, thermometer thirty-two.
+
+We start with a jerk and suddenly stop.
+"What's broke?" says one; another "What's up?",
+"Oh, nothing," they answer, "That's our way:
+You must stand the jerking, sorry to say."
+We "stand it" with oft this painful thought:
+Are our heads on yet, or are they not?
+
+Comrades in misery___let me see;
+Girl like a statue opposite me;
+Back and forth the others jostle___
+She never winks, nor moves a muscle;
+See her, as she sits there now;
+She's "well balanced," anyhow.
+
+Woman in trouble, tearful eyes,
+Sits by the window, softly cries,
+Pity___for griefs we may not know,
+For breasts that ache, for tears that flow,
+Though we know not why. Her eyelids red
+Tell a sorrowful tale___some hope is dead.
+
+Man who follows the Golden Rule,
+And lends his papers___a pocket full,
+Has a blank book___once in a minute
+Has an idea, and writes it in it.
+Guess him? Yes, of course I can,
+He's a___well___a newspaper man.
+
+Blue-eyed fairy, wrapped in fur;
+Sweet young mother tending her.
+Fairy thinks it's "awful far,"
+Wants to get off this "naughty car."
+So do we, young golden-hair;
+All this crowd are with you there!
+<% end -%>
+
+<%= simple_format @content_for_poem %>
+
+
\ No newline at end of file
Added: al-admin/trunk/app/views/account/login.rhtml
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/views/account/login.rhtml Sat Aug 11 23:30:20 2007
@@ -0,0 +1,12 @@
+<% form_tag do -%>
+
+<%= text_field_tag 'login' %>
+
+
+<%= password_field_tag 'password' %>
+
+
+<%= check_box_tag 'remember_me' %>
+
+
<%= submit_tag 'Log in' %>
+<% end -%>
Added: al-admin/trunk/app/views/account/signup.rhtml
==============================================================================
--- (empty file)
+++ al-admin/trunk/app/views/account/signup.rhtml Sat Aug 11 23:30:20 2007
@@ -0,0 +1,14 @@
+<%= error_messages_for :user %>
+<%= error_messages_for :system_user %>
+<% form_for :user do |f| -%>
+