activeldap 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|