activeldap 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/CHANGES +648 -567
  2. data/README +53 -48
  3. data/Rakefile +25 -53
  4. data/TODO +2 -0
  5. data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
  6. data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
  7. data/examples/al-admin/app/controllers/application_controller.rb +1 -1
  8. data/examples/al-admin/app/views/_entry/_attributes_information.html.erb +7 -1
  9. data/examples/al-admin/app/views/users/_attributes_update_form.html.erb +13 -1
  10. data/examples/al-admin/config/environment.rb +2 -3
  11. data/lib/active_ldap.rb +103 -98
  12. data/lib/active_ldap/association/belongs_to_many.rb +7 -7
  13. data/lib/active_ldap/association/has_many.rb +4 -4
  14. data/lib/active_ldap/associations.rb +29 -5
  15. data/lib/active_ldap/attributes.rb +5 -1
  16. data/lib/active_ldap/base.rb +17 -13
  17. data/lib/active_ldap/configuration.rb +3 -4
  18. data/lib/active_ldap/connection.rb +3 -3
  19. data/lib/active_ldap/get_text/parser.rb +4 -2
  20. data/lib/active_ldap/helper.rb +59 -0
  21. data/lib/active_ldap/operations.rb +15 -10
  22. data/lib/active_ldap/xml.rb +22 -30
  23. data/po/en/active-ldap.po +221 -154
  24. data/po/ja/active-ldap.po +237 -178
  25. data/test-unit/History.txt +26 -0
  26. data/test-unit/Manifest.txt +1 -1
  27. data/test-unit/README.txt +1 -0
  28. data/test-unit/Rakefile +6 -1
  29. data/test-unit/lib/test/unit/autorunner.rb +6 -0
  30. data/test-unit/lib/test/unit/testcase.rb +101 -36
  31. data/test-unit/test/{test_testcase.rb → test-testcase.rb} +30 -1
  32. data/test-unit/test/test_assertions.rb +1 -1
  33. data/test/al-test-utils.rb +3 -1
  34. data/test/test_associations.rb +75 -6
  35. data/test/test_base.rb +45 -3
  36. metadata +75 -45
  37. data/examples/al-admin/config/initializers/gettext.rb +0 -15
@@ -6,11 +6,11 @@ module ActiveLdap
6
6
  private
7
7
  def insert_entry(entry)
8
8
  old_value = entry[@options[:many], true]
9
- foreign_key_name = @options[:foreign_key_name]
10
- if foreign_key_name == "dn"
9
+ primary_key_name = @options[:primary_key_name]
10
+ if primary_key_name == "dn"
11
11
  old_value = dn_values_to_string_values(old_value)
12
12
  end
13
- new_value = old_value + @owner[foreign_key_name, true]
13
+ new_value = old_value + @owner[primary_key_name, true]
14
14
  new_value = new_value.uniq.sort
15
15
  if old_value != new_value
16
16
  entry[@options[:many]] = new_value
@@ -21,11 +21,11 @@ module ActiveLdap
21
21
  def delete_entries(entries)
22
22
  entries.each do |entry|
23
23
  old_value = entry[@options[:many], true]
24
- foreign_key_name = @options[:foreign_key_name]
25
- if foreign_key_name == "dn"
24
+ primary_key_name = @options[:primary_key_name]
25
+ if primary_key_name == "dn"
26
26
  old_value = dn_values_to_string_values(old_value)
27
27
  end
28
- new_value = old_value - @owner[foreign_key_name, true]
28
+ new_value = old_value - @owner[primary_key_name, true]
29
29
  new_value = new_value.uniq.sort
30
30
  if old_value != new_value
31
31
  entry[@options[:many]] = new_value
@@ -35,7 +35,7 @@ module ActiveLdap
35
35
  end
36
36
 
37
37
  def find_target
38
- values = @owner[@options[:foreign_key_name], true].compact
38
+ values = @owner[@options[:primary_key_name], true].compact
39
39
  return [] if values.empty?
40
40
 
41
41
  key = @options[:many]
@@ -8,17 +8,17 @@ module ActiveLdap
8
8
 
9
9
  private
10
10
  def insert_entry(entry)
11
- entry[primary_key] = @owner[@options[:foreign_key_name]]
11
+ entry[@options[:foreign_key_name]] = @owner[primary_key]
12
12
  entry.save
