activeldap 0.9.0 → 0.10.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 +61 -0
- data/README +8 -1
- data/Rakefile +4 -1
- data/benchmark/bench-al.rb +12 -2
- data/examples/al-admin/app/controllers/account_controller.rb +4 -3
- data/examples/al-admin/app/controllers/application.rb +5 -2
- data/examples/al-admin/app/controllers/directory_controller.rb +3 -1
- data/examples/al-admin/app/controllers/users_controller.rb +19 -4
- data/examples/al-admin/app/controllers/welcome_controller.rb +4 -2
- data/examples/al-admin/app/helpers/application_helper.rb +7 -1
- data/examples/al-admin/app/helpers/url_helper.rb +4 -0
- data/examples/al-admin/app/models/ldap_user.rb +4 -0
- data/examples/al-admin/app/views/_entry/{_attributes_information.rhtml → _attributes_information.html.erb} +0 -0
- data/examples/al-admin/app/views/_entry/{_entry.rhtml → _entry.html.erb} +0 -0
- data/examples/al-admin/app/views/_schema/{_aliases.rhtml → _aliases.html.erb} +0 -0
- data/examples/al-admin/app/views/_switcher/{_after.rhtml → _after.html.erb} +0 -0
- data/examples/al-admin/app/views/_switcher/{_before.rhtml → _before.html.erb} +0 -0
- data/examples/al-admin/app/views/account/{login.rhtml → login.html.erb} +0 -0
- data/examples/al-admin/app/views/account/{sign_up.rhtml → sign_up.html.erb} +0 -0
- data/examples/al-admin/app/views/attributes/{_attributes.rhtml → _attributes.html.erb} +0 -0
- data/examples/al-admin/app/views/attributes/{_detail.rhtml → _detail.html.erb} +0 -0
- data/examples/al-admin/app/views/attributes/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/app/views/attributes/{show.rhtml → show.html.erb} +0 -0
- data/examples/al-admin/app/views/directory/{_tree.rhtml → _tree.html.erb} +0 -0
- data/examples/al-admin/app/views/directory/{_tree_view_js.rhtml → _tree_view_js.html.erb} +4 -5
- data/examples/al-admin/app/views/directory/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/app/views/directory/{populate.rhtml → populate.html.erb} +0 -0
- data/examples/al-admin/app/views/layouts/{_footer.rhtml → _footer.html.erb} +0 -0
- data/examples/al-admin/app/views/layouts/{_header_menu.rhtml → _header_menu.html.erb} +0 -0
- data/examples/al-admin/app/views/layouts/{_main_menu.rhtml → _main_menu.html.erb} +0 -0
- data/examples/al-admin/app/views/layouts/{application.rhtml → application.html.erb} +3 -2
- data/examples/al-admin/app/views/object_classes/{_attributes.rhtml → _attributes.html.erb} +0 -0
- data/examples/al-admin/app/views/object_classes/{_object_classes.rhtml → _object_classes.html.erb} +0 -0
- data/examples/al-admin/app/views/object_classes/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/app/views/object_classes/{show.rhtml → show.html.erb} +0 -0
- data/examples/al-admin/app/views/syntaxes/{_detail.rhtml → _detail.html.erb} +0 -0
- data/examples/al-admin/app/views/syntaxes/{_syntaxes.rhtml → _syntaxes.html.erb} +0 -0
- data/examples/al-admin/app/views/syntaxes/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/app/views/syntaxes/{show.rhtml → show.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{_attributes_update_form.rhtml → _attributes_update_form.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{_form.rhtml → _form.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{_object_classes_update_form.rhtml → _object_classes_update_form.html.erb} +7 -1
- data/examples/al-admin/app/views/users/{_password_change_form.rhtml → _password_change_form.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{edit.rhtml → edit.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/app/views/users/{show.rhtml → show.html.erb} +0 -0
- data/examples/al-admin/app/views/welcome/{index.rhtml → index.html.erb} +0 -0
- data/examples/al-admin/config/boot.rb +96 -32
- data/examples/al-admin/config/environment.rb +30 -36
- data/examples/al-admin/config/environments/development.rb +2 -5
- data/examples/al-admin/config/environments/production.rb +1 -0
- data/examples/al-admin/config/environments/test.rb +4 -1
- data/examples/al-admin/config/initializers/exception_notifier.rb +2 -0
- data/examples/al-admin/config/initializers/gettext.rb +1 -0
- data/examples/al-admin/config/initializers/inflections.rb +10 -0
- data/examples/al-admin/config/initializers/mime_types.rb +5 -0
- data/examples/al-admin/config/initializers/ralative_url_support.rb +1 -0
- data/examples/al-admin/config/routes.rb +24 -12
- data/examples/al-admin/lib/authenticated_system.rb +1 -1
- data/examples/al-admin/lib/tasks/gettext.rake +1 -1
- data/examples/al-admin/po/en/al-admin.po +102 -100
- data/examples/al-admin/po/ja/al-admin.po +112 -110
- data/examples/al-admin/po/nl/al-admin.po +117 -110
- data/examples/al-admin/public/javascripts/controls.js +484 -354
- data/examples/al-admin/public/javascripts/dragdrop.js +88 -58
- data/examples/al-admin/public/javascripts/effects.js +396 -364
- data/examples/al-admin/public/javascripts/prototype.js +2817 -1107
- data/examples/al-admin/public/stylesheets/base.css +5 -0
- data/examples/al-admin/script/performance/request +3 -0
- data/lib/active_ldap.rb +13 -10
- data/lib/active_ldap/adapter/base.rb +159 -43
- data/lib/active_ldap/adapter/jndi.rb +175 -0
- data/lib/active_ldap/adapter/jndi_connection.rb +180 -0
- data/lib/active_ldap/adapter/ldap.rb +91 -46
- data/lib/active_ldap/adapter/ldap_ext.rb +19 -5
- data/lib/active_ldap/adapter/net_ldap.rb +52 -44
- data/lib/active_ldap/association/has_many_wrap.rb +1 -1
- data/lib/active_ldap/attributes.rb +20 -95
- data/lib/active_ldap/base.rb +195 -186
- data/lib/active_ldap/callbacks.rb +33 -0
- data/lib/active_ldap/command.rb +3 -3
- data/lib/active_ldap/connection.rb +21 -3
- data/lib/active_ldap/distinguished_name.rb +18 -11
- data/lib/active_ldap/entry_attribute.rb +78 -0
- data/lib/active_ldap/human_readable.rb +20 -0
- data/lib/active_ldap/ldif.rb +860 -10
- data/lib/active_ldap/object_class.rb +6 -4
- data/lib/active_ldap/operations.rb +129 -22
- data/lib/active_ldap/schema.rb +118 -9
- data/lib/active_ldap/schema/syntaxes.rb +33 -16
- data/lib/active_ldap/validations.rb +74 -65
- data/po/en/active-ldap.po +378 -768
- data/po/ja/active-ldap.po +935 -868
- data/rails/plugin/active_ldap/init.rb +40 -2
- data/test/al-test-utils.rb +78 -58
- data/test/command.rb +51 -1
- data/test/test-unit-ext/priority.rb +29 -6
- data/test/test_adapter.rb +21 -2
- data/test/test_attributes.rb +13 -0
- data/test/test_base.rb +51 -1
- data/test/test_connection.rb +2 -1
- data/test/test_connection_per_class.rb +55 -1
- data/test/test_connection_per_dn.rb +29 -1
- data/test/test_find.rb +73 -0
- data/test/test_ldif.rb +1829 -15
- data/test/test_load.rb +126 -0
- data/test/test_object_class.rb +23 -5
- data/test/test_schema.rb +28 -0
- data/test/test_syntax.rb +22 -11
- data/test/test_user.rb +16 -25
- data/test/test_useradd-binary.rb +1 -1
- data/test/test_usermod-binary-add-time.rb +1 -1
- data/test/test_usermod-binary-add.rb +1 -1
- data/test/test_validation.rb +100 -22
- metadata +77 -71
- 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/views/layouts/_flash_box.rhtml +0 -4
- data/examples/al-admin/public/stylesheets/common.css +0 -2
- data/examples/al-admin/script/breakpointer +0 -3
@@ -29,7 +29,11 @@ module ActiveLdap
|
|
29
29
|
}
|
30
30
|
config[:encryption] = {:method => method} if method
|
31
31
|
begin
|
32
|
-
|
32
|
+
uri = construct_uri(host, port, method == :simple_tls)
|
33
|
+
with_start_tls = method == :start_tls
|
34
|
+
info = {:uri => uri, :with_start_tls => with_start_tls}
|
35
|
+
[log("connect", info) {Net::LDAP::Connection.new(config)},
|
36
|
+
uri, with_start_tls]
|
33
37
|
rescue Net::LDAP::LdapError
|
34
38
|
raise ConnectionError, $!.message
|
35
39
|
end
|
@@ -37,7 +41,7 @@ module ActiveLdap
|
|
37
41
|
end
|
38
42
|
|
39
43
|
def unbind(options={})
|
40
|
-
@bound = false
|
44
|
+
log("unbind") {@bound = false}
|
41
45
|
end
|
42
46
|
|
43
47
|
def bind(options={})
|
@@ -52,7 +56,7 @@ module ActiveLdap
|
|
52
56
|
def bind_as_anonymous(options={})
|
53
57
|
super do
|
54
58
|
@bound = false
|
55
|
-
execute(:bind, :method => :anonymous)
|
59
|
+
execute(:bind, {:name => "bind: anonymous"}, {:method => :anonymous})
|
56
60
|
@bound = true
|
57
61
|
end
|
58
62
|
end
|
@@ -70,7 +74,11 @@ module ActiveLdap
|
|
70
74
|
:attributes => attrs,
|
71
75
|
:size => limit,
|
72
76
|
}
|
73
|
-
|
77
|
+
info = {
|
78
|
+
:base => base, :scope => scope_name(scope),
|
79
|
+
:filter => filter, :attributes => attrs,
|
80
|
+
}
|
81
|
+
execute(:search, info, args) do |entry|
|
74
82
|
attributes = {}
|
75
83
|
entry.original_attribute_names.each do |name|
|
76
84
|
attributes[name] = entry[name]
|
@@ -80,31 +88,11 @@ module ActiveLdap
|
|
80
88
|
end
|
81
89
|
end
|
82
90
|
|
83
|
-
def to_ldif(dn, attributes)
|
84
|
-
entry = Net::LDAP::Entry.new(dn.dup)
|
85
|
-
attributes.each do |key, values|
|
86
|
-
entry[key] = values.flatten
|
87
|
-
end
|
88
|
-
entry.to_ldif
|
89
|
-
end
|
90
|
-
|
91
|
-
def load(ldifs, options={})
|
92
|
-
super do |ldif|
|
93
|
-
entry = Net::LDAP::Entry.from_single_ldif_string(ldif)
|
94
|
-
attributes = {}
|
95
|
-
entry.each do |name, values|
|
96
|
-
attributes[name] = values
|
97
|
-
end
|
98
|
-
attributes.delete(:dn)
|
99
|
-
execute(:add,
|
100
|
-
:dn => entry.dn,
|
101
|
-
:attributes => attributes)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
91
|
def delete(targets, options={})
|
106
92
|
super do |target|
|
107
|
-
|
93
|
+
args = {:dn => target}
|
94
|
+
info = args.dup
|
95
|
+
execute(:delete, info, args)
|
108
96
|
end
|
109
97
|
end
|
110
98
|
|
@@ -116,21 +104,38 @@ module ActiveLdap
|
|
116
104
|
attributes[name] = values
|
117
105
|
end
|
118
106
|
end
|
119
|
-
|
107
|
+
args = {:dn => dn, :attributes => attributes}
|
108
|
+
info = args.dup
|
109
|
+
execute(:add, info, args)
|
120
110
|
end
|
121
111
|
end
|
122
112
|
|
123
113
|
def modify(dn, entries, options={})
|
124
114
|
super do |dn, entries|
|
125
|
-
|
115
|
+
info = {:dn => dn, :attributes => entries}
|
116
|
+
execute(:modify, info,
|
126
117
|
:dn => dn,
|
127
118
|
:operations => parse_entries(entries))
|
128
119
|
end
|
129
120
|
end
|
130
121
|
|
122
|
+
def modify_rdn(dn, new_rdn, delete_old_rdn, new_superior, options={})
|
123
|
+
super do |dn, new_rdn, delete_old_rdn, new_superior|
|
124
|
+
info = {
|
125
|
+
:name => "modify: RDN", :dn => dn, :new_rdn => new_rdn,
|
126
|
+
:delete_old_rdn => delete_old_rdn,
|
127
|
+
}
|
128
|
+
execute(:rename, info,
|
129
|
+
:olddn => dn,
|
130
|
+
:newrdn => new_rdn,
|
131
|
+
:delete_attributes => delete_old_rdn)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
131
135
|
private
|
132
|
-
def execute(method, *args, &block)
|
133
|
-
|
136
|
+
def execute(method, info=nil, *args, &block)
|
137
|
+
name = (info || {}).delete(:name) || method
|
138
|
+
result = log(name, info) {@connection.send(method, *args, &block)}
|
134
139
|
message = nil
|
135
140
|
if result.is_a?(Hash)
|
136
141
|
message = result[:errorMessage]
|
@@ -139,16 +144,8 @@ module ActiveLdap
|
|
139
144
|
unless result.zero?
|
140
145
|
klass = LdapError::ERRORS[result]
|
141
146
|
klass ||= LdapError
|
142
|
-
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def root_dse(attrs, options={})
|
148
|
-
search(:base => "",
|
149
|
-
:scope => :base,
|
150
|
-
:attributes => attrs).collect do |dn, attributes|
|
151
|
-
attributes
|
147
|
+
message = [Net::LDAP.result2string(result), message].compact.join(": ")
|
148
|
+
raise klass, message
|
152
149
|
end
|
153
150
|
end
|
154
151
|
|
@@ -177,6 +174,14 @@ module ActiveLdap
|
|
177
174
|
value
|
178
175
|
end
|
179
176
|
|
177
|
+
def scope_name(scope)
|
178
|
+
{
|
179
|
+
Net::LDAP::SearchScope_BaseObject => :base,
|
180
|
+
Net::LDAP::SearchScope_WholeSubtree => :sub,
|
181
|
+
Net::LDAP::SearchScope_SingleLevel => :one,
|
182
|
+
}[scope]
|
183
|
+
end
|
184
|
+
|
180
185
|
def sasl_bind(bind_dn, options={})
|
181
186
|
super do |bind_dn, mechanism, quiet|
|
182
187
|
normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
|
@@ -191,7 +196,10 @@ module ActiveLdap
|
|
191
196
|
:challenge_response => challenge_response,
|
192
197
|
}
|
193
198
|
@bound = false
|
194
|
-
|
199
|
+
info = {
|
200
|
+
:name => "bind: SASL", :dn => bind_dn, :mechanism => mechanism,
|
201
|
+
}
|
202
|
+
execute(:bind, info, args)
|
195
203
|
@bound = true
|
196
204
|
end
|
197
205
|
end
|
@@ -263,7 +271,7 @@ module ActiveLdap
|
|
263
271
|
:password => passwd,
|
264
272
|
}
|
265
273
|
@bound = false
|
266
|
-
execute(:bind, args)
|
274
|
+
execute(:bind, {:dn => bind_dn}, args)
|
267
275
|
@bound = true
|
268
276
|
end
|
269
277
|
end
|
@@ -281,7 +289,7 @@ module ActiveLdap
|
|
281
289
|
|
282
290
|
def ensure_mod_type(type)
|
283
291
|
case type
|
284
|
-
when :replace, :add
|
292
|
+
when :replace, :add, :delete
|
285
293
|
type
|
286
294
|
else
|
287
295
|
raise ArgumentError, _("unknown type: %s") % type
|
@@ -3,8 +3,8 @@ module ActiveLdap
|
|
3
3
|
def self.included(base)
|
4
4
|
base.class_eval do
|
5
5
|
extend(ClassMethods)
|
6
|
-
extend(
|
7
|
-
include(
|
6
|
+
extend(Normalizable)
|
7
|
+
include(Normalizable)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -19,9 +19,20 @@ module ActiveLdap
|
|
19
19
|
result + ancestor.instance_eval {@attr_protected ||= []}
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def blank_value?(value)
|
24
|
+
case value
|
25
|
+
when Hash
|
26
|
+
value.values.all? {|val| blank_value?(val)}
|
27
|
+
when Array
|
28
|
+
value.all? {|val| blank_value?(val)}
|
29
|
+
else
|
30
|
+
value.blank?
|
31
|
+
end
|
32
|
+
end
|
22
33
|
end
|
23
34
|
|
24
|
-
module
|
35
|
+
module Normalizable
|
25
36
|
def normalize_attribute_name(name)
|
26
37
|
name.to_s.downcase
|
27
38
|
end
|
@@ -36,13 +47,7 @@ module ActiveLdap
|
|
36
47
|
end
|
37
48
|
|
38
49
|
name = normalize_attribute_name(name)
|
39
|
-
|
40
|
-
handler = "normalize_attribute_value_of_#{rubyish_class_name}"
|
41
|
-
if respond_to?(handler, true)
|
42
|
-
[name, send(handler, name, value)]
|
43
|
-
else
|
44
|
-
[name, [schema.attribute(name).normalize_value(value)]]
|
45
|
-
end
|
50
|
+
[name, schema.attribute(name).normalize_value(value)]
|
46
51
|
end
|
47
52
|
|
48
53
|
def unnormalize_attributes(attributes)
|
@@ -59,7 +64,7 @@ module ActiveLdap
|
|
59
64
|
else
|
60
65
|
values.each do |value|
|
61
66
|
if value.is_a?(Hash)
|
62
|
-
suffix, real_value =
|
67
|
+
suffix, real_value = unnormalize_attribute_options(value)
|
63
68
|
new_name = name + suffix
|
64
69
|
result[new_name] ||= []
|
65
70
|
result[new_name].concat(real_value)
|
@@ -72,86 +77,6 @@ module ActiveLdap
|
|
72
77
|
result
|
73
78
|
end
|
74
79
|
|
75
|
-
private
|
76
|
-
def normalize_attribute_value_of_array(name, value)
|
77
|
-
attribute = schema.attribute(name)
|
78
|
-
if value.size > 1 and attribute.single_value?
|
79
|
-
format = _("Attribute %s can only have a single value")
|
80
|
-
message = format % self.class.human_attribute_name(attribute)
|
81
|
-
raise TypeError, message
|
82
|
-
end
|
83
|
-
if value.empty?
|
84
|
-
if schema.attribute(name).binary_required?
|
85
|
-
[{'binary' => value}]
|
86
|
-
else
|
87
|
-
value
|
88
|
-
end
|
89
|
-
else
|
90
|
-
value.collect do |entry|
|
91
|
-
normalize_attribute(name, entry)[1][0]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def normalize_attribute_value_of_hash(name, value)
|
97
|
-
if value.keys.size > 1
|
98
|
-
format = _("Hashes must have one key-value pair only: %s")
|
99
|
-
raise TypeError, format % value.inspect
|
100
|
-
end
|
101
|
-
unless value.keys[0].match(/^(lang-[a-z][a-z]*)|(binary)$/)
|
102
|
-
logger.warn do
|
103
|
-
format = _("unknown option did not match lang-* or binary: %s")
|
104
|
-
format % value.keys[0]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
# Contents MUST be a String or an Array
|
108
|
-
if !value.has_key?('binary') and schema.attribute(name).binary_required?
|
109
|
-
suffix, real_value = extract_attribute_options(value)
|
110
|
-
name, values =
|
111
|
-
normalize_attribute_options("#{name}#{suffix};binary", real_value)
|
112
|
-
values
|
113
|
-
else
|
114
|
-
[value]
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def normalize_attribute_value_of_nil_class(name, value)
|
119
|
-
if schema.attribute(name).binary_required?
|
120
|
-
[{'binary' => []}]
|
121
|
-
else
|
122
|
-
[]
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def normalize_attribute_value_of_string(name, value)
|
127
|
-
if schema.attribute(name).binary_required?
|
128
|
-
[{'binary' => [value]}]
|
129
|
-
else
|
130
|
-
[value]
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def normalize_attribute_value_of_date(name, value)
|
135
|
-
new_value = sprintf('%.04d%.02d%.02d%.02d%.02d%.02d%s',
|
136
|
-
value.year, value.month, value.mday, 0, 0, 0,
|
137
|
-
'+0000')
|
138
|
-
normalize_attribute_value_of_string(name, new_value)
|
139
|
-
end
|
140
|
-
|
141
|
-
def normalize_attribute_value_of_time(name, value)
|
142
|
-
new_value = sprintf('%.04d%.02d%.02d%.02d%.02d%.02d%s',
|
143
|
-
0, 0, 0, value.hour, value.min, value.sec,
|
144
|
-
value.zone)
|
145
|
-
normalize_attribute_value_of_string(name, new_value)
|
146
|
-
end
|
147
|
-
|
148
|
-
def normalize_attribute_value_of_date_time(name, value)
|
149
|
-
new_value = sprintf('%.04d%.02d%.02d%.02d%.02d%.02d%s',
|
150
|
-
value.year, value.month, value.mday, value.hour,
|
151
|
-
value.min, value.sec, value.zone)
|
152
|
-
normalize_attribute_value_of_string(name, new_value)
|
153
|
-
end
|
154
|
-
|
155
80
|
# normalize_attribute_options
|
156
81
|
#
|
157
82
|
# Makes the Hashized value from the full attribute name
|
@@ -165,18 +90,18 @@ module ActiveLdap
|
|
165
90
|
[options.reverse.inject(value) {|result, option| {option => result}}]]
|
166
91
|
end
|
167
92
|
|
168
|
-
#
|
93
|
+
# unnormalize_attribute_options
|
169
94
|
#
|
170
|
-
#
|
95
|
+
# Unnormalizes all of the subtypes from a given set of nested hashes
|
171
96
|
# and returns the attribute suffix and the final true value
|
172
|
-
def
|
97
|
+
def unnormalize_attribute_options(value)
|
173
98
|
options = ''
|
174
99
|
ret_val = value
|
175
100
|
if value.class == Hash
|
176
101
|
options = ';' + value.keys[0]
|
177
102
|
ret_val = value[value.keys[0]]
|
178
103
|
if ret_val.class == Hash
|
179
|
-
sub_options, ret_val =
|
104
|
+
sub_options, ret_val = unnormalize_attribute_options(ret_val)
|
180
105
|
options += sub_options
|
181
106
|
end
|
182
107
|
end
|
data/lib/active_ldap/base.rb
CHANGED
@@ -123,16 +123,63 @@ module ActiveLdap
|
|
123
123
|
end
|
124
124
|
|
125
125
|
class LdifInvalid < Error
|
126
|
-
attr_reader :ldif, :reason
|
127
|
-
def initialize(ldif, reason=nil)
|
126
|
+
attr_reader :ldif, :reason, :line, :column, :nearest
|
127
|
+
def initialize(ldif, reason=nil, line=nil, column=nil)
|
128
128
|
@ldif = ldif
|
129
129
|
@reason = reason
|
130
|
+
@line = line
|
131
|
+
@column = column
|
132
|
+
@nearest = nil
|
130
133
|
if @reason
|
131
|
-
message = _("
|
134
|
+
message = _("invalid LDIF: %s:") % @reason
|
132
135
|
else
|
133
|
-
message = _("
|
136
|
+
message = _("invalid LDIF:")
|
134
137
|
end
|
135
|
-
|
138
|
+
if @line and @column
|
139
|
+
@nearest = detect_nearest(@line, @column)
|
140
|
+
snippet = generate_snippet
|
141
|
+
message << "\n#{snippet}\n"
|
142
|
+
end
|
143
|
+
super("#{message}\n#{numbered_ldif}")
|
144
|
+
end
|
145
|
+
|
146
|
+
NEAREST_MARK = "|@|"
|
147
|
+
private
|
148
|
+
def detect_nearest(line, column)
|
149
|
+
nearest = @ldif.to_a[line - 1] || ""
|
150
|
+
if column - 1 == nearest.size # for JRuby 1.0.2 :<
|
151
|
+
nearest << NEAREST_MARK
|
152
|
+
else
|
153
|
+
nearest[column - 1, 0] = NEAREST_MARK
|
154
|
+
end
|
155
|
+
nearest = "#{@ldif.to_a[line - 2]}#{nearest}" if nearest == NEAREST_MARK
|
156
|
+
nearest
|
157
|
+
end
|
158
|
+
|
159
|
+
def generate_snippet
|
160
|
+
nearest = @nearest.chomp
|
161
|
+
column_column = ":#{@column}"
|
162
|
+
target_position_info = "#{@line}#{column_column}: "
|
163
|
+
if /\n/ =~ nearest
|
164
|
+
snippet = "%#{Math.log10(@line).truncate}d" % (@line - 1)
|
165
|
+
snippet << " " * column_column.size
|
166
|
+
snippet << ": "
|
167
|
+
snippet << nearest.gsub(/\n/, "\n#{target_position_info}")
|
168
|
+
else
|
169
|
+
snippet = "#{target_position_info}#{nearest}"
|
170
|
+
end
|
171
|
+
snippet
|
172
|
+
end
|
173
|
+
|
174
|
+
def numbered_ldif
|
175
|
+
return @ldif if @ldif.blank?
|
176
|
+
lines = @ldif.to_a
|
177
|
+
format = "%#{Math.log10(lines.size).truncate + 1}d: %s"
|
178
|
+
i = 0
|
179
|
+
lines.collect do |line|
|
180
|
+
i += 1
|
181
|
+
format % [i, line]
|
182
|
+
end.join
|
136
183
|
end
|
137
184
|
end
|
138
185
|
|
@@ -173,6 +220,15 @@ module ActiveLdap
|
|
173
220
|
end
|
174
221
|
end
|
175
222
|
|
223
|
+
class AttributeValueInvalid < Error
|
224
|
+
attr_reader :attribute, :value
|
225
|
+
def initialize(attribute, value, message)
|
226
|
+
@attribute = attribute
|
227
|
+
@value = value
|
228
|
+
super(message)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
176
232
|
# Base
|
177
233
|
#
|
178
234
|
# Base is the primary class which contains all of the core
|
@@ -190,9 +246,12 @@ module ActiveLdap
|
|
190
246
|
end
|
191
247
|
end
|
192
248
|
|
249
|
+
cattr_accessor :colorize_logging, :instance_writer => false
|
250
|
+
@@colorize_logging = true
|
251
|
+
|
193
252
|
VALID_LDAP_MAPPING_OPTIONS = [:dn_attribute, :prefix, :scope,
|
194
253
|
:classes, :recommended_classes,
|
195
|
-
:sort_by, :order]
|
254
|
+
:excluded_classes, :sort_by, :order]
|
196
255
|
|
197
256
|
cattr_accessor :logger
|
198
257
|
cattr_accessor :configurations
|
@@ -228,6 +287,7 @@ module ActiveLdap
|
|
228
287
|
class_local_attr_accessor false, :prefix, :base
|
229
288
|
class_local_attr_accessor true, :dn_attribute, :scope, :sort_by, :order
|
230
289
|
class_local_attr_accessor true, :required_classes, :recommended_classes
|
290
|
+
class_local_attr_accessor true, :excluded_classes
|
231
291
|
|
232
292
|
class << self
|
233
293
|
# Hide new in Base
|
@@ -297,6 +357,7 @@ module ActiveLdap
|
|
297
357
|
self.scope = options[:scope]
|
298
358
|
self.required_classes = options[:classes]
|
299
359
|
self.recommended_classes = options[:recommended_classes]
|
360
|
+
self.excluded_classes = options[:excluded_classes]
|
300
361
|
self.sort_by = options[:sort_by]
|
301
362
|
self.order = options[:order]
|
302
363
|
|
@@ -323,6 +384,16 @@ module ActiveLdap
|
|
323
384
|
end.join(",")
|
324
385
|
end
|
325
386
|
|
387
|
+
alias_method :base_without_parsed_cache_clear=, :base=
|
388
|
+
def base=(value)
|
389
|
+
self.base_without_parsed_cache_clear = value
|
390
|
+
@parsed_base = nil
|
391
|
+
end
|
392
|
+
|
393
|
+
def parsed_base
|
394
|
+
@parsed_base ||= DN.parse(base)
|
395
|
+
end
|
396
|
+
|
326
397
|
alias_method :scope_without_validation=, :scope=
|
327
398
|
def scope=(scope)
|
328
399
|
validate_scope(scope)
|
@@ -410,6 +481,7 @@ module ActiveLdap
|
|
410
481
|
self.scope = :sub
|
411
482
|
self.required_classes = ['top']
|
412
483
|
self.recommended_classes = []
|
484
|
+
self.excluded_classes = []
|
413
485
|
|
414
486
|
include Enumerable
|
415
487
|
|
@@ -424,25 +496,26 @@ module ActiveLdap
|
|
424
496
|
init_base
|
425
497
|
@new_entry = true
|
426
498
|
initial_classes = required_classes | recommended_classes
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
499
|
+
case attributes
|
500
|
+
when nil
|
501
|
+
self.classes = initial_classes
|
502
|
+
when String, Array, DN
|
503
|
+
self.classes = initial_classes
|
431
504
|
self.dn = attributes
|
432
|
-
|
505
|
+
when Hash
|
433
506
|
classes, attributes = extract_object_class(attributes)
|
434
|
-
|
507
|
+
self.classes = classes | initial_classes
|
435
508
|
normalized_attributes = {}
|
436
509
|
attributes.each do |key, value|
|
437
510
|
real_key = to_real_attribute_name(key) || key
|
438
511
|
normalized_attributes[real_key] = value
|
439
512
|
end
|
440
|
-
self.dn = normalized_attributes
|
513
|
+
self.dn = normalized_attributes.delete(dn_attribute)
|
441
514
|
self.attributes = normalized_attributes
|
442
515
|
else
|
443
|
-
|
444
|
-
|
445
|
-
raise ArgumentError,
|
516
|
+
format = _("'%s' must be either nil, DN value as ActiveLdap::DN, " \
|
517
|
+
"String or Array or attributes as Hash")
|
518
|
+
raise ArgumentError, format % attributes.inspect
|
446
519
|
end
|
447
520
|
yield self if block_given?
|
448
521
|
assert_dn_attribute
|
@@ -471,13 +544,11 @@ module ActiveLdap
|
|
471
544
|
end
|
472
545
|
|
473
546
|
def may
|
474
|
-
|
475
|
-
@may
|
547
|
+
entry_attribute.may
|
476
548
|
end
|
477
549
|
|
478
550
|
def must
|
479
|
-
|
480
|
-
@must
|
551
|
+
entry_attribute.must
|
481
552
|
end
|
482
553
|
|
483
554
|
# attributes
|
@@ -485,15 +556,7 @@ module ActiveLdap
|
|
485
556
|
# Return attribute methods so that a program can determine available
|
486
557
|
# attributes dynamically without schema awareness
|
487
558
|
def attribute_names(normalize=false)
|
488
|
-
|
489
|
-
names = @attribute_names.keys
|
490
|
-
if normalize
|
491
|
-
names.collect do |name|
|
492
|
-
to_real_attribute_name(name)
|
493
|
-
end.uniq
|
494
|
-
else
|
495
|
-
names
|
496
|
-
end
|
559
|
+
entry_attribute.names(normalize)
|
497
560
|
end
|
498
561
|
|
499
562
|
def attribute_present?(name)
|
@@ -520,16 +583,7 @@ module ActiveLdap
|
|
520
583
|
#
|
521
584
|
# Return the authoritative dn
|
522
585
|
def dn
|
523
|
-
|
524
|
-
|
525
|
-
dn_value = id
|
526
|
-
if dn_value.nil?
|
527
|
-
raise DistinguishedNameNotSetError.new,
|
528
|
-
_("%s's DN attribute (%s) isn't set") % [self, dn_attribute]
|
529
|
-
end
|
530
|
-
_base = base
|
531
|
-
_base = nil if _base.empty?
|
532
|
-
["#{dn_attribute}=#{dn_value}", _base].compact.join(",")
|
586
|
+
@dn ||= compute_dn
|
533
587
|
end
|
534
588
|
|
535
589
|
def id
|
@@ -542,6 +596,7 @@ module ActiveLdap
|
|
542
596
|
|
543
597
|
def dn=(value)
|
544
598
|
set_attribute(dn_attribute, value)
|
599
|
+
@dn = nil
|
545
600
|
end
|
546
601
|
alias_method(:id=, :dn=)
|
547
602
|
|
@@ -593,8 +648,6 @@ module ActiveLdap
|
|
593
648
|
# using class_eval instead of using method_missing. This would
|
594
649
|
# give tab completion in irb.
|
595
650
|
def method_missing(name, *args, &block)
|
596
|
-
ensure_apply_object_class
|
597
|
-
|
598
651
|
key = name.to_s
|
599
652
|
case key
|
600
653
|
when /=$/
|
@@ -629,8 +682,7 @@ module ActiveLdap
|
|
629
682
|
|
630
683
|
# Add available attributes to the methods
|
631
684
|
def methods(inherited_too=true)
|
632
|
-
|
633
|
-
target_names = @attribute_names.keys + @attribute_aliases.keys
|
685
|
+
target_names = entry_attribute.all_names
|
634
686
|
target_names -= ['objectClass', Inflector.underscore('objectClass')]
|
635
687
|
super + target_names.uniq.collect do |x|
|
636
688
|
[x, "#{x}=", "#{x}?", "#{x}_before_type_cast"]
|
@@ -639,10 +691,12 @@ module ActiveLdap
|
|
639
691
|
|
640
692
|
alias_method :respond_to_without_attributes?, :respond_to?
|
641
693
|
def respond_to?(name, include_priv=false)
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
694
|
+
return true if super
|
695
|
+
|
696
|
+
name = name.to_s
|
697
|
+
return true if have_attribute?(name)
|
698
|
+
return false if /(?:=|\?|_before_type_cast)$/ !~ name
|
699
|
+
have_attribute?($PREMATCH)
|
646
700
|
end
|
647
701
|
|
648
702
|
# Updates a given attribute and saves immediately
|
@@ -677,7 +731,7 @@ module ActiveLdap
|
|
677
731
|
# Do not let URL/form hackers supply the keys.
|
678
732
|
def attributes=(new_attributes)
|
679
733
|
return if new_attributes.nil?
|
680
|
-
_schema = nil
|
734
|
+
_schema = _local_entry_attribute = nil
|
681
735
|
targets = remove_attributes_protected_from_mass_assignment(new_attributes)
|
682
736
|
targets.each do |key, value|
|
683
737
|
setter = "#{key}="
|
@@ -685,14 +739,15 @@ module ActiveLdap
|
|
685
739
|
_schema ||= schema
|
686
740
|
attribute = _schema.attribute(key)
|
687
741
|
next if attribute.id.nil?
|
688
|
-
|
742
|
+
_local_entry_attribute ||= local_entry_attribute
|
743
|
+
_local_entry_attribute.register(attribute)
|
689
744
|
end
|
690
745
|
send(setter, value)
|
691
746
|
end
|
692
747
|
end
|
693
748
|
|
694
749
|
def to_ldif
|
695
|
-
super(dn,
|
750
|
+
super(dn, @data)
|
696
751
|
end
|
697
752
|
|
698
753
|
def to_xml(options={})
|
@@ -735,7 +790,7 @@ module ActiveLdap
|
|
735
790
|
|
736
791
|
@ldap_data.update(attributes)
|
737
792
|
classes, attributes = extract_object_class(attributes)
|
738
|
-
|
793
|
+
self.classes = classes
|
739
794
|
self.attributes = attributes
|
740
795
|
@new_entry = false
|
741
796
|
self
|
@@ -759,11 +814,9 @@ module ActiveLdap
|
|
759
814
|
end
|
760
815
|
end
|
761
816
|
|
762
|
-
def bind(config_or_password={}, &block)
|
817
|
+
def bind(config_or_password={}, config_or_ignore=nil, &block)
|
763
818
|
if config_or_password.is_a?(String)
|
764
|
-
config = {:password => config_or_password
|
765
|
-
elsif config_or_password.respond_to?(:call)
|
766
|
-
config = {:password_block => config_or_password}
|
819
|
+
config = (config_or_ignore || {}).merge(:password => config_or_password)
|
767
820
|
else
|
768
821
|
config = config_or_password
|
769
822
|
end
|
@@ -776,7 +829,7 @@ module ActiveLdap
|
|
776
829
|
@connection = nil
|
777
830
|
connection.connect
|
778
831
|
@connection = connection
|
779
|
-
|
832
|
+
clear_connection_based_cache
|
780
833
|
clear_association_cache
|
781
834
|
rescue ActiveLdap::Error
|
782
835
|
remove_connection
|
@@ -786,6 +839,17 @@ module ActiveLdap
|
|
786
839
|
true
|
787
840
|
end
|
788
841
|
|
842
|
+
def clear_connection_based_cache
|
843
|
+
@schema = nil
|
844
|
+
@local_entry_attribute = nil
|
845
|
+
clear_object_class_based_cache
|
846
|
+
end
|
847
|
+
|
848
|
+
def clear_object_class_based_cache
|
849
|
+
@entry_attribute = nil
|
850
|
+
@real_names = {}
|
851
|
+
end
|
852
|
+
|
789
853
|
def schema
|
790
854
|
@schema ||= super
|
791
855
|
end
|
@@ -797,6 +861,7 @@ module ActiveLdap
|
|
797
861
|
|
798
862
|
undef_method :base=
|
799
863
|
def base=(object_local_base)
|
864
|
+
@dn = nil
|
800
865
|
@base = object_local_base
|
801
866
|
end
|
802
867
|
|
@@ -824,42 +889,50 @@ module ActiveLdap
|
|
824
889
|
end
|
825
890
|
|
826
891
|
private
|
892
|
+
def attribute_name_resolvable_without_connection?
|
893
|
+
@entry_attribute and @local_entry_attribute
|
894
|
+
end
|
895
|
+
|
896
|
+
def entry_attribute
|
897
|
+
@entry_attribute ||= connection.entry_attribute(@data["objectClass"] || [])
|
898
|
+
end
|
899
|
+
|
900
|
+
def local_entry_attribute
|
901
|
+
@local_entry_attribute ||= connection.entry_attribute([])
|
902
|
+
end
|
903
|
+
|
827
904
|
def abbreviate_instance_variables
|
828
905
|
@abbreviating ||= nil
|
829
906
|
connection, @connection = @connection, nil
|
830
907
|
schema, @schema = @schema, nil
|
831
|
-
|
832
|
-
|
833
|
-
|
908
|
+
entry_attribute, @entry_attribute = @entry_attribute, nil
|
909
|
+
local_entry_attribute, @local_entry_attribute = @local_entry_attribute, nil
|
910
|
+
real_names, @real_names = @real_names, nil
|
834
911
|
unless @abbreviating
|
835
912
|
@abbreviating = true
|
836
|
-
@must, @may = @must.collect(&:name), @may.collect(&:name)
|
837
|
-
@object_classes = @object_classes.collect(&:name)
|
838
913
|
end
|
839
914
|
yield
|
840
915
|
ensure
|
841
916
|
@connection = connection
|
842
917
|
@schema = schema
|
843
|
-
@
|
844
|
-
@
|
845
|
-
@
|
846
|
-
@object_classes = object_classes
|
918
|
+
@entry_attribute = entry_attribute
|
919
|
+
@local_entry_attribute = local_entry_attribute
|
920
|
+
@real_names = real_names
|
847
921
|
@abbreviating = false
|
848
922
|
end
|
849
923
|
|
850
924
|
def extract_object_class(attributes)
|
851
925
|
classes = []
|
852
|
-
attrs =
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
classes
|
857
|
-
true
|
926
|
+
attrs = {}
|
927
|
+
attributes.each do |key, value|
|
928
|
+
key = key.to_s
|
929
|
+
if /\Aobject_?class\z/i =~ key
|
930
|
+
classes.concat(value.to_a)
|
858
931
|
else
|
859
|
-
|
932
|
+
attrs[key] = value
|
860
933
|
end
|
861
934
|
end
|
862
|
-
[classes,
|
935
|
+
[classes, attributes]
|
863
936
|
end
|
864
937
|
|
865
938
|
def init_base
|
@@ -868,11 +941,12 @@ module ActiveLdap
|
|
868
941
|
|
869
942
|
def initialize_by_ldap_data(dn, attributes)
|
870
943
|
init_base
|
944
|
+
@dn = dn
|
871
945
|
@new_entry = false
|
872
946
|
@dn_is_base = false
|
873
947
|
@ldap_data = attributes
|
874
948
|
classes, attributes = extract_object_class(attributes)
|
875
|
-
|
949
|
+
self.classes = classes
|
876
950
|
self.dn = dn
|
877
951
|
self.attributes = attributes
|
878
952
|
yield self if block_given?
|
@@ -893,32 +967,22 @@ module ActiveLdap
|
|
893
967
|
|
894
968
|
def to_real_attribute_name(name, allow_normalized_name=false)
|
895
969
|
return name if name.nil?
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
real_name ||= @attribute_aliases[Inflector.underscore(name)]
|
900
|
-
if real_name
|
901
|
-
real_name
|
902
|
-
elsif allow_normalized_name
|
903
|
-
@normalized_attribute_names[normalize_attribute_name(name)]
|
970
|
+
if allow_normalized_name
|
971
|
+
entry_attribute.normalize(name, allow_normalized_name) ||
|
972
|
+
local_entry_attribute.normalize(name, allow_normalized_name)
|
904
973
|
else
|
905
|
-
|
974
|
+
@real_names[name] ||=
|
975
|
+
entry_attribute.normalize(name, false) ||
|
976
|
+
local_entry_attribute.normalize(name, false)
|
906
977
|
end
|
907
978
|
end
|
908
979
|
|
909
|
-
def ensure_apply_object_class
|
910
|
-
current_object_class = @data['objectClass']
|
911
|
-
return if current_object_class.nil? or current_object_class == @last_oc
|
912
|
-
apply_object_class(current_object_class)
|
913
|
-
end
|
914
|
-
|
915
980
|
# enforce_type
|
916
981
|
#
|
917
982
|
# enforce_type applies your changes without attempting to write to LDAP.
|
918
983
|
# This means that if you set userCertificate to somebinary value, it will
|
919
984
|
# wrap it up correctly.
|
920
985
|
def enforce_type(key, value)
|
921
|
-
ensure_apply_object_class
|
922
986
|
# Enforce attribute value formatting
|
923
987
|
normalize_attribute(key, value)[1]
|
924
988
|
end
|
@@ -927,60 +991,12 @@ module ActiveLdap
|
|
927
991
|
@mutex = Mutex.new
|
928
992
|
@data = {} # where the r/w entry data is stored
|
929
993
|
@ldap_data = {} # original ldap entry data
|
930
|
-
@attribute_schemata = {}
|
931
|
-
@attribute_names = {} # list of valid method calls for attributes used
|
932
|
-
# for dereferencing
|
933
|
-
@normalized_attribute_names = {} # list of normalized attribute name
|
934
|
-
@attribute_aliases = {} # aliases of @attribute_names
|
935
|
-
@last_oc = false # for use in other methods for "caching"
|
936
994
|
@dn_attribute = nil
|
937
995
|
@base = nil
|
938
996
|
@scope = nil
|
997
|
+
@dn = nil
|
939
998
|
@connection ||= nil
|
940
|
-
|
941
|
-
|
942
|
-
# apply_object_class
|
943
|
-
#
|
944
|
-
# objectClass= special case for updating appropriately
|
945
|
-
# This updates the objectClass entry in @data. It also
|
946
|
-
# updating all required and allowed attributes while
|
947
|
-
# removing defined attributes that are no longer valid
|
948
|
-
# given the new objectclasses.
|
949
|
-
def apply_object_class(val)
|
950
|
-
new_oc = val
|
951
|
-
new_oc = [val] if new_oc.class != Array
|
952
|
-
new_oc = new_oc.uniq
|
953
|
-
return new_oc if @last_oc == new_oc
|
954
|
-
|
955
|
-
# Store for caching purposes
|
956
|
-
@last_oc = new_oc.dup
|
957
|
-
|
958
|
-
# Set the actual objectClass data
|
959
|
-
define_attribute_methods(schema.attribute('objectClass'))
|
960
|
-
replace_class(*new_oc)
|
961
|
-
|
962
|
-
# Build |data| from schema
|
963
|
-
# clear attribute name mapping first
|
964
|
-
@attribute_schemata = {}
|
965
|
-
@attribute_names = {}
|
966
|
-
@normalized_attribute_names = {}
|
967
|
-
@attribute_aliases = {}
|
968
|
-
@must = []
|
969
|
-
@may = []
|
970
|
-
@object_classes = []
|
971
|
-
new_oc.each do |objc|
|
972
|
-
# get all attributes for the class
|
973
|
-
object_class = schema.object_class(objc)
|
974
|
-
@object_classes << object_class
|
975
|
-
@must.concat(object_class.must)
|
976
|
-
@may.concat(object_class.may)
|
977
|
-
end
|
978
|
-
@must.uniq!
|
979
|
-
@may.uniq!
|
980
|
-
(@must + @may).each do |attr|
|
981
|
-
# Update attr_method with appropriate
|
982
|
-
define_attribute_methods(attr)
|
983
|
-
end
|
999
|
+
clear_connection_based_cache
|
984
1000
|
end
|
985
1001
|
|
986
1002
|
# get_attribute
|
@@ -999,7 +1015,11 @@ module ActiveLdap
|
|
999
1015
|
value.each do |option, val|
|
1000
1016
|
result[option] = type_cast(attribute, val)
|
1001
1017
|
end
|
1002
|
-
result
|
1018
|
+
if result.size == 1 and result.has_key?("binary")
|
1019
|
+
result["binary"]
|
1020
|
+
else
|
1021
|
+
result
|
1022
|
+
end
|
1003
1023
|
when Array
|
1004
1024
|
value.collect do |val|
|
1005
1025
|
type_cast(attribute, val)
|
@@ -1013,11 +1033,7 @@ module ActiveLdap
|
|
1013
1033
|
name = to_real_attribute_name(name)
|
1014
1034
|
|
1015
1035
|
value = @data[name] || []
|
1016
|
-
|
1017
|
-
[name, value.dup]
|
1018
|
-
else
|
1019
|
-
[name, array_of(value.dup, false)]
|
1020
|
-
end
|
1036
|
+
[name, array_of(value, force_array)]
|
1021
1037
|
end
|
1022
1038
|
|
1023
1039
|
def get_attribute_as_query(name, force_array=false)
|
@@ -1042,35 +1058,25 @@ module ActiveLdap
|
|
1042
1058
|
attr, value = update_dn(attr, value) if attr == dn_attribute
|
1043
1059
|
raise UnknownAttribute.new(name) if attr.nil?
|
1044
1060
|
|
1045
|
-
|
1046
|
-
when nil, ""
|
1047
|
-
value = []
|
1048
|
-
when Array
|
1049
|
-
value = value.collect {|c| c.blank? ? [] : c}.flatten
|
1050
|
-
when String
|
1051
|
-
value = [value]
|
1052
|
-
when Numeric
|
1053
|
-
value = [value.to_s]
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
@data[attr] = enforce_type(attr, value)
|
1061
|
+
@data[attr] = value
|
1057
1062
|
end
|
1058
1063
|
|
1059
1064
|
def update_dn(attr, value)
|
1065
|
+
@dn = nil
|
1060
1066
|
@dn_is_base = false
|
1061
|
-
return [attr,
|
1067
|
+
return [attr, nil] if value.blank?
|
1062
1068
|
|
1063
|
-
new_dn_attribute, new_value,
|
1069
|
+
new_dn_attribute, new_value, bases = split_dn_value(value)
|
1064
1070
|
if new_dn_attribute.nil? and new_value.nil?
|
1065
1071
|
@dn_is_base = true
|
1066
1072
|
@base = nil
|
1067
|
-
attr, value =
|
1073
|
+
attr, value = bases[0].to_a[0]
|
1068
1074
|
@dn_attribute = attr
|
1069
1075
|
else
|
1070
1076
|
new_dn_attribute = to_real_attribute_name(new_dn_attribute)
|
1071
1077
|
if new_dn_attribute
|
1072
1078
|
value = new_value
|
1073
|
-
@base =
|
1079
|
+
@base = bases.empty? ? nil : DN.new(*bases).to_s
|
1074
1080
|
if dn_attribute != new_dn_attribute
|
1075
1081
|
@dn_attribute = attr = new_dn_attribute
|
1076
1082
|
end
|
@@ -1082,13 +1088,14 @@ module ActiveLdap
|
|
1082
1088
|
def split_dn_value(value)
|
1083
1089
|
dn_value = relative_dn_value = nil
|
1084
1090
|
begin
|
1085
|
-
dn_value =
|
1091
|
+
dn_value = value if value.is_a?(DN)
|
1092
|
+
dn_value ||= DN.parse(value)
|
1086
1093
|
rescue DistinguishedNameInvalid
|
1087
1094
|
dn_value = DN.parse("#{dn_attribute}=#{value}")
|
1088
1095
|
end
|
1089
1096
|
|
1090
1097
|
begin
|
1091
|
-
relative_dn_value = dn_value -
|
1098
|
+
relative_dn_value = dn_value - self.class.parsed_base
|
1092
1099
|
if relative_dn_value.rdns.empty?
|
1093
1100
|
val = []
|
1094
1101
|
bases = dn_value.rdns
|
@@ -1100,23 +1107,25 @@ module ActiveLdap
|
|
1100
1107
|
end
|
1101
1108
|
|
1102
1109
|
dn_attribute_name, dn_attribute_value = val.to_a[0]
|
1103
|
-
[dn_attribute_name, dn_attribute_value,
|
1104
|
-
bases.empty? ? nil : DN.new(*bases).to_s]
|
1110
|
+
[dn_attribute_name, dn_attribute_value, bases]
|
1105
1111
|
end
|
1106
1112
|
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
@attribute_schemata[real_name] = attribute
|
1115
|
-
([real_name] + attribute.aliases).each do |name|
|
1116
|
-
@attribute_names[name] = real_name
|
1117
|
-
@attribute_aliases[Inflector.underscore(name)] = real_name
|
1118
|
-
@normalized_attribute_names[normalize_attribute_name(name)] = real_name
|
1113
|
+
def compute_dn(escape_dn_value=false)
|
1114
|
+
return base if @dn_is_base
|
1115
|
+
|
1116
|
+
dn_value = id
|
1117
|
+
if dn_value.nil?
|
1118
|
+
raise DistinguishedNameNotSetError.new,
|
1119
|
+
_("%s's DN attribute (%s) isn't set") % [self, dn_attribute]
|
1119
1120
|
end
|
1121
|
+
dn_value = DN.escape_value(dn_value) if escape_dn_value
|
1122
|
+
_base = base
|
1123
|
+
_base = nil if _base.empty?
|
1124
|
+
["#{dn_attribute}=#{dn_value}", _base].compact.join(",")
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def escaped_dn
|
1128
|
+
compute_dn(true)
|
1120
1129
|
end
|
1121
1130
|
|
1122
1131
|
# array_of
|
@@ -1127,7 +1136,7 @@ module ActiveLdap
|
|
1127
1136
|
case value
|
1128
1137
|
when Array
|
1129
1138
|
if to_a or value.size > 1
|
1130
|
-
value.collect {|v| array_of(v,
|
1139
|
+
value.collect {|v| array_of(v, false)}.compact
|
1131
1140
|
else
|
1132
1141
|
if value.empty?
|
1133
1142
|
nil
|
@@ -1144,7 +1153,7 @@ module ActiveLdap
|
|
1144
1153
|
result
|
1145
1154
|
end
|
1146
1155
|
else
|
1147
|
-
to_a ? [value
|
1156
|
+
to_a ? [value] : value
|
1148
1157
|
end
|
1149
1158
|
end
|
1150
1159
|
|
@@ -1158,7 +1167,7 @@ module ActiveLdap
|
|
1158
1167
|
real_name ||= key
|
1159
1168
|
next if _schema.attribute(real_name).id.nil?
|
1160
1169
|
result[real_name] ||= []
|
1161
|
-
result[real_name].concat(values)
|
1170
|
+
result[real_name].concat(enforce_type(real_name, values))
|
1162
1171
|
end
|
1163
1172
|
result
|
1164
1173
|
end
|
@@ -1205,14 +1214,14 @@ module ActiveLdap
|
|
1205
1214
|
dn_value = data[dn_attr]
|
1206
1215
|
|
1207
1216
|
attributes = []
|
1208
|
-
attributes.push([
|
1217
|
+
attributes.push([dn_attr, dn_value])
|
1209
1218
|
|
1210
1219
|
oc_value = data['objectClass']
|
1211
|
-
attributes.push([
|
1220
|
+
attributes.push(['objectClass', oc_value])
|
1212
1221
|
data.each do |key, value|
|
1213
1222
|
next if value.empty? or key == 'objectClass' or key == dn_attr
|
1214
1223
|
|
1215
|
-
attributes.push([
|
1224
|
+
attributes.push([key, value])
|
1216
1225
|
end
|
1217
1226
|
|
1218
1227
|
attributes
|
@@ -1256,7 +1265,7 @@ module ActiveLdap
|
|
1256
1265
|
def create
|
1257
1266
|
prepare_data_for_saving do |data, ldap_data|
|
1258
1267
|
attributes = collect_all_attributes(data)
|
1259
|
-
add_entry(
|
1268
|
+
add_entry(escaped_dn, attributes)
|
1260
1269
|
@new_entry = false
|
1261
1270
|
true
|
1262
1271
|
end
|
@@ -1265,7 +1274,7 @@ module ActiveLdap
|
|
1265
1274
|
def update
|
1266
1275
|
prepare_data_for_saving do |data, ldap_data|
|
1267
1276
|
attributes = collect_modified_attributes(ldap_data, data)
|
1268
|
-
modify_entry(
|
1277
|
+
modify_entry(escaped_dn, attributes)
|
1269
1278
|
true
|
1270
1279
|
end
|
1271
1280
|
end
|