require 'net/ldap' ## # some additional ldap specific config handlings. # class DsAdmin::Storage::Config def object_class(storage) @config[storage.config_key][@model.config_key][:objectClass] end def dn(storage, data) eval_pattern( @config[storage.config_key][@model.config_key][:dnPat], data) + ',' + query(storage)[:base] end end class DsAdmin::Storage::Ldap include DsAdmin::Storage def initialize(config) super(config) @ldap = Net::LDAP.new(@config.con(self)) end def read query = @config.query(self) ## # two things. # - create a hash from the ldap search result # - map the id's from the ldap search resulte into id's used in # the models. The mapping is read from the config. # @ldap.search(query).map do |data| map = { :dn => :id } map.merge!(@config.map(self)) remap(data, map) end end def write(model) @config.model = model data = model.to_h odata = read.find{|od| od[:id] == data[:id]} return create(data) unless odata update(odata, data) end protected def create(data) dn = @config.dn(self, data) data.delete(:id) entry = Net::LDAP::Entry.new(dn) entry[:changetype] = 'add' entry[:objectclass] = @config.object_class(self) remap(data, @config.map(self).invert).each {|key,value| entry[key] = value} puts entry.to_ldif # TODO: make real writes return dn end def update(old, new) new.delete(:id) replace = remap( new.find_all{|key,value| value != old[key]}, @config.map(self).invert ) ## # if the given model already has an id; # # check if ldap dn has to be changed in order to # reflect the attributes. # if so, remove old entry # replace.each do |key,value| if old[:id] =~ /(^|, *)#{key.to_s}=([^, ]+)/ && $2 != value delete(old[:id]) puts return create(new) end end entry = Net::LDAP::Entry.new(old[:id]) entry[:changetype] = 'modify' entry[:replace] = replace.keys replace.each {|key,value| entry[key] = value } puts entry.to_ldif # TODO: make real writes return old[:id] end def delete(id) entry = Net::LDAP::Entry.new(id) entry[:changetype] = 'delete' puts entry.to_ldif # TODO: make real writes return true end def remap(data, map) remapped = Hash.new data.each do |key,value| key = map[key] || key value = value.size==1 ? value[0] : value.to_a remapped.merge!({ key => value }) end if data remapped end end