13
13
  end
14
14
 
15
15
  def find_target
16
- collect_targets(:foreign_key_name)
16
+ collect_targets(:primary_key_name)
17
17
  end
18
18
 
19
19
  def delete_entries(entries)
20
- key = primary_key
21
- components = @owner[@options[:foreign_key_name], true].reject do |value|
20
+ key = @options[:foreign_key_name]
21
+ components = @owner[primary_key, true].reject do |value|
22
22
  value.nil?
23
23
  end
24
24
  filter = [:and,
@@ -37,7 +37,9 @@ module ActiveLdap
37
37
  # Example:
38
38
  # belongs_to :groups, :class_name => "Group",
39
39
  # :many => "memberUid" # Group#memberUid
40
- # # :foreign_key => "uid" # User#uid
40
+ # # :primary_key => "uid" # User#uid
41
+ # ## deprecated since 1.1.0. Use :primary_key instead.
42
+ # ## :foreign_key => "uid" # User#uid
41
43
  # # dn attribute value is used by default
42
44
  # belongs_to :primary_group, :class_name => "Group",
43
45
  # :foreign_key => "gidNumber", # User#gidNumber
@@ -61,7 +63,14 @@ module ActiveLdap
61
63
  }
62
64
  if opts[:many]
63
65
  association_class = Association::BelongsToMany
64
- opts[:foreign_key_name] ||= dn_attribute
66
+ foreign_key_name = opts[:foreign_key_name]
67
+ if foreign_key_name
68
+ message = _(":foreign_key belongs_to(:many) option is " \
69
+ "deprecated since 1.1.0. Use :primary_key instead.")
70
+ ActiveSupport::Deprecation.warn(message)
71
+ opts[:primary_key_name] ||= foreign_key_name
72
+ end
73
+ opts[:primary_key_name] ||= dn_attribute
65
74
  else
66
75
  association_class = Association::BelongsTo
67
76
  opts[:foreign_key_name] ||= "#{association_id}_id"
@@ -92,15 +101,19 @@ module ActiveLdap
92
101
  #
93
102
  # Example:
94
103
  # has_many :primary_members, :class_name => "User",
95
- # :primary_key => "gidNumber", # User#gidNumber
96
- # :foreign_key => "gidNumber" # Group#gidNumber
104
+ # :primary_key => "gidNumber", # Group#gidNumber
105
+ # :foreign_key => "gidNumber" # User#gidNumber
106
+ # ## deprecated since 1.1.0. Those options
107
+ # ## are inverted.
108
+ # # :primary_key => "gidNumber", # User#gidNumber
109
+ # # :foreign_key => "gidNumber" # Group#gidNumber
97
110
  # has_many :members, :class_name => "User",
98
111
  # :wrap => "memberUid" # Group#memberUid
99
112
  def has_many(association_id, options = {})
100
113
  validate_has_many_options(options)
101
114
  klass = options[:class]
102
115
  klass ||= (options[:class_name] || association_id.to_s).classify
103
- foreign_key = options[:foreign_key] || "#{association_id}_id"
116
+ foreign_key = options[:foreign_key]
104
117
  primary_key = options[:primary_key]
105
118
  set_associated_class(association_id, klass)
106
119
 
@@ -112,9 +125,20 @@ module ActiveLdap
112
125
  :extend => options[:extend],
113
126
  }
114
127
  if opts[:wrap]
128
+ opts[:foreign_key_name] ||= "#{association_id}_id"
115
129
  association_class = Association::HasManyWrap
116
130
  else
117
131
  association_class = Association::HasMany
132
+ primary_key_name = opts[:primary_key_name]
133
+ foreign_key_name = opts[:foreign_key_name]
134
+ if primary_key_name != foreign_key_name and
135
+ !new.have_attribute?(primary_key_name)
136
+ message = _(":primary_key and :foreign_key has_many options are " \
137
+ "inverted their mean since 1.1.0. Please invert them.")
138
+ ActiveSupport::Deprecation.warn(message)
139
+ opts[:foreign_key_name] = primary_key_name
140
+ opts[:primary_key_name] = foreign_key_name
141
+ end
118
142
  end
119
143
 
120
144
  association_accessor(association_id) do |target|
@@ -40,8 +40,11 @@ module ActiveLdap
40
40
  when Hash
