Revision 2bd92292
Added by Marc Dequènes about 15 years ago
- ID 2bd92292f8692c53b98ab68897904f9eb244ca01
TODO | ||
---|---|---|
- ensure removing an aspect also remove reverse-depends
|
||
- improve configuration:
|
||
* allow global relations to share them among objects ???
|
||
- select parent at creation with :parent if present, or use
|
bin/shadowwalker | ||
---|---|---|
locale = ENV['LANGUAGE'] || ENV['LC_ALL'] || ENV['LC_MESSAGES'] || ENV['LANG']
|
||
|
||
require 'ldap_shadows'
|
||
require 'ldap_shadows/display_utils'
|
||
require 'ldap_shadows/display_helper'
|
||
require 'ldap_shadows/manipulation_helper'
|
||
require 'cmdparse2'
|
||
|
||
include LdapShadows
|
||
... | ... | |
|
||
obj_klass, item = params_shift_item_handle_full_handle(args)
|
||
|
||
modification_done = false
|
||
args.each do |mod_info|
|
||
mod_done = item.item_modify_from_string(mod_info)
|
||
modification_done ||= mod_done
|
||
end
|
||
modification_done = LdapShadows::Manipulation.item_modify_from_strings(item, args)
|
||
|
||
if modification_done
|
||
item.save!
|
||
... | ... | |
item = obj_klass.new(item_hdl)
|
||
item.base = loc_item.dn_obj - obj_klass.base_obj
|
||
|
||
|
||
modification_done = false
|
||
args.each do |mod_info|
|
||
mod_done = item.item_modify_from_string(mod_info)
|
||
modification_done ||= mod_done
|
||
end
|
||
modification_done = LdapShadows::Manipulation.item_modify_from_strings(item, args)
|
||
|
||
item.save!
|
||
puts "Creation done."
|
||
... | ... | |
|
||
raise SyntaxError, _("no search arguments") if args.empty?
|
||
|
||
res = Elements::LdapObject.items_find_from_strings($shadow, args)
|
||
res = LdapShadows::Manipulation.items_find_from_strings($shadow, args)
|
||
unless res.empty?
|
||
display_lines = []
|
||
res.each do |raw_item|
|
||
display_lines << Elements::LdapObject.raw_item_info($shadow, raw_item)[:name]
|
||
display_lines << LdapShadows::Manipulation.raw_item_info($shadow, raw_item)[:name]
|
||
end
|
||
puts display_lines.join("\n")
|
||
end
|
lib/ldap_shadows/display_helper.rb | ||
---|---|---|
#--
|
||
# LdapShadows, a Medium-level LDAP Access Library and Tool.
|
||
# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
require 'active_support'
|
||
|
||
|
||
module LdapShadows
|
||
module Translator
|
||
I18n.default_locale = :en
|
||
|
||
def self.translate_object_name(obj_hdl)
|
||
I18n.t(obj_hdl, :scope => 'objects', :default => "Object '#{obj_hdl}'")
|
||
end
|
||
|
||
def self.translate_field_name(field_name)
|
||
if field_name.index(":")
|
||
type, key = field_name.split(":")
|
||
case type
|
||
when 'rel'
|
||
I18n.t(key, :scope => 'relations', :default => field_name)
|
||
else
|
||
raise "Cannot translate unknown data key type"
|
||
end
|
||
else
|
||
att = ActiveLdap::Base.schema.attribute(field_name)
|
||
I18n.t(att.human_attribute_name, :scope => 'attribute_types', :default => att.human_attribute_description)
|
||
end
|
||
end
|
||
|
||
def self.translate_aspect_name(aspect_name)
|
||
I18n.t(aspect_name, :scope => 'aspects', :default => "Aspect '#{aspect_name}'")
|
||
end
|
||
end
|
||
|
||
module Display
|
||
def self.display_fields(attr_data, options = {})
|
||
attr_data.each_pair do |key, val|
|
||
next if val[:expert] and not options[:expert]
|
||
next if val[:admin] and not options[:admin]
|
||
|
||
field_name = Translator.translate_field_name(key)
|
||
|
||
str = field_name
|
||
str += " [#{key}]" if options[:handles]
|
||
if val[:binary] and options[:skip_binary]
|
||
str += " -> #{val[:value].size} file(s) available"
|
||
else
|
||
str += ": " + (val[:multiple] ? val[:value].sort.collect{|v| v.to_s }.join(", ") : val[:value].to_s)
|
||
end
|
||
|
||
puts str
|
||
end
|
||
end
|
||
|
||
def self.display_item(item, options = {})
|
||
obj_human_name = Translator.translate_object_name(item.class.handle)
|
||
name = item.human_name
|
||
name += " [#{item.full_handle}]" if options[:handles]
|
||
puts "=== #{obj_human_name}: #{name} ==="
|
||
|
||
if options[:debug]
|
||
puts item.to_s
|
||
puts "--- Detected Info ---"
|
||
puts "aspects: " + item.aspects.sort.join(", ")
|
||
|
||
puts "--- Relations ---"
|
||
item.relations.each do |rel|
|
||
rel_data = item.send(rel)
|
||
if rel_data.is_a? Enumerable
|
||
next if rel_data.empty?
|
||
rel_value = rel_data.collect{|g| g.name }.join(", ")
|
||
else
|
||
# the exists? method also ensure the object is loaded
|
||
next unless rel_data.exists?
|
||
rel_value = rel_data.name
|
||
end
|
||
puts "#{rel}: " + rel_value
|
||
end
|
||
|
||
if options[:show_family_members]
|
||
puts "--- Family ---"
|
||
puts "parent: " + item.family_parent_dn.to_s
|
||
puts "siblings: " + item.family_siblings_dn.join(", ")
|
||
puts "children: " + item.family_children_dn.join(", ")
|
||
end
|
||
else
|
||
obj_info, obj_aspects = item.organized_data
|
||
|
||
display_fields(obj_info, options)
|
||
|
||
obj_aspects.each_pair do |aspect_name, aspect_data|
|
||
name = Translator.translate_aspect_name(aspect_name)
|
||
name += " [#{aspect_name}]" if options[:handles]
|
||
puts "--- #{name} ---"
|
||
display_fields(aspect_data, options)
|
||
end
|
||
|
||
if options[:show_family_members]
|
||
puts "--- Family ---"
|
||
puts "parent: " + item.class.raw_item_info(item.class.shadow, item.family_parent)[:name]
|
||
puts "siblings: " + item.family_siblings.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
|
||
puts "children: " + item.family_children.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
|
||
end
|
||
end
|
||
end
|
||
|
||
def self.display_item_list(title, item_list, options)
|
||
puts "=== #{title} (#{item_list.size}) ==="
|
||
item_list.each do |item|
|
||
str = item.human_name
|
||
str += " [#{item.full_handle}]" if options[:handles]
|
||
str += ": #{item.human_description}" unless item.human_description.empty?
|
||
puts str
|
||
end
|
||
end
|
||
|
||
def self.display_hash_tree(tree, level)
|
||
tree.keys.sort.each do |key|
|
||
str = ""
|
||
str += " " + "| " * (level -1) + "+-- " if level > 0
|
||
str += "<#{key}>"
|
||
puts str
|
||
|
||
display_hash_tree(tree[key], level + 1) if tree[key]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
lib/ldap_shadows/display_utils.rb | ||
---|---|---|
#--
|
||
# LdapShadows, a Medium-level LDAP Access Library and Tool.
|
||
# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
require 'active_support'
|
||
|
||
|
||
module LdapShadows
|
||
module Translator
|
||
I18n.default_locale = :en
|
||
|
||
def self.translate_object_name(obj_hdl)
|
||
I18n.t(obj_hdl, :scope => 'objects', :default => "Object '#{obj_hdl}'")
|
||
end
|
||
|
||
def self.translate_field_name(field_name)
|
||
if field_name.index(":")
|
||
type, key = field_name.split(":")
|
||
case type
|
||
when 'rel'
|
||
I18n.t(key, :scope => 'relations', :default => field_name)
|
||
else
|
||
raise "Cannot translate unknown data key type"
|
||
end
|
||
else
|
||
att = ActiveLdap::Base.schema.attribute(field_name)
|
||
I18n.t(att.human_attribute_name, :scope => 'attribute_types', :default => att.human_attribute_description)
|
||
end
|
||
end
|
||
|
||
def self.translate_aspect_name(aspect_name)
|
||
I18n.t(aspect_name, :scope => 'aspects', :default => "Aspect '#{aspect_name}'")
|
||
end
|
||
end
|
||
|
||
module Display
|
||
def self.display_fields(attr_data, options = {})
|
||
attr_data.each_pair do |key, val|
|
||
next if val[:expert] and not options[:expert]
|
||
next if val[:admin] and not options[:admin]
|
||
|
||
field_name = Translator.translate_field_name(key)
|
||
|
||
str = field_name
|
||
str += " [#{key}]" if options[:handles]
|
||
if val[:binary] and options[:skip_binary]
|
||
str += " -> #{val[:value].size} file(s) available"
|
||
else
|
||
str += ": " + (val[:multiple] ? val[:value].sort.collect{|v| v.to_s }.join(", ") : val[:value].to_s)
|
||
end
|
||
|
||
puts str
|
||
end
|
||
end
|
||
|
||
def self.display_item(item, options = {})
|
||
obj_human_name = Translator.translate_object_name(item.class.handle)
|
||
name = item.human_name
|
||
name += " [#{item.full_handle}]" if options[:handles]
|
||
puts "=== #{obj_human_name}: #{name} ==="
|
||
|
||
if options[:debug]
|
||
puts item.to_s
|
||
puts "--- Detected Info ---"
|
||
puts "aspects: " + item.aspects.sort.join(", ")
|
||
|
||
puts "--- Relations ---"
|
||
item.relations.each do |rel|
|
||
rel_data = item.send(rel)
|
||
if rel_data.is_a? Enumerable
|
||
next if rel_data.empty?
|
||
rel_value = rel_data.collect{|g| g.name }.join(", ")
|
||
else
|
||
# the exists? method also ensure the object is loaded
|
||
next unless rel_data.exists?
|
||
rel_value = rel_data.name
|
||
end
|
||
puts "#{rel}: " + rel_value
|
||
end
|
||
|
||
if options[:show_family_members]
|
||
puts "--- Family ---"
|
||
puts "parent: " + item.family_parent_dn.to_s
|
||
puts "siblings: " + item.family_siblings_dn.join(", ")
|
||
puts "children: " + item.family_children_dn.join(", ")
|
||
end
|
||
else
|
||
obj_info, obj_aspects = item.organized_data
|
||
|
||
display_fields(obj_info, options)
|
||
|
||
obj_aspects.each_pair do |aspect_name, aspect_data|
|
||
name = Translator.translate_aspect_name(aspect_name)
|
||
name += " [#{aspect_name}]" if options[:handles]
|
||
puts "--- #{name} ---"
|
||
display_fields(aspect_data, options)
|
||
end
|
||
|
||
if options[:show_family_members]
|
||
puts "--- Family ---"
|
||
puts "parent: " + item.class.raw_item_info(item.class.shadow, item.family_parent)[:name]
|
||
puts "siblings: " + item.family_siblings.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
|
||
puts "children: " + item.family_children.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
|
||
end
|
||
end
|
||
end
|
||
|
||
def self.display_item_list(title, item_list, options)
|
||
puts "=== #{title} (#{item_list.size}) ==="
|
||
item_list.each do |item|
|
||
str = item.human_name
|
||
str += " [#{item.full_handle}]" if options[:handles]
|
||
str += ": #{item.human_description}" unless item.human_description.empty?
|
||
puts str
|
||
end
|
||
end
|
||
|
||
def self.display_hash_tree(tree, level)
|
||
tree.keys.sort.each do |key|
|
||
str = ""
|
||
str += " " + "| " * (level -1) + "+-- " if level > 0
|
||
str += "<#{key}>"
|
||
puts str
|
||
|
||
display_hash_tree(tree[key], level + 1) if tree[key]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
lib/ldap_shadows/elements/object.rb | ||
---|---|---|
[obj_info, obj_aspects]
|
||
end
|
||
|
||
def item_modify_from_string(str)
|
||
unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|\+=|-=)(.*)$/
|
||
raise SyntaxError, _("modification parameter '%s' is invalid") % str
|
||
end
|
||
key = $1
|
||
op = $2
|
||
val = $3
|
||
|
||
item_modify(key, op, val)
|
||
end
|
||
|
||
def item_modify(key, op, val)
|
||
def modify(key, op, val)
|
||
if key.index(":")
|
||
type, field = key.split(":")
|
||
else
|
||
... | ... | |
|
||
case type
|
||
when nil
|
||
item_modify_field(key, op, val)
|
||
modify_field(key, op, val)
|
||
when 'rel'
|
||
item_modify_relation(field, op, val)
|
||
modify_relation(field, op, val)
|
||
when ''
|
||
case field
|
||
when 'aspects'
|
||
item_modify_aspects(op, val)
|
||
modify_aspects(op, val)
|
||
else
|
||
raise PreProcessingError, _("Unknown core field '%s'") % field
|
||
end
|
||
... | ... | |
end
|
||
end
|
||
|
||
def item_modify_field(field, op, val)
|
||
def modify_field(field, op, val)
|
||
unless self.has_field?(field)
|
||
raise PreProcessingError, _("No such field '%s' in object '%s'") % [field, self.class.handle]
|
||
end
|
||
... | ... | |
true
|
||
end
|
||
|
||
def item_modify_relation(rel, op, val)
|
||
def modify_relation(rel, op, val)
|
||
unless self.relations.include?(rel)
|
||
raise PreProcessingError, _("No such relation '%s' for object '%s'") % [rel, self.class.handle]
|
||
end
|
||
|
||
rel_info = self.class.relations_info[rel]
|
||
rel_info = self.class.relations_info[rel.to_sym]
|
||
if rel_info[:read_only]
|
||
raise PreProcessingError, _("The relation '%s' cannot be modified (read only)") % rel
|
||
end
|
||
... | ... | |
true
|
||
end
|
||
|
||
def item_modify_aspects(op, aspect_name)
|
||
def modify_aspects(op, aspect_name)
|
||
unless self.class.possible_aspects.include?(aspect_name)
|
||
raise PreProcessingError, _("No such aspect '%s' for object '%s'") % [aspect_name, self.class.handle]
|
||
end
|
||
... | ... | |
raise PreProcessingError, _("The equality operator is not possible for aspects")
|
||
|
||
when '+='
|
||
return false if self.aspects.keys.include?(aspect)
|
||
return false if self.aspects.keys.include?(aspect_name)
|
||
|
||
self.add_aspect(aspect)
|
||
self.add_aspect(aspect_name)
|
||
|
||
when '-='
|
||
return false unless self.aspects.keys.include?(aspect)
|
||
return false unless self.aspects.keys.include?(aspect_name)
|
||
|
||
self.remove_aspect(aspect)
|
||
self.remove_aspect(aspect_name)
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
... | ... | |
true
|
||
end
|
||
|
||
def self.items_find_from_strings(shadow, str_list)
|
||
ldap_search_objects = "(objectClass=*)"
|
||
ldap_search_aspects = ""
|
||
ldap_search_fields = []
|
||
str_list.each do |str|
|
||
unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|~=)(.*)$/
|
||
raise SyntaxError, _("search parameter '%s' is invalid") % str
|
||
end
|
||
key = $1
|
||
op = $2
|
||
val = $3
|
||
|
||
if key.index(":")
|
||
type, field = key.split(":")
|
||
else
|
||
type = nil
|
||
field = key
|
||
end
|
||
|
||
case type
|
||
when nil
|
||
ldap_search_fields << ldap_search_string_field(field, op, val)
|
||
when 'rel'
|
||
raise PreProcessingError, _("Searching relations is not implemented yet")
|
||
when ''
|
||
case field
|
||
when 'objects'
|
||
ldap_search_objects = ldap_search_string_objects(shadow, field, op, val)
|
||
when 'aspects'
|
||
ldap_search_aspects = ldap_search_string_aspects(shadow, field, op, val)
|
||
else
|
||
raise PreProcessingError, _("Unknown core field '%s'") % field
|
||
end
|
||
else
|
||
raise PreProcessingError, _("Unknown type '%s' for field '%s'") % [type, field]
|
||
end
|
||
end
|
||
ldap_search_string = "(&" + ldap_search_objects + ldap_search_aspects + ldap_search_fields.join + ")"
|
||
|
||
LdapObject.find(:all, :scope => :sub, :filter => ldap_search_string, :attributes => ["objectClass"])
|
||
end
|
||
|
||
def self.ldap_search_string_field(field, op, val)
|
||
esc_val = self.connection.escape_filter_value(val)
|
||
case op
|
||
when "="
|
||
"(#{field}=#{esc_val})"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not implemented yet")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
|
||
def self.ldap_search_string_objects(shadow, field, op, val_list)
|
||
ldap_search_parts = val_list.split(",").collect do |val|
|
||
obj_hdl = val.downcase.singularize
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
raise PreProcessingError, _("No such object '%s'") % val if obj_klass.nil?
|
||
|
||
ldap_classes = obj_klass.required_classes
|
||
|
||
case op
|
||
when "="
|
||
"(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not possible with objects")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
"(|" + ldap_search_parts.join + ")"
|
||
end
|
||
|
||
def self.ldap_search_string_aspects(shadow, field, op, val_list)
|
||
ldap_search_parts = val_list.split(",").collect do |val|
|
||
aspect = shadow.get_aspect(val)
|
||
raise PreProcessingError, _("No such aspect '%s'") % val if aspect.nil?
|
||
|
||
ldap_classes = aspect.parameters[:mapping][:classes]
|
||
|
||
case op
|
||
when "="
|
||
"(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not possible with aspects")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
"(&" + ldap_search_parts.join + ")"
|
||
end
|
||
|
||
def self.find_raw_item_object(shadow, raw_item)
|
||
# easy case
|
||
base_obj_klass = LdapShadows::Elements::LdapObject
|
||
if raw_item.class != base_obj_klass and raw_item.class.ancestors.include?(base_obj_klass)
|
||
return raw_item.class.handle
|
||
end
|
||
|
||
shadow.objects.each do |obj_hdl|
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
ldap_classes = obj_klass.required_classes
|
||
return obj_hdl if raw_item.classes & ldap_classes == ldap_classes
|
||
end
|
||
nil
|
||
end
|
||
|
||
def self.raw_item_info(shadow, raw_item)
|
||
obj_hdl = self.find_raw_item_object(shadow, raw_item)
|
||
if obj_hdl
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
item = obj_klass.new(raw_item.dn)
|
||
{:name => item.full_handle, :item => item, :object => obj_klass}
|
||
else
|
||
{:name => "unknown/#{raw_item.dn}"}
|
||
end
|
||
end
|
||
|
||
def add_aspect(aspect_name)
|
||
return unless self.class.possible_aspects.include?(aspect_name)
|
||
|
lib/ldap_shadows/manipulation_helper.rb | ||
---|---|---|
#--
|
||
# LdapShadows, a Medium-level LDAP Access Library and Tool.
|
||
# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
|
||
module LdapShadows
|
||
module Manipulation
|
||
def self.item_modify_from_strings(item, str_list)
|
||
str_list = [str_list] unless str_list.is_a? Array
|
||
|
||
modification_done = false
|
||
str_list.each do |str|
|
||
unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|\+=|-=)(.*)$/
|
||
raise SyntaxError, _("modification parameter '%s' is invalid") % str
|
||
end
|
||
key = $1
|
||
op = $2
|
||
val = $3
|
||
|
||
mod_done = item.modify(key, op, val)
|
||
modification_done ||= mod_done
|
||
end
|
||
|
||
modification_done
|
||
end
|
||
|
||
def self.items_find_from_strings(shadow, str_list)
|
||
ldap_search_objects = "(objectClass=*)"
|
||
ldap_search_aspects = ""
|
||
ldap_search_fields = []
|
||
str_list.each do |str|
|
||
unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|~=)(.*)$/
|
||
raise SyntaxError, _("search parameter '%s' is invalid") % str
|
||
end
|
||
key = $1
|
||
op = $2
|
||
val = $3
|
||
|
||
if key.index(":")
|
||
type, field = key.split(":")
|
||
else
|
||
type = nil
|
||
field = key
|
||
end
|
||
|
||
case type
|
||
when nil
|
||
ldap_search_fields << ldap_search_string_field(field, op, val)
|
||
when 'rel'
|
||
raise PreProcessingError, _("Searching relations is not implemented yet")
|
||
when ''
|
||
case field
|
||
when 'objects'
|
||
ldap_search_objects = ldap_search_string_objects(shadow, field, op, val)
|
||
when 'aspects'
|
||
ldap_search_aspects = ldap_search_string_aspects(shadow, field, op, val)
|
||
else
|
||
raise PreProcessingError, _("Unknown core field '%s'") % field
|
||
end
|
||
else
|
||
raise PreProcessingError, _("Unknown type '%s' for field '%s'") % [type, field]
|
||
end
|
||
end
|
||
ldap_search_string = "(&" + ldap_search_objects + ldap_search_aspects + ldap_search_fields.join + ")"
|
||
|
||
ActiveLdap::Base.find(:all, :scope => :sub, :filter => ldap_search_string, :attributes => ["objectClass"])
|
||
end
|
||
|
||
def self.find_raw_item_object(shadow, raw_item)
|
||
# easy case
|
||
base_obj_klass = LdapShadows::Elements::LdapObject
|
||
if raw_item.class != base_obj_klass and raw_item.class.ancestors.include?(base_obj_klass)
|
||
return raw_item.class.handle
|
||
end
|
||
|
||
shadow.objects.each do |obj_hdl|
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
ldap_classes = obj_klass.required_classes
|
||
return obj_hdl if raw_item.classes & ldap_classes == ldap_classes
|
||
end
|
||
nil
|
||
end
|
||
|
||
def self.raw_item_info(shadow, raw_item)
|
||
obj_hdl = self.find_raw_item_object(shadow, raw_item)
|
||
if obj_hdl
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
item = obj_klass.new(raw_item.dn)
|
||
{:name => item.full_handle, :item => item, :object => obj_klass}
|
||
else
|
||
{:name => "unknown/#{raw_item.dn}"}
|
||
end
|
||
end
|
||
|
||
protected
|
||
|
||
def self.ldap_search_string_field(field, op, val)
|
||
esc_val = ActiveLdap::Base.connection.escape_filter_value(val)
|
||
case op
|
||
when "="
|
||
"(#{field}=#{esc_val})"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not implemented yet")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
|
||
def self.ldap_search_string_objects(shadow, field, op, val_list)
|
||
ldap_search_parts = val_list.split(",").collect do |val|
|
||
obj_hdl = val.downcase.singularize
|
||
obj_klass = shadow.get_object(obj_hdl)
|
||
raise PreProcessingError, _("No such object '%s'") % val if obj_klass.nil?
|
||
|
||
ldap_classes = obj_klass.required_classes
|
||
|
||
case op
|
||
when "="
|
||
"(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not possible with objects")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
"(|" + ldap_search_parts.join + ")"
|
||
end
|
||
|
||
def self.ldap_search_string_aspects(shadow, field, op, val_list)
|
||
ldap_search_parts = val_list.split(",").collect do |val|
|
||
aspect = shadow.get_aspect(val)
|
||
raise PreProcessingError, _("No such aspect '%s'") % val if aspect.nil?
|
||
|
||
ldap_classes = aspect.parameters[:mapping][:classes]
|
||
|
||
case op
|
||
when "="
|
||
"(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
|
||
|
||
when "~="
|
||
raise PreProcessingError, _("Searching with regex is not possible with aspects")
|
||
|
||
else
|
||
raise SyntaxError, _("Unknown operator '%s'") % op
|
||
end
|
||
end
|
||
"(&" + ldap_search_parts.join + ")"
|
||
end
|
||
end
|
||
end
|
lib/ldap_shadows/shadow.rb | ||
---|---|---|
def tree(search_base, raw = false, all_objects = false)
|
||
item_list = {}
|
||
if all_objects
|
||
# does not work well...
|
||
#Elements::LdapObject.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
|
||
# item_list[item.dn_obj] = item
|
||
#end
|
||
ActiveLdap::Base.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
|
||
item_list[ActiveLdap::DistinguishedName.parse(item.dn)]= item
|
||
end
|
||
... | ... | |
raw_tree = {}
|
||
tree = {}
|
||
|
||
base_dn = ActiveLdap::DistinguishedName.parse(Elements::LdapObject.base)
|
||
base_dn = ActiveLdap::DistinguishedName.parse(ActiveLdap::Base.base)
|
||
dn_list = item_list.keys
|
||
|
||
dn_list.each do |dn|
|
||
... | ... | |
current_item = ActiveLdap::Base.find(:first, :base => current_dn.to_s, :scope => :base, :attributes => [''])
|
||
item_list[current_dn] = current_item
|
||
end
|
||
p_item = Elements::LdapObject.raw_item_info(self, item_list[current_dn])[:name]
|
||
p_item = LdapShadows::Manipulation.raw_item_info(self, item_list[current_dn])[:name]
|
||
end
|
||
|
||
unless p_raw_tree.has_key?(p_dn)
|
||
... | ... | |
res = {base_dn.to_s => raw_tree}
|
||
else
|
||
base_obj = ActiveLdap::Base.find(:first, :base => base_dn.to_s, :scope => :base, :attributes => [''])
|
||
res = {Elements::LdapObject.raw_item_info(self, base_obj)[:name] => tree}
|
||
res = {LdapShadows::Manipulation.raw_item_info(self, base_obj)[:name] => tree}
|
||
end
|
||
|
||
res
|
Also available in: Unified diff
[cleanup] moved helper things out of LdapObject in Manipulation and began sweeping dust