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.
- data/CHANGES +648 -567
- data/README +53 -48
- data/Rakefile +25 -53
- data/TODO +2 -0
- data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
- data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
- data/examples/al-admin/app/controllers/application_controller.rb +1 -1
- data/examples/al-admin/app/views/_entry/_attributes_information.html.erb +7 -1
- data/examples/al-admin/app/views/users/_attributes_update_form.html.erb +13 -1
- data/examples/al-admin/config/environment.rb +2 -3
- data/lib/active_ldap.rb +103 -98
- data/lib/active_ldap/association/belongs_to_many.rb +7 -7
- data/lib/active_ldap/association/has_many.rb +4 -4
- data/lib/active_ldap/associations.rb +29 -5
- data/lib/active_ldap/attributes.rb +5 -1
- data/lib/active_ldap/base.rb +17 -13
- data/lib/active_ldap/configuration.rb +3 -4
- data/lib/active_ldap/connection.rb +3 -3
- data/lib/active_ldap/get_text/parser.rb +4 -2
- data/lib/active_ldap/helper.rb +59 -0
- data/lib/active_ldap/operations.rb +15 -10
- data/lib/active_ldap/xml.rb +22 -30
- data/po/en/active-ldap.po +221 -154
- data/po/ja/active-ldap.po +237 -178
- data/test-unit/History.txt +26 -0
- data/test-unit/Manifest.txt +1 -1
- data/test-unit/README.txt +1 -0
- data/test-unit/Rakefile +6 -1
- data/test-unit/lib/test/unit/autorunner.rb +6 -0
- data/test-unit/lib/test/unit/testcase.rb +101 -36
- data/test-unit/test/{test_testcase.rb → test-testcase.rb} +30 -1
- data/test-unit/test/test_assertions.rb +1 -1
- data/test/al-test-utils.rb +3 -1
- data/test/test_associations.rb +75 -6
- data/test/test_base.rb +45 -3
- metadata +75 -45
- 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
|
-
|
10
|
-
if
|
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[
|
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
|
-
|
25
|
-
if
|
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[
|
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[:
|
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[
|
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(:
|
16
|
+
collect_targets(:primary_key_name)
|
17
17
|
end
|
18
18
|
|
19
19
|
def delete_entries(entries)
|
20
|
-
key =
|
21
|
-
components = @owner[
|
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
|
-
# # :
|
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]
|
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", #
|
96
|
-
# :foreign_key => "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]
|
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
|
-
|
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
|
data/lib/active_ldap/base.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
1398
|
-
|
1399
|
-
|
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
|
-
|
111
|
-
|
112
|
-
|
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
|
-
|
99
|
-
|
100
|
-
|
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.
|
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
|
-
|
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'
|
data/lib/active_ldap/helper.rb
CHANGED
@@ -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
|
-
|
50
|
-
|
51
|
-
|
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(
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
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
|
-
|
516
|
+
options[:connection].delete(targets)
|
512
517
|
end
|
513
518
|
end
|
514
519
|
|
data/lib/active_ldap/xml.rb
CHANGED
@@ -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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
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.
|
86
|
-
xml
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
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
|
|