41
41
  result = {}
42
42
  value.each do |k, v|
43
- result[k] = remove_blank_value(v) || []
43
+ v = remove_blank_value(v)
44
+ next if v.nil?
45
+ result[k] = v
44
46
  end
47
+ result = nil if result.blank?
45
48
  result
46
49
  when Array
47
50
  result = []
@@ -50,6 +53,7 @@ module ActiveLdap
50
53
  next if v.nil?
51
54
  result << v
52
55
  end
56
+ result = nil if result.blank?
53
57
  result
54
58
  when String
55
59
  if /\A\s*\z/ =~ value
@@ -678,7 +678,17 @@ module ActiveLdap
678
678
  # [ User.find("a"), User.find("b"), User.find("c") ] &
679
679
  # [ User.find("a"), User.find("d") ] # => [ User.find("a") ]
680
680
  def hash
681
- dn.hash
681
+ return super if @_hashing # workaround for GetText :<
682
+ _dn = nil
683
+ begin
684
+ @_hashing = true
685
+ _dn = dn
686
+ rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
687
+ return super
688
+ ensure
689
+ @_hashing = false
690
+ end
691
+ _dn.hash
682
692
  end
683
693
 
684
694
  def may
@@ -897,6 +907,7 @@ module ActiveLdap
897
907
  def to_xml(options={})
898
908
  options = options.dup
899
909
  options[:root] ||= (self.class.name || '').underscore
910
+ options[:root] = 'anonymous' if options[:root].blank?
900
911
  except = options[:except]
901
912
  if except
902
913
  options[:except] = except.collect do |name|
@@ -1151,6 +1162,7 @@ module ActiveLdap
1151
1162
  @dn_is_base = false
1152
1163
  @dn_split_value = nil
1153
1164
  @connection ||= nil
1165
+ @_hashing = false
1154
1166
  clear_connection_based_cache
1155
1167
  end
1156
1168
 
@@ -1322,7 +1334,7 @@ module ActiveLdap
1322
1334
  ensure_update_dn
1323
1335
  dn_value = id
1324
1336
  if dn_value.nil?
1325
- format =_("%s's DN attribute (%s) isn't set")
1337
+ format = _("%s's DN attribute (%s) isn't set")
1326
1338
  message = format % [self.inspect, dn_attribute]
1327
1339
  raise DistinguishedNameNotSetError.new, message
1328
1340
  end
@@ -1394,17 +1406,9 @@ module ActiveLdap
1394
1406
  value = self.class.remove_blank_value(value) || []
1395
1407
  next if v == value
1396
1408
 
1397
- # Create mod entries
1398
- if self.class.blank_value?(value)
1399
- # Since some types do not have equality matching rules,
1400
- # delete doesn't work
1401
- # Replacing with nothing is equivalent.
1402
- if !data.has_key?(k) and schema.attribute(k).binary_required?
1403
- value = [{'binary' => []}]
1404
- end
1405
- else
1406
- # Ditched delete then replace because attribs with no equality
1407
- # match rules will fails
1409
+ if self.class.blank_value?(value) and
1410
+ schema.attribute(k).binary_required?
1411
+ value = [{'binary' => []}]
1408
1412
  end
1409
1413
  attributes.push([:replace, k, value])
1410
1414
  end
