Class: DataMapper::Adapters::LdapAdapter

Inherits:
AbstractAdapter
  • Object
show all
Includes:
Slf4r::Logger
Defined in:
lib/adapters/ldap_adapter.rb,
lib/adapters/noop_transaction.rb

Constant Summary collapse

COMPARATORS =
{ "=" => :eql, ">=" => :gte, "<=" => :lte, "like" => :like }

Instance Method Summary collapse

Constructor Details

#initialize(name, options) ⇒ LdapAdapter

Returns a new instance of LdapAdapter.



178
179
180
181
# File 'lib/adapters/ldap_adapter.rb', line 178

def initialize(name, options)
  super(name, options)
  @ldap_connection = ::Ldap::LdapConnection.new(@options)
end

Instance Method Details

#create(resources) ⇒ Object



184
185
186
187
188
# File 'lib/adapters/ldap_adapter.rb', line 184

def create(resources)
  resources.select do |resource|
    create_resource(resource)
  end.size # just return the number of create resources
end

#create_resource(resource) ⇒ Fixnum

Returns value for the primary key or nil.

Parameters:

Returns:

  • (Fixnum)

    value for the primary key or nil

See Also:

  • SimpleAdapter#create_resource


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/adapters/ldap_adapter.rb', line 203

def create_resource(resource)
  logger.debug { resource.inspect }

  props = resource.model.ldap_properties(resource)
  key = nil
  resource.send(:properties).each do |prop|
    value = prop.get!(resource)
    if prop.class == ::Ldap::LdapArray
      props[prop.field.to_sym] = value unless value.nil? or value.size == 0
    else
      props[prop.field.to_sym] = value.to_s unless value.nil?
    end
    key = prop if prop.serial?
  end
  resource_dup = resource.dup
  id = ldap.retrieve_next_id(resource.model.treebase,
                             key_properties(resource).field)
  resource_dup.send("#{key_properties(resource).name}=".to_sym, id)
  props[key_properties(resource).field.to_sym] = "#{id}"
  key_value = begin
                ldap.create_object(resource.model.dn_prefix(resource_dup),
                                   resource.model.treebase,
                                   key_properties(resource).field,
                                   props, resource.model.multivalue_field)
              rescue => e
                raise e unless resource.model.multivalue_field
                # TODO something with creating these multivalue objects
              end
  logger.debug { "resource #{resource.inspect} key value: #{key_value.inspect}" + ", multivalue_field: " + resource.model.multivalue_field.to_s }
  if key_value and !key.nil?
    key.set!(resource, key_value.to_i)
    resource
  elsif resource.model.multivalue_field
    multivalue_prop = resource.send(:properties).detect do |prop|
      prop.field.to_sym == resource.model.multivalue_field
    end
    update_resource(resource,
                    { multivalue_prop =>
                      resource.send(multivalue_prop.name.to_sym)})
  else
    nil
  end
end

#current_transactionObject



30
31
32
# File 'lib/adapters/noop_transaction.rb', line 30

def current_transaction
  @transaction
end

#delete(resource) ⇒ Object

See Also:

  • AbstractAdapter#delete


301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/adapters/ldap_adapter.rb', line 301

def delete(resource)
  resource.each do |resource|
    if resource.model.multivalue_field
      multivalue_prop = resource.send(:properties).detect do |prop|
        prop.field.to_sym == resource.model.multivalue_field
      end
      update_resource(resource,
                      { multivalue_prop => nil })
    else
      ldap.delete_object(resource.model.dn_prefix(resource),
                         resource.model.treebase)
    end
  end
end

#key_properties(resource) ⇒ Object



119
120
121
# File 'lib/adapters/ldap_adapter.rb', line 119

def key_properties(resource)
  resource.model.key.first
end

#ldapLdap::LdapFacade

Returns ready to use LdapFacade.

Returns:

  • (Ldap::LdapFacade)

    ready to use LdapFacade



111
112
113
# File 'lib/adapters/ldap_adapter.rb', line 111

def ldap
  @ldap_connection.current
end

#open_ldap_connection(&block) ⇒ Object



115
116
117
# File 'lib/adapters/ldap_adapter.rb', line 115

def open_ldap_connection(&block)
  @ldap_connection.open(&block)
end

#pop_transactionObject



26
27
28
# File 'lib/adapters/noop_transaction.rb', line 26

def pop_transaction
  @transaction
end

#push_transaction(transaction) ⇒ Object



22
23
24
# File 'lib/adapters/noop_transaction.rb', line 22

def push_transaction(transaction)
  @transaction = transaction
end

#read(query) ⇒ Object

See Also:

  • AbstractAdapter#read


317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/adapters/ldap_adapter.rb', line 317

def read(query)
  result = []
  #get data values out of the query
  resources = read_resources(query)
  resources.each do |resource|
    map = {}
    query.fields.each_with_index do |property, idx|
      map[property.field] = property.typecast(resource[idx])
    end
    result << map
  end

