dm-ldap-adapter 0.4.3-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +75 -0
- data/MIT-LICENSE +20 -0
- data/README.md +247 -0
- data/ldap-commands.txt +17 -0
- data/lib/adapters/ldap_adapter.rb +370 -0
- data/lib/adapters/noop_transaction.rb +35 -0
- data/lib/dm-ldap-adapter.rb +1 -0
- data/lib/dummy_ldap_resource.rb +60 -0
- data/lib/ldap/array.rb +122 -0
- data/lib/ldap/conditions_2_filter.rb +95 -0
- data/lib/ldap/digest.rb +30 -0
- data/lib/ldap/net_ldap_facade.rb +161 -0
- data/lib/ldap/ruby_ldap_facade.rb +201 -0
- data/lib/ldap/transactions.rb +2 -0
- data/lib/ldap/unboundid_ldap_facade.rb +188 -0
- data/lib/ldap/version.rb +3 -0
- data/lib/ldap_resource.rb +189 -0
- data/spec/assiociations_ldap_adapter_spec.rb +179 -0
- data/spec/authentication_ldap_adapter_spec.rb +32 -0
- data/spec/contact.rb +58 -0
- data/spec/ldap_adapter_spec.rb +239 -0
- data/spec/ldap_array_spec.rb +119 -0
- data/spec/multi_repository_spec.rb +79 -0
- data/spec/multi_value_attributes_spec.rb +161 -0
- data/spec/performance_spec.rb.omit +67 -0
- data/spec/sorting_spec.rb +61 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +163 -0
- metadata +354 -0
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require "dm-core"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Ldap
         | 
| 4 | 
            +
              class NoopTransaction
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                def close ; end
         | 
| 7 | 
            +
                def begin ; end
         | 
| 8 | 
            +
                def prepare ; end
         | 
| 9 | 
            +
                def commit ; end
         | 
| 10 | 
            +
                def rollback ; end
         | 
| 11 | 
            +
                def rollback_prepared ; end
         | 
| 12 | 
            +
                
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            module DataMapper
         | 
| 17 | 
            +
              module Adapters
         | 
| 18 | 
            +
                class LdapAdapter
         | 
| 19 | 
            +
                  def transaction_primitive
         | 
| 20 | 
            +
                    ::Ldap::NoopTransaction.new
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  def push_transaction(transaction)
         | 
| 23 | 
            +
                    @transaction = transaction
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def pop_transaction
         | 
| 27 | 
            +
                    @transaction
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  
         | 
| 30 | 
            +
                  def current_transaction
         | 
| 31 | 
            +
                    @transaction
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            require 'adapter/ldap-adapter'
         | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            require 'slf4r/logger'
         | 
| 2 | 
            +
            require 'ldap/digest'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            # dummy implementation which turns the extra ldap configuration noops
         | 
| 5 | 
            +
            module DataMapper
         | 
| 6 | 
            +
              module Resource
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                module ClassMethods
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  include ::Slf4r::Logger
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def ldap_properties(resource = nil, &block)
         | 
| 13 | 
            +
                    if block
         | 
| 14 | 
            +
                      @ldap_properties = block
         | 
| 15 | 
            +
                    elsif resource.instance_of? Hash
         | 
| 16 | 
            +
                      @ldap_properties = resource
         | 
| 17 | 
            +
                      logger.debug { "ldap_properties=#{@ldap_properties.inspect}" }
         | 
| 18 | 
            +
                    elsif resource
         | 
| 19 | 
            +
                      logger.debug { "ldap_properties=#{@ldap_properties.call(resource).inspect}" }
         | 
| 20 | 
            +
                    else
         | 
| 21 | 
            +
                      logger.debug { "ldap_properties=#{@ldap_properties.inspect}" }
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def treebase(resource = nil, &block)
         | 
| 26 | 
            +
                    if block
         | 
| 27 | 
            +
                      @treebase = block
         | 
| 28 | 
            +
                    elsif resource.instance_of? String
         | 
| 29 | 
            +
                      @treebase = resource
         | 
| 30 | 
            +
                      logger.debug { "treebase=#{@treebase.inspect}" }
         | 
| 31 | 
            +
                    elsif resource
         | 