@@ -107,10 +107,9 @@ module ActiveLdap
107
107
  target.base = value.gsub(/['}{#]/, '')
108
108
  when :scope, :ldap_scope
109
109
  if key == :ldap_scope
110
- logger.warning do
111
- _(":ldap_scope configuration option is deprecated. " \
112
- "Use :scope instead.")
113
- end
110
+ message = _(":ldap_scope configuration option is deprecated. " \
111
+ "Use :scope instead.")
112
+ ActiveSupport::Deprecation.warn(message)
114
113
  end
115
114
  target.scope = value
116
115
  configuration[:scope] = value
@@ -95,9 +95,9 @@ module ActiveLdap
95
95
  raise AdapterNotFound.new(adapter)
96
96
  end
97
97
  if config.has_key?(:ldap_scope)
98
- logger.warning do
99
- _(":ldap_scope connection option is deprecated. Use :scope instead.")
100
- end
98
+ message = _(":ldap_scope connection option is deprecated. " \
99
+ "Use :scope instead.")
100
+ ActiveSupport::Deprecation.warn(message)
101
101
  config[:scope] ||= config.delete(:ldap_scope)
102
102
  end
103
103
  config = remove_connection_related_configuration(config)
@@ -11,7 +11,7 @@ module ActiveLdap
11
11
  configuration = default_configuration.merge(configuration)
12
12
 
13
13
  configuration = extract_options(configuration)
14
- ActiveLdap::Base.establish_connection(configuration)
14
+ ActiveLdap::Base.setup_connection(configuration)
15
15
  end
16
16
 
17
17
  def parse(file, targets=[])
@@ -72,7 +72,9 @@ module ActiveLdap
72
72
  if File.exists?(configuration)
73
73
  require 'erb'
74
74
  require 'yaml'
75
- configuration = YAML.load(ERB.new(File.read(configuration)).result)
75
+ erb = ERB.new(File.read(configuration))
76
+ erb.filename = configuration
77
+ configuration = YAML.load(erb.result)
76
78
  else
77
79
  ENV["RAILS_ENV"] = configuration
78
80
  require 'config/environment'
@@ -29,5 +29,64 @@ module ActiveLdap
29
29
  Base.human_syntax_description(syntax)
30
30
  end
31
31
  alias_method(:lsd_, :ldap_syntax_description_gettext)
32
+
33
+ def ldap_field(type, object_name, method, options={})
34
+ case type
35
+ when "radio_button", "check_box", "text_area"
36
+ form_method = type
37
+ else
38
+ form_method = "#{type}_field"
39
+ end
40
+
41
+ object = options[:object]
42
+ if object.nil?
43
+ normalized_object_name = object_name.to_s.sub(/\[\](\])?$/, "\\1")
44
+ object = instance_variable_get("@#{normalized_object_name}")
45
+ end
46
+ values = object.nil? ? nil : object[method, true]
47
+ values = [nil] if values.blank?
48
+ required_ldap_options = options.delete(:ldap_options) || []
49
+ required_ldap_options.each do |required_ldap_option|
50
+ found = false
51
+ values.each do |value|
52
+ next unless value.is_a?(Hash)
53
+ if Hash.to_a[0].to_s == required_ldap_option.to_s
54
+ found = true
55
+ break
56
+ end
57
+ end
58
+ values << {required_ldap_option => ""} unless found
59
+ end
60
+
61
+ fields = []
62
+ collect_values = Proc.new do |value, ldap_options|
63
+ case value
64
+ when Hash
65
+ value.each do |k, v|
66
+ collect_values.call(v, ldap_options + [k])
67
+ end
68
+ when Array
69
+ value.each do |v|
70
+ collect_values.call(v, ldap_options)
71
+ end
72
+ else
73
+ id = "#{object_name}_#{method}"
74
+ name = "#{object_name}[#{method}][]"
75
+ ldap_options.collect.each do |ldap_option|
76
+ id << "_#{ldap_option}"
77
+ name << "[#{ldap_option}][]"
78
+ end
79
+ ldap_value_options = {:id => id, :name => name, :value => value}
80
+ field = send(form_method, object_name, method,
81
+ ldap_value_options.merge(options))
82
+ if block_given?
83
+ field = yield(field, {:options => ldap_options, :value => value})
84
+ end
85
+ fields << field unless field.blank?
86
+ end
87
+ end
88
+ collect_values.call(values, [])
89
+ fields.join("\n")
90
+ end
32
91
  end
33
92
  end
@@ -46,9 +46,9 @@ module ActiveLdap
46
46
  _base = options[:base] ? [options[:base]] : [prefix, base]
47
47
  _base = prepare_search_base(_base)
48
48
  if options.has_key?(:ldap_scope)
49
- logger.warning do
50
- _(":ldap_scope search option is deprecated. Use :scope instead.")
51
- end
49
+ message = _(":ldap_scope search option is deprecated. " \
50
+ "Use :scope instead.")
51
+ ActiveSupport::Deprecation.warn(message)
52
52
  options[:scope] ||= options[:ldap_scope]
53
53
  end
54
54
  search_options = {
@@ -497,18 +497,23 @@ module ActiveLdap
497
497
  options[:connection].delete(dn, options)
498
498
  end
499
499
 
500
- def delete_all(filter=nil, options={})
501
- options = {:base => base, :scope => scope}.merge(options)
502
- options = options.merge(:filter => filter) if filter
503
- options[:connection] ||= connection
504
- conn = options[:connection]
505
- targets = conn.search(options).collect do |dn, attributes|
500
+ def delete_all(options_or_filter=nil, deprecated_options=nil)
501
+ if deprecated_options.nil?
502
+ if options_or_filter.is_a?(String)
503
+ options = {:filter => options_or_filter}
504
+ else
505
+ options = (options_or_filter || {}).dup
506
+ end
507
+ else
508
+ options = deprecated_options.merge(:filter => options_or_filter)
509
+ end
510
+ targets = search(options).collect do |dn, attributes|
506
511
  dn
507
512
  end.sort_by do |dn|
508
513
  dn.upcase.reverse
509
514
  end.reverse
510
515
 
511
- conn.delete(targets)
516
+ options[:connection].delete(targets)
512
517
  end
513
518
  end
514
519
 
@@ -1,4 +1,5 @@
1
1
  require 'erb'
2
+ require 'builder'
2
3
 
3
4
  require 'active_ldap/ldif'
4
5
 
@@ -16,17 +17,18 @@ module ActiveLdap
16
17
 
17
18
  def to_s
18
19
  root = @options[:root]
19
- result = "<#{root}>\n"
20
- target_attributes.each do |key, values|
21
- values = normalize_values(values).sort_by {|value, _| value}
22
- if @schema.attribute(key).single_value?
23
- result << " #{serialize_attribute_value(key, *values[0])}\n"
24
- else
25
- result << serialize_attribute_values(key, values)
20
+ indent = @options[:indent] || 2
21
+ xml = @options[:builder] || Builder::XmlMarkup.new(:indent => indent)
22
+ xml.tag!(root) do
23
+ target_attributes.each do |key, values|
24
+ values = normalize_values(values).sort_by {|value, _| value}
25
+ if @schema.attribute(key).single_value?
26
+ serialize_attribute_value(xml, key, *values[0])
27
+ else
28
+ serialize_attribute_values(xml, key, values)
29
+ end
26
30
  end
27
31
  end
28
- result << "</#{root}>\n"
29
- result
30
32
  end
31
33
 
32
34
  private
@@ -77,36 +79,26 @@ module ActiveLdap
77
79
  targets
78
80
  end
79
81
 
80
- def serialize_attribute_values(name, values)
81
- return "" if values.blank?
82
+ def serialize_attribute_values(xml, name, values)
83
+ return if values.blank?
82
84
 
83
- result = ""
84
85
  if name == "dn" or @options[:type].to_s.downcase == "ldif"
85
- values.collect do |value, xml_attributes|
86
- xml = serialize_attribute_value(name, value, xml_attributes)
87
- result << " #{xml}\n"
86
+ values.each do |value, xml_attributes|
87
+ serialize_attribute_value(xml, name, value, xml_attributes)
88
88
  end
89
89
  else
90
90
  plural_name = name.pluralize
91
- result << " <#{plural_name} type=\"array\">\n"
92
- values.each do |value, xml_attributes|
93
- xml = serialize_attribute_value(name, value, xml_attributes)
94
- result << " #{xml}\n"
91
+ attributes = @options[:skip_types] ? {} : {"type" => "array"}
92
+ xml.tag!(plural_name, attributes) do
93
+ values.each do |value, xml_attributes|
94
+ serialize_attribute_value(xml, name, value, xml_attributes)
95
+ end
95
96
  end
96
- result << " </#{plural_name}>\n"
97
97
  end
98
- result
99
98
  end
100
99
 
101
- def serialize_attribute_value(name, value, xml_attributes)
102
- if xml_attributes.blank?
103
- xml_attributes = ""
104
- else
105
- xml_attributes = " " + xml_attributes.collect do |n, v|
106
- "#{ERB::Util.h(n)}=\"#{ERB::Util.h(v)}\""
107
- end.join(" ")
108
- end
109
- "<#{name}#{xml_attributes}>#{ERB::Util.h(value)}</#{name}>"
100
+ def serialize_attribute_value(xml, name, value, xml_attributes)
101
+ xml.tag!(name, value, xml_attributes)
110
102
  end
111
103
  end
112
104