#puts "read_many"
#p result
  result = result.uniq if query.unique?
  result = query.match_records(result) if query.model.multivalue_field
  result = query.sort_records_case_insensitive(result)
  result = query.limit_records(result)
  result
end

#read_resources(query) ⇒ Object



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/adapters/ldap_adapter.rb', line 338

def read_resources(query)
  query_order = query.order.first.target.field if query.order
  #Use empty string as default for order in query
  order_by = query_order || ''

  field_names = query.fields.collect {|f| f.field }
  result = ldap.read_objects(query.model.treebase,
                             query.model.key.collect { |k| k.field },
                             to_ldap_conditions(query),
                             field_names, order_by)
  if query.model.multivalue_field
    props_result = []
    result.each do |props|
      # run over all values of the multivalue field
      (props[query.model.multivalue_field] || []).each do |value|
        values =  query.fields.collect do |f|
          if query.model.multivalue_field == f.field.to_sym
            value
          else
            prop = props[f.field.to_sym].first
            f.primitive == Integer ? prop.to_i : prop.join rescue prop
          end
        end
        props_result << values
      end
    end
    props_result
  else # no multivalue field
    result.collect do |props|
      query.fields.collect do |f|
        prop = props[f.field.to_sym]
        if f.class == Ldap::LdapArray
          prop if prop
        elsif prop
          f.primitive == Integer ? prop.first.to_i : prop.join
        end
      end
    end
  end
end

#to_ldap_conditions(query) ⇒ Array

helper to remove datamapper specific classes from the conditions

Parameters:

  • conditions (Array)

    array of tuples: (action, property, new value)

Returns:

  • (Array)

    tuples: (action, attribute name, new value)



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/adapters/ldap_adapter.rb', line 130

def to_ldap_conditions(query)
  conditions = query.conditions
  ldap_conditions = []
  conditions.operands.each do |c|
    if c.is_a? Array
      props = {}
      query.fields.each{ |f| props[f.name] = f.field}
      or_conditions = []
      c[0].split('or').each do |e|
        e.strip!
        match = e.match("=|<=|>=|like")
        or_conditions << [COMPARATORS[match.values_at(0)[0]],
                          props[match.pre_match.strip.to_sym],
                          match.post_match.strip.gsub(/'/, '')]
      end
      ldap_conditions << [:or_operator, or_conditions, nil]
    else
      comparator = c.slug
      case comparator
      when :raw
      when :not
          # TODO proper recursion !!!
          ldap_conditions << [comparator, c.operands.first.subject.field, c.operands.first.send(:dumped_value)]
      when :in
        ldap_conditions << [:eql, c.subject.field, c.send(:dumped_value)]
      else
        if c.subject.is_a? Ldap::LdapArray
          # assume a single value here !!!
          val = c.send(:dumped_value)
          ldap_conditions << [comparator, c.subject.field, val[1, val.size - 2]]
        else
          ldap_conditions << [comparator, c.subject.field, c.send(:dumped_value)]
        end
      end
    end
  end
  ldap_conditions
end

#transaction_primitiveObject



19
20
21
# File 'lib/adapters/noop_transaction.rb', line 19

def transaction_primitive
  ::Ldap::NoopTransaction.new
end

#update(attributes, resources) ⇒ Object



190
191
192
193
194
195
196
197
# File 'lib/adapters/ldap_adapter.rb', line 190

def update(attributes, resources)
  resources.select do |resource|
#puts "update"
#p resource
    update_resource(resource, attributes)

  end.size
end

#update_resource(resource, attributes) ⇒ Object

Parameters:

  • resource (DataMapper::Resource)

    to be updated

  • attributes (Hash)

    new attributes for the resource

See Also:

  • SimpleAdapter#update_resource


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/adapters/ldap_adapter.rb', line 252

def update_resource(resource, attributes)
  actions = []
  attributes.each do |property, value|
    field = property.field.to_sym #TODO sym needed or string ???
    if property.class == ::Ldap::LdapArray
      value = property.load(value)
      if resource.original_attributes[property].nil?
        value.each do |v|
          actions << [:add, field, v]
        end
      else
        array_actions = []
        resource.original_attributes[property].each do |ov|
          unless value.member? ov
            actions << [:delete, field, ov.to_s]
          end
        end
        value.each do |v|
          unless resource.original_attributes[property].member? v
            actions << [:add, field, v.to_s]
          end
        end
        array_actions
      end
    else
      if resource.model.multivalue_field == property.field.to_sym
        if value.nil?
          actions << [:delete, field, resource.attribute_get(property.name).to_s]
        else
          actions << [:add, field, value.to_s]
        end
      elsif value.nil?
        actions << [:delete, field, []]
      elsif resource.original_attributes[property].nil?
        actions << [:add, field, value.to_s]
      else
        actions << [:replace, field, value.to_s]
      end
    end
  end
#puts "actions"
#p actions
#puts
  ldap.update_object(resource.model.dn_prefix(resource),
                     resource.model.treebase,
                     actions)
end