| 32 | 
            +
                      logger.debug { "treebase=#{@treebase.call(resource).inspect}" }
         | 
| 33 | 
            +
                    else
         | 
| 34 | 
            +
                      logger.debug { "treebase=#{@treebase}" }
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def dn_prefix(resource = nil, &block)
         | 
| 39 | 
            +
                    if block
         | 
| 40 | 
            +
                      @dn_prefix = block
         | 
| 41 | 
            +
                    elsif resource.instance_of? Hash
         | 
| 42 | 
            +
                      @dn_prefix = resource
         | 
| 43 | 
            +
                      logger.debug { "dn_prefix=#{@dn_prefix.inspect}" }
         | 
| 44 | 
            +
                    elsif resource
         | 
| 45 | 
            +
                      logger.debug { "dn_prefix=#{@dn_prefix.call(resource).inspect}" }
         | 
| 46 | 
            +
                    else
         | 
| 47 | 
            +
                      logger.debug { "dn_prefix=#{dn_prefix}" }
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def multivalue_field(field = nil)
         | 
| 52 | 
            +
                    logger.debug { "multivalue_field = #{field}" } if field
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def authenticate(password)
         | 
| 57 | 
            +
                  raise "NotImplemented"
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
    
        data/lib/ldap/array.rb
    ADDED
    
    | @@ -0,0 +1,122 @@ | |
| 1 | 
            +
            require 'dm-core'
         | 
| 2 | 
            +
            module Ldap
         | 
| 3 | 
            +
              class Array < ::Array
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(resource, property,  *args)
         | 
| 6 | 
            +
                  setup(resource, property)
         | 
| 7 | 
            +
                  super(args)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def setup(resource, property)
         | 
| 11 | 
            +
                  @resource = resource
         | 
| 12 | 
            +
                  @property = property
         | 
| 13 | 
            +
                  self
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                alias :push! :push
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def []=(k, v)
         | 
| 19 | 
            +
                  ar = [self].flatten
         | 
| 20 | 
            +
                  ar[k] = v
         | 
| 21 | 
            +
                  @resource.send("#{@property.name}=".to_sym, ar)
         | 
| 22 | 
            +
                  super
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def <<(element)
         | 
| 26 | 
            +
                  push(element)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def push(element)
         | 
| 30 | 
            +
                  ar = [self].flatten
         | 
| 31 | 
            +
                  ar.push(element)
         | 
| 32 | 
            +
                  @resource.send("#{@property.name}=".to_sym, ar)
         | 
| 33 | 
            +
                  super
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
               alias :delete! :delete
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def delete(element)
         | 
| 39 | 
            +
                  ar = [self].flatten
         | 
| 40 | 
            +
                  ar.delete(element)
         | 
| 41 | 
            +
                  @resource.send(:"#{@property.name}=", ar)
         | 
| 42 | 
            +
                  super
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              class LdapArray < ::DataMapper::Property::Text 
         | 
| 47 | 
            +
                
         | 
| 48 | 
            +
                default Proc.new { |r,p| Ldap::Array.new(r,p) }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def custom?
         | 
| 51 | 
            +
                  true
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def primitive?(value)
         | 
| 55 | 
            +
                  super || value.kind_of?(::Array)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def load(value)
         | 
| 59 | 
            +
                  result = case value
         | 
| 60 | 
            +
                           when ::String then value[1, value.size-2].split('","').to_a.freeze
         | 
| 61 | 
            +
                           when ::Array then value.freeze
         | 
| 62 | 
            +
                           else
         | 
| 63 | 
            +
                             []
         | 
| 64 | 
            +
                           end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def dump(value)
         | 
| 68 | 
            +
                  result = case value
         | 
| 69 | 
            +
                           when LdapArray then '"' + value.join('","') + '"'
         | 
| 70 | 
            +
                           when ::Array then '"' + value.join('","') + '"'
         | 
| 71 | 
            +
                           when ::String then '"' + value.to_s + '"'
         | 
| 72 | 
            +
                           else
         | 
| 73 | 
            +
                             nil
         | 
| 74 | 
            +
                           end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # keep the *args so it works for both DM-1.1.x and DM-1.0.x
         | 
| 78 | 
            +
                def initialize(_model = nil, _name = nil, options = {}, *args)
         | 
