root/bin/shadowwalker @ d9091cc0
89d8bebc | Marc Dequènes (Duck) | #!/usr/bin/ruby -Ku
|
|
#--
|
|||
# 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/>.
|
|||
#++
|
|||
# to allow in-place run for test
|
|||
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
|||
require 'ldap_shadows'
|
|||
bbb82941 | Marc Dequènes (Duck) | require 'ldap_shadows/display_utils'
|
|
89d8bebc | Marc Dequènes (Duck) | require 'yaml'
|
|
require 'cmdparse2'
|
|||
bbb82941 | Marc Dequènes (Duck) | include LdapShadows
|
|
b0304d30 | Marc Dequènes (Duck) | ||
89d8bebc | Marc Dequènes (Duck) | config_str = IO.read(File.join(LdapShadows::Config::CFG_DIR, "test.conf"))
|
|
1744c478 | Marc Dequènes (Duck) | config = YAML.load(config_str)
|
|
config_str_prv_filelist = [
|
|||
File.join(ENV['HOME'], ".shadowwalker"),
|
|||
File.join(LdapShadows::Config::CFG_DIR, "private.conf")
|
|||
]
|
|||
config_str_prv_filelist.each do |file|
|
|||
if File.exists?(file)
|
|||
config_str_prv = IO.read(file)
|
|||
config.merge!(YAML.load(config_str_prv))
|
|||
break
|
|||
end
|
|||
end
|
|||
config.recursive_symbolize_keys!
|
|||
89d8bebc | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | ||
bbb82941 | Marc Dequènes (Duck) | $program_options = {}
|
|
89d8bebc | Marc Dequènes (Duck) | cmdparser = CmdParse::CommandParser.new(true)
|
|
bbb82941 | Marc Dequènes (Duck) | cmdparser.banner = PRODUCT
|
|
5ca3fa56 | Marc Dequènes (Duck) | cmdparser.program_name = File.basename(__FILE__)
|
|
bbb82941 | Marc Dequènes (Duck) | cmdparser.program_version = VERSION.split(".")
|
|
89d8bebc | Marc Dequènes (Duck) | ||
cmdparser.options = CmdParse::OptionParserWrapper.new do |opt|
|
|||
opt.separator "Global options:"
|
|||
bbb82941 | Marc Dequènes (Duck) | opt.on("--debug", "Output debug info without being formated") {|t| $program_options[:debug] = true }
|
|
opt.on("--expert", "Output extra info for expert users") {|t| $program_options[:expert] = true }
|
|||
opt.on("--handles", "Output with handles (objects/field/... keys used for manipulations)") {|t| $program_options[:handles] = true }
|
|||
89d8bebc | Marc Dequènes (Duck) | end
|
|
cmdparser.add_command(CmdParse::HelpCommand.new)
|
|||
cmdparser.add_command(CmdParse::VersionCommand.new)
|
|||
304a503d | Marc Dequènes (Duck) | ||
$ldapctl = Controller.new
|
|||
$ldapctl.set_global_config(config[:presentation])
|
|||
89d8bebc | Marc Dequènes (Duck) | config[:aspects].each_pair do |aspect_name, aspect_data|
|
|
304a503d | Marc Dequènes (Duck) | $ldapctl.set_aspect(aspect_name, aspect_data)
|
|
89d8bebc | Marc Dequènes (Duck) | end
|
|
127edd07 | Marc Dequènes (Duck) | begin
|
|
ActiveLdap::Base.setup_connection(config[:ldap])
|
|||
config[:objects].each_pair do |obj_name, obj_data|
|
|||
304a503d | Marc Dequènes (Duck) | $ldapctl.load_object(obj_name, obj_data)
|
|
127edd07 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | $ldapctl.load_relations
|
|
127edd07 | Marc Dequènes (Duck) | rescue ActiveLdap::Error => e
|
|
STDERR.puts "LDAP connection error: " + e.to_s
|
|||
exit 3
|
|||
89d8bebc | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | class Command < CmdParse::Command
|
|
attr_accessor :usages_params
|
|||
def usage
|
|||
if @usages_params
|
|||
base_usage_str = super.sub("[ARGS]", "")
|
|||
usages = @usages_params.collect {|params| base_usage_str + params }
|
|||
usages.join("\n")
|
|||
else
|
|||
super
|
|||
6089b33a | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | end
|
|
end
|
|||
class ListCommand < Command
|
|||
def initialize
|
|||
super('list', false)
|
|||
a24bc5b1 | Marc Dequènes (Duck) | self.short_desc = "list objects, and items/aspects/fields of an object"
|
|
self.usages_params = [
|
|||
304a503d | Marc Dequènes (Duck) | ":objects",
|
|
a24bc5b1 | Marc Dequènes (Duck) | "<object>",
|
|
"<object> :aspects",
|
|||
"<object> :fields"
|
|||
304a503d | Marc Dequènes (Duck) | ]
|
|
end
|
|||
def execute (args)
|
|||
if args.size < 1
|
|||
STDERR.puts "syntax error: no object name given"
|
|||
6089b33a | Marc Dequènes (Duck) | exit 1
|
|
end
|
|||
a24bc5b1 | Marc Dequènes (Duck) | obj_hdl = args.shift.downcase.singularize
|
|
304a503d | Marc Dequènes (Duck) | case obj_hdl
|
|
when ':object'
|
|||
26a3ca45 | Marc Dequènes (Duck) | list = $ldapctl.objects
|
|
puts "=== List of LDAP objects (#{list.size}) ==="
|
|||
list.each do |obj_name|
|
|||
304a503d | Marc Dequènes (Duck) | puts " - #{obj_name}"
|
|
end
|
|||
else
|
|||
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
if obj_klass.nil?
|
|||
STDERR.puts "No such object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
89d8bebc | Marc Dequènes (Duck) | ||
a24bc5b1 | Marc Dequènes (Duck) | if args.empty?
|
|
obj_human_name = Translator.translate_object_name(obj_hdl)
|
|||
Display.display_item_list("List of #{obj_human_name.pluralize}", obj_klass.find(:all))
|
|||
else
|
|||
subobj_hdl = args.shift.downcase.singularize
|
|||
obj_human_name = Translator.translate_object_name(obj_hdl)
|
|||
case subobj_hdl
|
|||
when ':aspect'
|
|||
list = obj_klass.possible_aspects
|
|||
puts "=== List of LDAP Aspects of #{obj_human_name.pluralize} (#{list.size}) ==="
|
|||
list.each do |aspect|
|
|||
str = Translator.translate_aspect_name(aspect)
|
|||
str += " [#{aspect}]" if $program_options[:handles]
|
|||
puts " - #{str}"
|
|||
end
|
|||
when ':field'
|
|||
list = obj_klass.possible_attributes
|
|||
puts "=== List of LDAP Fields of #{obj_human_name.pluralize} (#{list.size}) ==="
|
|||
list.each do |field|
|
|||
str = Translator.translate_field_name(field)
|
|||
str += " [#{field}]" if $program_options[:handles]
|
|||
puts " - #{str}"
|
|||
end
|
|||
obj_klass.possible_aspects.each do |aspect|
|
|||
aspect_human_name = Translator.translate_aspect_name(aspect)
|
|||
list = obj_klass.possible_attributes_for_aspect(aspect)
|
|||
puts "--- Sublist of LDAP Fields for Aspect #{aspect_human_name} (#{list.size}) ---"
|
|||
list.each do |field|
|
|||
str = Translator.translate_field_name(field)
|
|||
str += " [#{field}]" if $program_options[:handles]
|
|||
puts " - #{str}"
|
|||
end
|
|||
end
|
|||
else
|
|||
37849308 | Marc Dequènes (Duck) | STDERR.puts "No such subobject '#{subobj_hdl}'."
|
|
exit 2
|
|||
a24bc5b1 | Marc Dequènes (Duck) | end
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | end
|
|
89d8bebc | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | end
|
|
cmdparser.add_command(ListCommand.new)
|
|||
class ShowCommand < Command
|
|||
def initialize
|
|||
super('show', false)
|
|||
self.short_desc = "show item information"
|
|||
self.usages_params = [
|
|||
"<object> <item>",
|
|||
"<object> <item> <field>#?",
|
|||
"<object> <item> <field>[#<index>]"
|
|||
]
|
|||
89d8bebc | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | def execute (args)
|
|
if args.size < 1
|
|||
STDERR.puts "syntax error: no object name given"
|
|||
exit 1
|
|||
end
|
|||
if args.size < 2
|
|||
STDERR.puts "syntax error: no item name given"
|
|||
exit 1
|
|||
end
|
|||
ca51664c | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | obj_hdl = args.shift
|
|
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
if obj_klass.nil?
|
|||
STDERR.puts "No such object '#{obj_hdl}'."
|
|||
ca51664c | Marc Dequènes (Duck) | exit 2
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | ||
item_hdl = args.shift
|
|||
begin
|
|||
item = obj_klass.find(item_hdl, :attributes => ["*", "+"])
|
|||
rescue ActiveLdap::EntryNotFound
|
|||
STDERR.puts "No such item '#{obj_hdl}/#{item_hdl}'"
|
|||
ca51664c | Marc Dequènes (Duck) | exit 2
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | if args.empty?
|
|
$program_options[:skip_binary] = true
|
|||
Display.display_item(item, $program_options)
|
|||
ca51664c | Marc Dequènes (Duck) | else
|
|
304a503d | Marc Dequènes (Duck) | field_info = args.shift
|
|
field_name, file_no = field_info.split("#")
|
|||
ca51664c | Marc Dequènes (Duck) | ||
5d28ad6e | Marc Dequènes (Duck) | unless item.has_field?(field_name)
|
|
304a503d | Marc Dequènes (Duck) | STDERR.puts "No such field '#{field_name}' in object '#{obj_hdl}'."
|
|
ca51664c | Marc Dequènes (Duck) | exit 2
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | unless item.attribute_present?(field_name)
|
|
STDERR.puts "Field '#{field_name}' in item '#{obj_hdl}/#{item_hdl}' is not present."
|
|||
ca51664c | Marc Dequènes (Duck) | exit 2
|
|
end
|
|||
5d28ad6e | Marc Dequènes (Duck) | field_data = item.send(field_name, true)
|
|
ca51664c | Marc Dequènes (Duck) | ||
11c9a6c9 | Marc Dequènes (Duck) | result_is_binary = false
|
|
304a503d | Marc Dequènes (Duck) | if file_no == "?"
|
|
result = field_data.size
|
|||
else
|
|||
file_no_i = file_no.to_i
|
|||
file_no = (file_no_i.to_s == file_no) ? file_no_i : nil
|
|||
ca51664c | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | attr_info = ActiveLdap::Base.schema.attribute(field_name)
|
|
field_single = attr_info.single_value?
|
|||
if file_no.nil? and not field_single
|
|||
STDERR.puts "Field '#{field_name}' in object '#{obj_hdl}' has multiple values, but you didn't select one."
|
|||
exit 2
|
|||
ca51664c | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | ||
file_no = 0 if file_no.nil?
|
|||
if file_no > 0 and field_single
|
|||
STDERR.puts "Field '#{field_name}' in object '#{obj_hdl}' has only a single value"
|
|||
exit 2
|
|||
end
|
|||
if file_no < 0 or file_no >= field_data.size
|
|||
STDERR.puts "Field '#{field_name}' in object '#{obj_hdl}' doesn't have such file number '#{file_no}' (select in range [0, #{field_data.size - 1}])"
|
|||
exit 2
|
|||
end
|
|||
11c9a6c9 | Marc Dequènes (Duck) | result = field_data[file_no]
|
|
result_is_binary = attr_info.binary?
|
|||
ca51664c | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | if args.empty?
|
|
11c9a6c9 | Marc Dequènes (Duck) | if result_is_binary
|
|
# output binary data without newline, so it can be pipped or redirected easily
|
|||
STDOUT.write result
|
|||
else
|
|||
puts result
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | else
|
|
file_name = args.shift
|
|||
if File.exists?(file_name)
|
|||
STDERR.puts "File '#{file_name}' already exists, and i won't overwrite it."
|
|||
exit 2
|
|||
end
|
|||
begin
|
|||
open(file_name, "w") do |fp|
|
|||
fp.write result
|
|||
end
|
|||
rescue
|
|||
STDERR.puts "Cannot save file: " + $!
|
|||
exit 3
|
|||
end
|
|||
puts "File saved."
|
|||
end
|
|||
ca51664c | Marc Dequènes (Duck) | end
|
|
end
|
|||
89d8bebc | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | cmdparser.add_command(ShowCommand.new)
|
|
89d8bebc | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | class TreeCommand < Command
|
|
def initialize
|
|||
super('tree', false)
|
|||
0d75a0b6 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | self.short_desc = "show skeleton items tree"
|
|
self.usages_params = [
|
|||
""
|
|||
]
|
|||
end
|
|||
def execute (args)
|
|||
puts "Tree:"
|
|||
base_dn = ActiveLdap::DistinguishedName.parse(LdapObject.base)
|
|||
0d75a0b6 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | gconfig = $ldapctl.get_global_config()
|
|
if gconfig.has_key?(:tree_objects)
|
|||
tree = {}
|
|||
0d75a0b6 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | gconfig[:tree_objects].each do |obj_hdl|
|
|
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
raise "object '#{obj_hdl}' not defined" unless obj_klass
|
|||
0d75a0b6 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | obj_klass.find(:all).each do |obj|
|
|
ptree = tree
|
|||
pdn = nil
|
|||
(obj.dn_obj - base_dn).to_s.split(',').reverse.each do |pdn|
|
|||
ptree[pdn] = {} unless ptree.has_key?(pdn)
|
|||
ptree = ptree[pdn]
|
|||
end
|
|||
ptree = nil
|
|||
0d75a0b6 | Marc Dequènes (Duck) | end
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | tree = {base_dn => tree}
|
|
0d75a0b6 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | Display.display_hash_tree(tree, 0)
|
|
end
|
|||
0d75a0b6 | Marc Dequènes (Duck) | end
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | cmdparser.add_command(TreeCommand.new)
|
|
b0304d30 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | class ModCommand < Command
|
|
def initialize
|
|||
super('mod', false)
|
|||
b0304d30 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | self.short_desc = "Modify attributes of an item"
|
|
self.usages_params = [
|
|||
d9091cc0 | Marc Dequènes (Duck) | "<object> <item> (<field>|<relation>|:aspects)(=|+=|-=)<value> [(<field>|<relation>|:aspects)(=|+=|-=)<value>] ..."
|
|
304a503d | Marc Dequènes (Duck) | ]
|
|
b0304d30 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | def execute (args)
|
|
if args.size < 1
|
|||
STDERR.puts "syntax error: no object name given"
|
|||
0814bfc3 | Marc Dequènes (Duck) | exit 1
|
|
end
|
|||
304a503d | Marc Dequènes (Duck) | if args.size < 2
|
|
STDERR.puts "syntax error: no item name given"
|
|||
exit 1
|
|||
0814bfc3 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | obj_hdl = args.shift
|
|
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
if obj_klass.nil?
|
|||
STDERR.puts "No such object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
43bd8057 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | item_hdl = args.shift
|
|
begin
|
|||
item = obj_klass.find(item_hdl)
|
|||
rescue ActiveLdap::EntryNotFound
|
|||
STDERR.puts "No such item '#{obj_hdl}/#{item_hdl}'"
|
|||
exit 2
|
|||
end
|
|||
43bd8057 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | modification_done = false
|
|
args.each do |mod_info|
|
|||
d9091cc0 | Marc Dequènes (Duck) | mod_info =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|\+=|-=)(.*)$/
|
|
304a503d | Marc Dequènes (Duck) | key = $1
|
|
op = $2
|
|||
val = $3
|
|||
43bd8057 | Marc Dequènes (Duck) | ||
d9091cc0 | Marc Dequènes (Duck) | if key.nil? or op.nil?
|
|
STDERR.puts "Syntax error in modification parameters: invalid field name, or missing/unknown operator, or empty value"
|
|||
304a503d | Marc Dequènes (Duck) | exit 1
|
|
34cb4054 | Marc Dequènes (Duck) | end
|
|
43bd8057 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | if key.index(":")
|
|
type, field = key.split(":")
|
|||
else
|
|||
type = nil
|
|||
field = key
|
|||
43bd8057 | Marc Dequènes (Duck) | end
|
|
0814bfc3 | Marc Dequènes (Duck) | ||
43bd8057 | Marc Dequènes (Duck) | case type
|
|
when nil
|
|||
5d28ad6e | Marc Dequènes (Duck) | unless item.has_field?(field)
|
|
304a503d | Marc Dequènes (Duck) | STDERR.puts "No such field '#{field}' in object '#{obj_hdl}'."
|
|
exit 2
|
|||
43bd8057 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | attr_info = ActiveLdap::Base.schema.attribute(field)
|
|
if attr_info.read_only?
|
|||
STDERR.puts "The field '#{field}' cannot be modified (read only), skipping."
|
|||
next
|
|||
end
|
|||
11c9a6c9 | Marc Dequènes (Duck) | if attr_info.binary?
|
|
unless File.exists?(val)
|
|||
STDERR.puts "The field '#{field}' contains binary data, you must provide a filename instead of a direct value."
|
|||
exit 2
|
|||
end
|
|||
begin
|
|||
val = File.read(val)
|
|||
rescue
|
|||
STDERR.puts "The file for the binary field '#{field}' cannot be read: " + $!
|
|||
exit 2
|
|||
end
|
|||
end
|
|||
5d28ad6e | Marc Dequènes (Duck) | old_val = item.send(field, true)
|
|
43bd8057 | Marc Dequènes (Duck) | when 'rel'
|
|
304a503d | Marc Dequènes (Duck) | unless item.relations.include?(field)
|
|
STDERR.puts "No such relation '#{field}' for object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
rel_info = item.info_for_relation(field)
|
|||
if rel_info[:read_only]
|
|||
STDERR.puts "The relation '#{field}' cannot be modified (read only), skipping."
|
|||
next
|
|||
43bd8057 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | # fetch remote object in relation, which will be the real 'val'
|
|
foreign_item_list = rel_info[:foreign_klass].find(:all, val)
|
|||
if foreign_item_list.empty?
|
|||
STDERR.puts "Foreign item '#{val}' for relation '#{field}' not found."
|
|||
exit 2
|
|||
end
|
|||
if foreign_item_list.size > 1
|
|||
STDERR.puts "Ambiguous item '#{val}' for relation '#{field}' (#{foreign_item_list.size} possible items)"
|
|||
exit 4
|
|||
end
|
|||
val = foreign_item_list.first
|
|||
d9091cc0 | Marc Dequènes (Duck) | when ''
|
|
case field
|
|||
when 'aspects'
|
|||
unless item.class.possible_aspects.include?(val)
|
|||
STDERR.puts "No such aspect '#{val}' for object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
else
|
|||
STDERR.puts "Unknown core field '#{field}'"
|
|||
exit 2
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | else
|
|
STDERR.puts "Unknown type '#{type}' for field '#{field}'."
|
|||
d9091cc0 | Marc Dequènes (Duck) | exit 2
|
|
0814bfc3 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | ||
# if val is nil or the latest value is removed, then the atribute is removed from the object,
|
|||
# or the association's attribute is removed from one side
|
|||
case op
|
|||
when '='
|
|||
d9091cc0 | Marc Dequènes (Duck) | if type == '' and field == 'aspects'
|
|
STDERR.puts "The equality operator is not possible for aspects."
|
|||
exit 2
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | item.send(field + "=", [val])
|
|
when '+='
|
|||
case type
|
|||
when nil
|
|||
if attr_info.single_value?
|
|||
STDERR.puts "The field '#{field}' cannot hold more than one value."
|
|||
exit 3
|
|||
end
|
|||
new_val = old_val << val
|
|||
item.send(field + "=", new_val)
|
|||
when 'rel'
|
|||
if rel_info[:single_value]
|
|||
STDERR.puts "The relation '#{field}' cannot hold more than one foreign item."
|
|||
exit 3
|
|||
end
|
|||
item.send(field) << val
|
|||
d9091cc0 | Marc Dequènes (Duck) | when ''
|
|
case field
|
|||
when 'aspects'
|
|||
item.add_aspect(val)
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | end
|
|
when '-='
|
|||
case type
|
|||
when nil
|
|||
new_val = old_val - [val]
|
|||
11c9a6c9 | Marc Dequènes (Duck) | item.send(field + "=", new_val)
|
|
304a503d | Marc Dequènes (Duck) | when 'rel'
|
|
item.send(field).delete(val)
|
|||
d9091cc0 | Marc Dequènes (Duck) | when ''
|
|
case field
|
|||
when 'aspects'
|
|||
item.remove_aspect(val)
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | end
|
|
else
|
|||
STDERR.puts "Syntax error in modification parameters: wrong operator"
|
|||
exit 1
|
|||
43bd8057 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | modification_done = true
|
|
end
|
|||
if modification_done
|
|||
d9091cc0 | Marc Dequènes (Duck) | missing_fields = item.missing_attributes
|
|
unless missing_fields.empty?
|
|||
STDERR.puts "Cannot save the modifications; the following fields are missing:"
|
|||
missing_fields.each do |field|
|
|||
str = Translator.translate_field_name(field)
|
|||
str += " [#{field}]" if $program_options[:handles]
|
|||
puts " - #{str}"
|
|||
end
|
|||
exit 2
|
|||
end
|
|||
304a503d | Marc Dequènes (Duck) | begin
|
|
item.save!
|
|||
rescue ActiveLdap::OperationNotPermitted => e
|
|||
STDERR.puts "You don't have enough rights to modify--at least--one of these attributes."
|
|||
exit 3
|
|||
end
|
|||
puts "Modification done."
|
|||
0814bfc3 | Marc Dequènes (Duck) | else
|
|
304a503d | Marc Dequènes (Duck) | puts "Nothing to do."
|
|
0814bfc3 | Marc Dequènes (Duck) | end
|
|
b0304d30 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | end
|
|
cmdparser.add_command(ModCommand.new)
|
|||
0814bfc3 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | class DelCommand < Command
|
|
def initialize
|
|||
super('del', false)
|
|||
self.short_desc = "Delete an item"
|
|||
self.usages_params = [
|
|||
5d28ad6e | Marc Dequènes (Duck) | "<object> <item>"
|
|
304a503d | Marc Dequènes (Duck) | ]
|
|
end
|
|||
def execute (args)
|
|||
if args.size < 1
|
|||
STDERR.puts "syntax error: no object name given"
|
|||
exit 1
|
|||
end
|
|||
if args.size < 2
|
|||
STDERR.puts "syntax error: no item name given"
|
|||
exit 1
|
|||
end
|
|||
obj_hdl = args.shift
|
|||
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
if obj_klass.nil?
|
|||
STDERR.puts "No such object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
item_hdl = args.shift
|
|||
34cb4054 | Marc Dequènes (Duck) | begin
|
|
304a503d | Marc Dequènes (Duck) | item = obj_klass.find(item_hdl, :attributes => ["*", "+"])
|
|
rescue ActiveLdap::EntryNotFound
|
|||
STDERR.puts "No such item '#{obj_hdl}/#{item_hdl}'"
|
|||
exit 2
|
|||
34cb4054 | Marc Dequènes (Duck) | end
|
|
b0304d30 | Marc Dequènes (Duck) | ||
304a503d | Marc Dequènes (Duck) | item.delete
|
|
puts "Deletion done."
|
|||
34cb4054 | Marc Dequènes (Duck) | end
|
|
b0304d30 | Marc Dequènes (Duck) | end
|
|
304a503d | Marc Dequènes (Duck) | cmdparser.add_command(DelCommand.new)
|
|
5d28ad6e | Marc Dequènes (Duck) | class CreateCommand < Command
|
|
def initialize
|
|||
super('create', false)
|
|||
self.short_desc = "Create an item"
|
|||
self.usages_params = [
|
|||
"<object> <new_item> [<field>=<value>] ..."
|
|||
]
|
|||
end
|
|||
def execute (args)
|
|||
if args.size < 1
|
|||
STDERR.puts "syntax error: no object name given"
|
|||
exit 1
|
|||
end
|
|||
if args.size < 2
|
|||
STDERR.puts "syntax error: no item name given"
|
|||
exit 1
|
|||
end
|
|||
obj_hdl = args.shift
|
|||
obj_klass = $ldapctl.find_klass(obj_hdl)
|
|||
if obj_klass.nil?
|
|||
STDERR.puts "No such object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
item_hdl = args.shift
|
|||
item = obj_klass.new(item_hdl)
|
|||
args.each do |param|
|
|||
param =~ /^([a-zA-Z]+)=(.*)$/
|
|||
key = $1
|
|||
val = $2
|
|||
d9091cc0 | Marc Dequènes (Duck) | val = nil if val == ''
|
|
5d28ad6e | Marc Dequènes (Duck) | if key.nil?
|
|
STDERR.puts "Syntax error in creation parameters: invalid field name"
|
|||
exit 1
|
|||
end
|
|||
field = key
|
|||
unless item.has_field?(field)
|
|||
STDERR.puts "No such field '#{field}' in object '#{obj_hdl}'."
|
|||
exit 2
|
|||
end
|
|||
attr_info = ActiveLdap::Base.schema.attribute(field)
|
|||
if attr_info.read_only?
|
|||
STDERR.puts "The field '#{field}' cannot be modified (read only), skipping."
|
|||
next
|
|||
end
|
|||
if attr_info.binary?
|
|||
unless File.exists?(val)
|
|||
STDERR.puts "The field '#{field}' contains binary data, you must provide a filename instead of a direct value."
|
|||
exit 2
|
|||
end
|
|||
begin
|
|||
val = File.read(val)
|
|||
rescue
|
|||
STDERR.puts "The file for the binary field '#{field}' cannot be read: " + $!
|
|||
exit 2
|
|||
end
|
|||
end
|
|||
item.send(field + "=", val)
|
|||
end
|
|||
d9091cc0 | Marc Dequènes (Duck) | missing_fields = item.missing_attributes
|
|
unless missing_fields.empty?
|
|||
STDERR.puts "Cannot save the new item; the following fields are missing:"
|
|||
missing_fields.each do |field|
|
|||
str = Translator.translate_field_name(field)
|
|||
str += " [#{field}]" if $program_options[:handles]
|
|||
puts " - #{str}"
|
|||
end
|
|||
exit 2
|
|||
end
|
|||
5d28ad6e | Marc Dequènes (Duck) | item.save!
|
|
end
|
|||
end
|
|||
cmdparser.add_command(CreateCommand.new)
|
|||
b0304d30 | Marc Dequènes (Duck) | ||
127edd07 | Marc Dequènes (Duck) | begin
|
|
cmdparser.parse
|
|||
rescue ActiveLdap::EntryInvalid => e
|
|||
11c9a6c9 | Marc Dequènes (Duck) | # work around #26758
|
|
STDERR.puts e.to_s.sub(/invalid format: .*: required syntax:/, "invalid format. required syntax:")
|
|||
127edd07 | Marc Dequènes (Duck) | exit 3
|
|
rescue ActiveLdap::OperationNotPermitted => e
|
|||
STDERR.puts "You don't have enough rights for this operation."
|
|||
exit 3
|
|||
rescue ActiveLdap::Error => e
|
|||
STDERR.puts "LDAP error: " + e.to_s
|
|||
exit 3
|
|||
end
|