Revision 7bfcd98b
Added by Marc Dequènes almost 14 years ago
- ID 7bfcd98b929705cc5c65b729a60f022827a66bfe
bin/test_client | ||
---|---|---|
ask "MapMaker", :info1, "/_cyborg_"
|
||
ask "Librarian", :info2, "/_cyborg_"
|
||
ask "Librarian", :library, "/Records"
|
||
ask "Librarian", :persons, "/Records/persons"
|
||
ask "Librarian", :dns_domains, "/Records/dns_domains"
|
||
ask "Librarian", :persons, "/Records/Persons"
|
||
ask "Librarian", :dns_domains, "/Records/DnsDomains"
|
||
ask "Librarian", :gorou, "/Records/Persons/gorou"
|
||
ask "Librarian", :guihome_net, "/Records/DnsDomains/guihome.net"
|
||
ask "Librarian", :person_search, "/Records/Persons/?", {:uidNumber => 10033}
|
||
ask "Librarian", :person_search_null, "/Records/Persons/?"
|
||
#ask "MapMaker", :zones, "/Zones"
|
||
#ask "MapMaker", :wanted_failure, "/prout"
|
||
#ask "MapMaker", :dns, "/Services/DNS"
|
lib/cyborghood-librarian/interface/0_base.rb | ||
---|---|---|
node 'Records' do
|
||
node ['Persons', 'DnsDomains'] do
|
||
object_list = Proc.new{|obj_name| bot.services.records.send(node_name.underscore, obj_name) }
|
||
object_list = Proc.new do |*args|
|
||
obj_name, options = args
|
||
options ||= {}
|
||
|
||
bot.services.records.send(node_name.underscore, obj_name, options)
|
||
end
|
||
|
||
on_request do |request|
|
||
request.reply.results = object_list.call
|
||
end
|
||
|
||
attr_search_node do |criterias|
|
||
object_list.call(:search, :criterias => criterias, :format => :data_hash)
|
||
end
|
||
|
||
node object_list do
|
||
on_request do |request|
|
||
prepare_value = Proc.new do |v|
|
||
if v.is_a? Array
|
||
v.collect!{|v2| prepare_value.call(v2) }
|
||
elsif v.is_a? ActiveLdap::DistinguishedName
|
||
v.to_s
|
||
else
|
||
v
|
||
end
|
||
end
|
||
|
||
obj_attrs = object_list.call(node_name).attributes
|
||
obj_attrs.delete('objectClass')
|
||
obj_attrs.each do |k, v|
|
||
obj_attrs[k] = prepare_value.call(v)
|
||
end
|
||
|
||
request.reply.results = obj_attrs
|
||
request.reply.results = object_list.call(node_name, :format => :data_hash)
|
||
end
|
||
end
|
||
end
|
lib/cyborghood-librarian/interface_dsl_addons.rb | ||
---|---|---|
|
||
-> ldap search /?
|
lib/cyborghood-librarian/records.rb | ||
---|---|---|
module CyborgHood
|
||
module LibrarianLand
|
||
class Records
|
||
def persons(obj_name = nil)
|
||
HIDDEN_ATTRIBUTES = ['objectClass', 'userPassword', 'hasSubordinates', 'entryUUID', 'entryDN', 'structuralObjectClass', 'subschemaSubentry']
|
||
|
||
def persons(*args)
|
||
find_records(LdapPerson, 'uid', *args)
|
||
end
|
||
|
||
def dns_domains(*args)
|
||
find_records(LdapDnsDomain, 'cn', *args)
|
||
end
|
||
|
||
protected
|
||
|
||
# obj_name:
|
||
# - nil: return list of objects'names
|
||
# - <value>: return object whose primary attribute is equal to <value>
|
||
# - :all: return all objects
|
||
def find_records(klass, primary_attr, obj_name = nil, options = {})
|
||
if obj_name.nil?
|
||
LdapPerson.find(:all, :attributes => ['uid']).collect{|i| i.uid }
|
||
klass.find(:all, :attributes => [primary_attr]).collect{|i| i.send(primary_attr) }
|
||
elsif obj_name == :search
|
||
filter_parts = []
|
||
options[:criterias].each do |k, v|
|
||
filter_parts << "(#{k}=#{v})"
|
||
end
|
||
filter = (filter_parts.size == 1) ? filter_parts.first : '(&' + filter_parts.join + ')'
|
||
|
||
list = klass.find(:all, :filter => filter)
|
||
index_result(list, primary_attr) if options[:indexed]
|
||
format_result(list, options[:format])
|
||
elsif obj_name == :all
|
||
list = klass.find(:all)
|
||
index_result(list, primary_attr) if options[:indexed]
|
||
format_result(list, options[:format])
|
||
else
|
||
list = LdapPerson.find(:all, :attribute => 'uid', :value => obj_name)
|
||
list = klass.find(:all, :attribute => primary_attr, :value => obj_name)
|
||
return if list.nil? or list.empty?
|
||
return list.first if list.size == 1
|
||
raise CyberError.new(:unrecoverable, "db/ldap", "broken DB: multiple Person with the same uid")
|
||
return format_result(list.first, options[:format]) if list.size == 1
|
||
raise CyberError.new(:unrecoverable, "db/ldap", "broken DB: multiple #{klass} with the same #{primary_attr}")
|
||
end
|
||
end
|
||
|
||
def dns_domains(obj_name = nil)
|
||
if obj_name.nil?
|
||
LdapDnsDomain.find(:all, :attributes => ['cn']).collect{|i| i.cn }
|
||
def format_value(v)
|
||
if v.is_a? Array
|
||
v.collect!{|v2| format_value(v2) }
|
||
elsif v.is_a? ActiveLdap::DistinguishedName
|
||
v.to_s
|
||
else
|
||
list = LdapDnsDomain.find(:all, :attribute => 'cn', :value => obj_name)
|
||
return if list.nil? or list.empty?
|
||
return list.first if list.size == 1
|
||
raise CyberError.new(:unrecoverable, "db/ldap", "broken DB: multiple DnsDomain with the same cn")
|
||
v
|
||
end
|
||
end
|
||
|
||
def dh_format_element(element)
|
||
obj_attrs = {}
|
||
element.attributes.each do |k, v|
|
||
next if HIDDEN_ATTRIBUTES.include? k
|
||
obj_attrs[k.to_sym] = format_value(v)
|
||
end
|
||
obj_attrs
|
||
end
|
||
|
||
def format_result(list, format = nil)
|
||
case format
|
||
when :data_hash
|
||
if list.is_a? Array
|
||
list.collect{|element| dh_format_element(element) }
|
||
elsif list.is_a? Hash
|
||
result = {}
|
||
list.each{|element_name, element| result[element_name] = dh_format_element(element) }
|
||
result
|
||
else
|
||
dh_format_element(list)
|
||
end
|
||
else
|
||
list
|
||
end
|
||
end
|
||
|
||
def index_result(list, primary_attr)
|
||
idx_list = {}
|
||
list.each{|i| idx_list[i.send(primary_attr)] = i }
|
||
idx_list
|
||
end
|
||
end
|
||
end # LibrarianLand
|
||
end
|
lib/cyborghood/cyborg/botnet/interface.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
def attr_search_node
|
||
def attr_search_node(list = nil, &block)
|
||
list ||= block
|
||
|
||
lookup_node = self
|
||
|
||
node '?', :hidden => true do
|
||
... | ... | |
if request.args.empty?
|
||
request.reply.results = lookup_node.__send__(:visible_nodes_names)
|
||
else
|
||
node_names_list = []
|
||
|
||
lookup_node.__send__(:visible_nodes).each do |match, node|
|
||
if match.is_a? String
|
||
match_list = [match]
|
||
elsif match.is_a? Proc
|
||
match_list = match.call
|
||
else
|
||
next
|
||
end
|
||
|
||
match_list.each do |child_node_name|
|
||
node.__send__(:load, child_node_name)
|
||
result = node.__send__(:request, request.session)
|
||
next unless result.respond_to? :to_hash
|
||
|
||
if hash_match_criterias(result.to_hash, request.args.first)
|
||
node_names_list << child_node_name
|
||
end
|
||
end
|
||
end
|
||
|
||
request.reply.results = node_names_list
|
||
request.reply.results = list.nil? ? search_among_children(request, lookup_node) :
|
||
search_in_list(request, lookup_node, list)
|
||
end
|
||
end
|
||
end
|
||
... | ... | |
|
||
def _call(session, node_path, args = nil)
|
||
args ||= []
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "wrong format for arguments") unless args.is_a? Array
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "wrong format for arguments when calling node '#{node_path}'") unless args.is_a? Array
|
||
|
||
node = find_node(session, node_path)
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "unknown node") if node.nil?
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "unknown node '#{node_path}'") if node.nil?
|
||
|
||
logger.debug "[Server API] Node '#{node_path}' found"
|
||
node.__send__(:request, session, args)
|
||
... | ... | |
rescue
|
||
logger.debug "node request error message: " + $!
|
||
logger.debug "node request error backtrace: " + $!.backtrace.join("\n")
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "method call failed: " + $!)
|
||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "call failed on node '#{node_path}': " + $!)
|
||
end
|
||
else
|
||
visible_nodes_names
|
||
... | ... | |
|
||
def hash_match_criterias(hash, crit)
|
||
crit.each do |key, wanted_value|
|
||
value = hash[key]
|
||
# force cast to string in case of a composite object
|
||
value = hash[key].to_s
|
||
|
||
if wanted_value.is_a? Array
|
||
return false unless wanted_value.include?(value)
|
||
... | ... | |
|
||
true
|
||
end
|
||
|
||
def search_among_children(request, lookup_node)
|
||
node_names_list = []
|
||
|
||
lookup_node.__send__(:visible_nodes).each do |match, node|
|
||
if match.is_a? String
|
||
match_list = [match]
|
||
elsif match.is_a? Proc
|
||
match_list = match.call
|
||
else
|
||
next
|
||
end
|
||
|
||
match_list.each do |child_node_name|
|
||
node.__send__(:load, child_node_name)
|
||
result = node.__send__(:request, request.session)
|
||
next unless result.respond_to? :to_hash
|
||
|
||
if hash_match_criterias(result.to_hash, request.args.first)
|
||
node_names_list << child_node_name
|
||
end
|
||
end
|
||
end
|
||
|
||
node_names_list
|
||
end
|
||
|
||
def search_in_list(request, lookup_node, list)
|
||
criterias = request.args.first
|
||
return [] unless criterias.is_a? Hash
|
||
|
||
if list.is_a? Proc
|
||
list = list.call(criterias)
|
||
# if result is an array, then a final list of names is given, return it
|
||
return list if list.is_a? Array
|
||
# else it must be a Hash which needs to be filtered
|
||
end
|
||
|
||
node_names_list = []
|
||
|
||
list.each do |element_name, element|
|
||
if hash_match_criterias(element.to_hash, criterias)
|
||
node_names_list << element_name
|
||
end
|
||
end
|
||
|
||
node_names_list
|
||
end
|
||
end
|
||
end
|
||
end # DSL
|
||
end
|
Also available in: Unified diff
[evol] Librarian API work §3