| 79 | 
            +
                  super
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  add_writer(model,name) unless options[:writer] == :private || options[:accessor] == :private
         | 
| 82 | 
            +
                  add_reader(model,name) unless options[:reader] == :private || options[:accessor] == :private        
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                private
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def add_reader(model, name)
         | 
| 88 | 
            +
                  #Creates instance method for reader
         | 
| 89 | 
            +
                  model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 90 | 
            +
                    def #{name}
         | 
| 91 | 
            +
                     attr_data = attribute_get(:#{name})
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                     case attr_data
         | 
| 94 | 
            +
                     when Ldap::Array
         | 
| 95 | 
            +
                       attr_data.setup(self, properties[:#{name}])
         | 
| 96 | 
            +
                     else
         | 
| 97 | 
            +
                       new_ldap_array = Ldap::Array.new(self, properties[:#{name}])
         | 
| 98 | 
            +
                       new_ldap_array.replace(attr_data || [])
         | 
| 99 | 
            +
                     end
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  RUBY
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                def add_writer(model, name)
         | 
| 105 | 
            +
                  #Creates instance method for writer
         | 
| 106 | 
            +
                  model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
         | 
| 107 | 
            +
                    def #{name}=(input)
         | 
| 108 | 
            +
                      data = case input
         | 
| 109 | 
            +
                      when Ldap::Array
         | 
| 110 | 
            +
                        input.setup(self, properties[:#{name}])
         | 
| 111 | 
            +
                      else
         | 
| 112 | 
            +
                        new_ldap_array = Ldap::Array.new(self, properties[:#{name}])
         | 
| 113 | 
            +
                        new_ldap_array.replace(input || [])
         | 
| 114 | 
            +
                      end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                      attribute_set(:#{name}, data)
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
                  RUBY
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
            end
         | 
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            require 'net/ldap'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Ldap
         | 
| 4 | 
            +
              class Conditions2Filter
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                @@logger = ::Slf4r::LoggerFacade.new(::Ldap::Conditions2Filter)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # @param Array of conditions for the search
         | 
| 9 | 
            +
                # @return Array of Hashes with a name/values pair for each attribute
         | 
| 10 | 
            +
                def self.convert(conditions)
         | 
| 11 | 
            +
                  @@logger.debug { "conditions #{conditions.inspect}" }
         | 
| 12 | 
            +
                  filters = []
         | 
| 13 | 
            +
                  conditions.each do |cond|
         | 
| 14 | 
            +
                    c = cond[2]
         | 
| 15 | 
            +
                    case cond[0]
         | 
| 16 | 
            +
                    when :or_operator
         | 
| 17 | 
            +
                      f = nil
         | 
| 18 | 
            +
                      cond[1].each do |cc|
         | 
| 19 | 
            +
                        ff = case cc[0]
         | 
| 20 | 
            +
                             when :eql
         | 
| 21 | 
            +
                               Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s )
         | 
| 22 | 
            +
                             when :gte
         | 
| 23 | 
            +
                               Net::LDAP::Filter.ge( cc[1].to_s, cc[2].to_s )
         | 
| 24 | 
            +
                             when :lte
         | 
| 25 | 
            +
                               Net::LDAP::Filter.le( cc[1].to_s, cc[2].to_s )
         | 
| 26 | 
            +
                             when :like
         | 
| 27 | 
            +
                               Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
         | 
| 28 | 
            +
                             else
         | 
| 29 | 
            +
                               logger.error(cc[0].to_s + " needs coding")
         | 
| 30 | 
            +
                             end
         | 
| 31 | 
            +
                        if f
         | 
| 32 | 
            +
                          f = f | ff
         | 
| 33 | 
            +
                        else
         | 
| 34 | 
            +
                          f = ff
         | 
| 35 | 
            +
                        end
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
                    when :eql
         | 
| 38 | 
            +
                      if c.nil?
         | 
| 39 | 
            +
                        f = ~ Net::LDAP::Filter.pres( cond[1].to_s )
         | 
| 40 | 
            +
                      elsif c.respond_to? :each
         | 
| 41 | 
            +
                        f = nil
         | 
| 42 | 
            +
                        c.each do |cc|
         | 
| 43 | 
            +
                          if f
         | 
| 44 | 
            +
                            f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
         | 
| 45 | 
            +
                          else
         | 
| 46 | 
            +
                            f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
         | 
| 47 | 
            +
                          end
         | 
| 48 | 
            +
                        end
         | 
| 49 | 
            +
                        #elsif c.class == Range
         | 
| 50 | 
            +
                        #  p c
         | 
| 51 | 
            +
                        #  f = Net::LDAP::Filter.ge( cond[1].to_s, c.begin.to_s ) & Net::LDAP::Filter.le( cond[1].to_s, c.end.to_s )
         | 
| 52 | 
            +
                      else
         | 
| 53 | 
            +
                        f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                    when :gte
         | 
| 56 | 
            +
                      f = Net::LDAP::Filter.ge( cond[1].to_s, c.to_s )
         | 
| 57 | 
            +
                    when :lte
         | 
| 58 | 
            +
                      f = Net::LDAP::Filter.le( cond[1].to_s, c.to_s )
         | 
| 59 | 
            +
                    when :not
         | 
| 60 | 
            +
                        if c.nil?
         | 
| 61 | 
            +
                          f = Net::LDAP::Filter.pres( cond[1].to_s )
         | 
| 62 | 
            +
                        elsif c.respond_to? :each
         | 
| 63 | 
            +
                          f = nil
         | 
| 64 | 
            +
                          c.each do |cc|
         | 
| 65 | 
            +
                          if f
         | 
| 66 | 
            +
                            f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
         | 
| 67 | 
            +
                          else
         | 
| 68 | 
            +
                            f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
         | 
| 69 | 
            +
                          end
         | 
| 70 | 
            +
                        end
         | 
| 71 | 
            +
                          f = ~ f
         | 
| 72 | 
            +
                        else
         | 
| 73 | 
            +
                          f = ~ Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
         | 
| 74 | 
            +
                        end
         | 
| 75 | 
            +
                    when :like
         | 
| 76 | 
            +
                      f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
         | 
| 77 | 
            +
                    else
         | 
| 78 | 
            +
                      logger.error(cond[0].to_s + " needs coding")
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                    filters << f if f
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  filter = nil
         | 
| 84 | 
            +
                  filters.each do |f|
         | 
| 85 | 
            +
                    if filter.nil?
         | 
| 86 | 
            +
                      filter = f
         | 
| 87 | 
            +
                    else
         | 
| 88 | 
            +
                      filter = filter & f
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                  @@logger.debug { "search filter: (#{filter.to_s})" }
         | 
| 92 | 
            +
                  filter
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
    
        data/lib/ldap/digest.rb
    ADDED
    
    | @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            begin
         | 
| 2 | 
            +
              require 'sha1'
         | 
| 3 | 
            +
            rescue LoadError
         | 
| 4 | 
            +
              # ruby1.9.x
         | 
| 5 | 
            +
              require 'digest/sha1'
         | 
| 6 | 
            +
              SHA1 = Digest::SHA1
         | 
| 7 | 
            +
            end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'base64'
         | 
| 10 | 
            +
            module Ldap
         | 
| 11 | 
            +
              class Digest
         | 
| 12 | 
            +
                # method from openldap faq which produces the userPassword attribute
         | 
| 13 | 
            +
                # for the ldap
         | 
| 14 | 
            +
                # @param secret String the password
         | 
| 15 | 
            +
                # @param salt String the salt for the password digester
         | 
| 16 | 
            +
                # @return the encoded password/salt
         | 
| 17 | 
            +
                def self.ssha(secret, salt)
         | 
| 18 | 
            +
                  (salt.empty? ? "{SHA}": "{SSHA}") +
         | 
| 19 | 
            +
                    Base64.encode64(::Digest::SHA1.digest(secret + salt) + salt).gsub(/\n/, '')
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # method from openldap faq which produces the userPassword attribute
         | 
| 23 | 
            +
                # for the ldap
         | 
| 24 | 
            +
                # @param secret String the password
         | 
| 25 | 
            +
                # @return the encoded password
         | 
| 26 | 
            +
                def self.sha(secret)
         | 
| 27 | 
            +
                  ssha(secret, "")
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,161 @@ | |
| 1 | 
            +
            require 'net/ldap'
         | 
| 2 | 
            +
            require 'ldap/conditions_2_filter'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Ldap
         | 
| 5 | 
            +
              class NetLdapFacade
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                # @param config Hash for the ldap connection
         | 
| 8 | 
            +
                def self.open(config)
         | 
| 9 | 
            +
                  Net::LDAP.open( config ) do |ldap|
         | 
| 10 | 
            +
                    yield ldap
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                include ::Slf4r::Logger
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # @param config Hash for the ldap connection
         | 
| 17 | 
            +
                def initialize(config)
         | 
| 18 | 
            +
                  if config.is_a? Hash
         | 
| 19 | 
            +
                    @ldap = Net::LDAP.new( config )
         | 
| 20 | 
            +
                  else
         | 
| 21 | 
            +
                    @ldap = config
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def retrieve_next_id(treebase, key_field)
         | 
| 26 | 
            +
                  base = "#{treebase},#{@ldap.base}"
         | 
| 27 | 
            +
                  id_sym = key_field.downcase.to_sym
         | 
| 28 | 
            +
                  max = 0
         | 
| 29 | 
            +
                  @ldap.search( :base => base,
         | 
| 30 | 
            +
                                :attributes => [key_field],
         | 
| 31 | 
            +
                                :return_result => false ) do |entry|
         | 
| 32 | 
            +
                    n = entry[id_sym].first.to_i
         | 
| 33 | 
            +
                    max = n if max < n
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                  max + 1
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # @param dn_prefix String the prefix of the dn
         | 
| 39 | 
            +
                # @param treebase the treebase of the dn or any search
         | 
| 40 | 
            +
                # @param key_field field which carries the integer unique id of the entity
         | 
| 41 | 
            +
                # @param props Hash of the ldap attributes of the new ldap object
         | 
| 42 | 
            +
                # @return nil in case of an error or the new id of the created object
         | 
| 43 | 
            +
                def create_object(dn_prefix, treebase, key_field, props, silence = false)
         | 
| 44 | 
            +
                  base = "#{treebase},#{@ldap.base}"
         | 
| 45 | 
            +
                  if @ldap.add( :dn => dn(dn_prefix, treebase),
         | 
| 46 | 
            +
                                :attributes => props) || @ldap.get_operation_result.code.to_s == "0"
         | 
| 47 | 
            +
                    props[key_field.to_sym]
         | 
| 48 | 
            +
                  else
         | 
| 49 | 
            +
                    unless silence
         | 
| 50 | 
            +
                      msg = ldap_error("create",
         | 
| 51 | 
            +
                                         dn(dn_prefix, treebase)) + "\n\t#{props.inspect}"
         | 
| 52 | 
            +
                      # TODO maybe raise always an error
         | 
| 53 | 
            +
                      if @ldap.get_operation_result.code.to_s == "68"
         | 
| 54 | 
            +
                        raise ::DataMapper::PersistenceError.new(msg)
         | 
| 55 | 
            +
                      else
         | 
| 56 | 
            +
                        logger.warn(msg)
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                    nil
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                # @param treebase the treebase of the search
         | 
| 64 | 
            +
                # @param key_fields Array of fields which carries the integer unique id(s) of the entity
         | 
| 65 | 
            +
                # @param Array of conditions for the search
         | 
| 66 | 
            +
                # @return Array of Hashes with a name/values pair for each attribute
         | 
| 67 | 
            +
                def read_objects(treebase, key_fields, conditions, field_names, order_field = nil)
         | 
| 68 | 
            +
                  result = []
         | 
| 69 | 
            +
                  filter = Conditions2Filter.convert(conditions)
         | 
| 70 | 
            +
                  @ldap.search( :base => "#{treebase},#{@ldap.base}",
         | 
| 71 | 
            +
                                :attributes => field_names,
         | 
| 72 | 
            +
                                :filter => filter ) do |res|
         | 
| 73 | 
            +
                    mapp = to_map(field_names, res)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    #puts map[key_field.to_sym]
         | 
| 76 | 
            +
                    # TODO maybe make filter which removes this unless
         | 
| 77 | 
            +
                    # TODO move this into the ldap_Adapter to make it more general, so that
         | 
| 78 | 
            +
                    # all field with Integer gets converted, etc
         | 
| 79 | 
            +
                    result << mapp if key_fields.detect do |key_field|
         | 
| 80 | 
            +
                      mapp.keys.detect {|k| k.to_s.downcase == key_field.downcase }
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                  result
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
             | 
| 87 | 
            +
                # @param dn_prefix String the prefix of the dn
         | 
| 88 | 
            +
                # @param treebase the treebase of the dn or any search
         | 
| 89 | 
            +
                # @param actions the add/replace/delete actions on the attributes
         | 
| 90 | 
            +
                # @return nil in case of an error or true
         | 
| 91 | 
            +
                def update_object(dn_prefix, treebase, actions)
         | 
| 92 | 
            +
                  if @ldap.modify( :dn => dn(dn_prefix, treebase),
         | 
| 93 | 
            +
                                   :operations => actions ) || @ldap.get_operation_result.code.to_s == "0"
         | 
| 94 | 
            +
                    true
         | 
| 95 | 
            +
                  else
         | 
| 96 | 
            +
                    logger.warn(ldap_error("update",
         | 
| 97 | 
            +
                                           dn(dn_prefix, treebase) + "\n\t#{actions.inspect}"))
         | 
| 98 | 
            +
                    nil
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                # @param dn_prefix String the prefix of the dn
         | 
| 103 | 
            +
                # @param treebase the treebase of the dn or any search
         | 
| 104 | 
            +
                # @return nil in case of an error or true
         | 
| 105 | 
            +
                def delete_object(dn_prefix, treebase)
         | 
| 106 | 
            +
                  if @ldap.delete( :dn => dn(dn_prefix, treebase) )
         | 
| 107 | 
            +
                    true
         | 
| 108 | 
            +
                  else
         | 
| 109 | 
            +
                    logger.warn(ldap_error("delete",
         | 
| 110 | 
            +
                                           dn(dn_prefix, treebase)))
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    nil
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
             | 
| 117 | 
            +
                # @param dn String for identifying the ldap object
         | 
| 118 | 
            +
                # @param password String to be used for authenticate to the dn
         | 
| 119 | 
            +
                def authenticate(dn, password)
         | 
| 120 | 
            +
                  Net::LDAP.new( { :host => @ldap.host,
         | 
| 121 | 
            +
                                   :port => @ldap.port,
         | 
| 122 | 
            +
                                   :auth => {
         | 
| 123 | 
            +
                                     :method => :simple,
         | 
| 124 | 
            +
                                     :username => dn,
         | 
| 125 | 
            +
                                     :password => password
         | 
| 126 | 
            +
                                   },
         | 
| 127 | 
            +
                                   :base => @ldap.base
         | 
| 128 | 
            +
                                 } ).bind
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                # helper to concat the dn from the various parts
         | 
| 132 | 
            +
                # @param dn_prefix String the prefix of the dn
         | 
| 133 | 
            +
                # @param treebase the treebase of the dn or any search
         | 
| 134 | 
            +
                # @return the complete dn String
         | 
| 135 | 
            +
                def dn(dn_prefix, treebase)
         | 
| 136 | 
            +
                  "#{dn_prefix},#{treebase},#{@ldap.base}"
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                private
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                # helper to extract the Hash from the ldap search result
         | 
| 142 | 
            +
                # @param Entry from the ldap_search
         | 
| 143 | 
            +
                # @return Hash with name/value pairs of the entry
         | 
| 144 | 
            +
                def to_map(field_names, entry)
         | 
| 145 | 
            +
                  fields = {:dn => :dn}
         | 
| 146 | 
            +
                  field_names.each { |f| fields[f.downcase.to_sym] = f.to_sym }
         | 
| 147 | 
            +
                  def entry.map
         | 
| 148 | 
            +
                    @myhash
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
                  result = {}
         | 
| 151 | 
            +
                  entry.map.each do |k,v|
         | 
| 152 | 
            +
                    result[fields[k]] = v
         | 
| 153 | 
            +
                  end
         | 
| 154 | 
            +
                  result
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
                
         | 
| 157 | 
            +
                def ldap_error(method, dn)
         | 
| 158 | 
            +
                  "#{method} error: (#{@ldap.get_operation_result.code}) #{@ldap.get_operation_result.message}\n\tDN: #{dn}"
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
            end
         |