activeldap 5.2.4 → 6.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.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/doc/text/development.md +26 -0
- data/doc/text/{news.textile → news.md} +367 -271
- data/doc/text/{rails.textile → rails.md} +44 -33
- data/doc/text/{tutorial.textile → tutorial.md} +177 -185
- data/lib/active_ldap/adapter/base.rb +30 -10
- data/lib/active_ldap/adapter/jndi.rb +21 -9
- data/lib/active_ldap/adapter/jndi_connection.rb +83 -20
- data/lib/active_ldap/adapter/ldap.rb +13 -22
- data/lib/active_ldap/adapter/ldap_ext.rb +32 -13
- data/lib/active_ldap/adapter/net_ldap.rb +9 -18
- data/lib/active_ldap/base.rb +11 -1
- data/lib/active_ldap/configuration.rb +24 -1
- data/lib/active_ldap/connection.rb +2 -2
- data/lib/active_ldap/human_readable.rb +5 -4
- data/lib/active_ldap/operations.rb +21 -4
- data/lib/active_ldap/persistence.rb +3 -2
- data/lib/active_ldap/validations.rb +12 -4
- data/lib/active_ldap/version.rb +1 -1
- data/lib/active_ldap.rb +0 -1
- data/test/add-phonetic-attribute-options-to-slapd.ldif +1 -1
- data/test/al-test-utils.rb +125 -38
- data/test/enable-dynamic-groups.ldif +22 -0
- data/test/enable-start-tls.ldif +1 -1
- data/test/run-test.rb +0 -4
- data/test/test_base.rb +76 -18
- data/test/test_base_per_instance.rb +33 -1
- data/test/test_connection.rb +4 -0
- data/test/test_entry.rb +1 -0
- data/test/test_find.rb +12 -2
- data/test/test_supported_control.rb +1 -1
- data/test/test_validation.rb +28 -15
- metadata +16 -30
- data/README.textile +0 -141
- data/doc/text/development.textile +0 -54
@@ -30,6 +30,8 @@ module ActiveLdap
|
|
30
30
|
:scope,
|
31
31
|
:sasl_options,
|
32
32
|
:follow_referrals,
|
33
|
+
:use_paged_results,
|
34
|
+
:page_size,
|
33
35
|
]
|
34
36
|
|
35
37
|
@@row_even = true
|
@@ -41,6 +43,7 @@ module ActiveLdap
|
|
41
43
|
@bind_tried = false
|
42
44
|
@entry_attributes = {}
|
43
45
|
@follow_referrals = nil
|
46
|
+
@page_size = nil
|
44
47
|
@configuration = configuration.dup
|
45
48
|
@logger = @configuration.delete(:logger)
|
46
49
|
@configuration.assert_valid_keys(VALID_ADAPTER_CONFIGURATION_KEYS)
|
@@ -48,6 +51,7 @@ module ActiveLdap
|
|
48
51
|
instance_variable_set("@#{name}", configuration[name])
|
49
52
|
end
|
50
53
|
@follow_referrals = true if @follow_referrals.nil?
|
54
|
+
@page_size ||= Configuration::DEFAULT_CONFIG[:page_size]
|
51
55
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
52
56
|
end
|
53
57
|
|
@@ -169,23 +173,40 @@ module ActiveLdap
|
|
169
173
|
end
|
170
174
|
|
171
175
|
def search(options={})
|
172
|
-
filter = parse_filter(options[:filter]) || 'objectClass=*'
|
173
|
-
attrs = options[:attributes] || []
|
174
|
-
scope = ensure_scope(options[:scope] || @scope)
|
175
176
|
base = options[:base]
|
177
|
+
base = ensure_dn_string(base)
|
178
|
+
attributes = options[:attributes] || []
|
179
|
+
attributes = attributes.to_a # just in case
|
176
180
|
limit = options[:limit] || 0
|
177
181
|
limit = nil if limit <= 0
|
182
|
+
use_paged_results = options[:use_paged_results]
|
183
|
+
use_paged_results = @use_paged_results if use_paged_results.nil?
|
184
|
+
if use_paged_results
|
185
|
+
use_paged_results = limit != 1 && supported_control.paged_results?
|
186
|
+
end
|
187
|
+
search_options = {
|
188
|
+
base: base,
|
189
|
+
scope: ensure_scope(options[:scope] || @scope),
|
190
|
+
filter: parse_filter(options[:filter]) || 'objectClass=*',
|
191
|
+
attributes: attributes,
|
192
|
+
limit: limit,
|
193
|
+
use_paged_results: use_paged_results,
|
194
|
+
page_size: options[:page_size] || @page_size,
|
195
|
+
}
|
178
196
|
|
179
|
-
attrs = attrs.to_a # just in case
|
180
|
-
base = ensure_dn_string(base)
|
181
197
|
begin
|
182
198
|
operation(options) do
|
183
|
-
yield(
|
199
|
+
yield(search_options)
|
184
200
|
end
|
185
|
-
rescue LdapError::NoSuchObject, LdapError::InvalidDnSyntax
|
201
|
+
rescue LdapError::NoSuchObject, LdapError::InvalidDnSyntax => error
|
186
202
|
# Do nothing on failure
|
187
203
|
@logger.info do
|
188
|
-
args = [
|
204
|
+
args = [
|
205
|
+
error.class.class,
|
206
|
+
error.message,
|
207
|
+
search_options[:filter],
|
208
|
+
search_options[:attributes].inspect,
|
209
|
+
]
|
189
210
|
_("Ignore error %s(%s): filter %s: attributes: %s") % args
|
190
211
|
end
|
191
212
|
end
|
@@ -662,8 +683,7 @@ module ActiveLdap
|
|
662
683
|
:scope => :base,
|
663
684
|
:attributes => attrs,
|
664
685
|
:limit => 1,
|
665
|
-
:try_reconnect => try_reconnect,
|
666
|
-
:use_paged_results => false) do |dn, attributes|
|
686
|
+
:try_reconnect => try_reconnect) do |dn, attributes|
|
667
687
|
found_attributes = attributes
|
668
688
|
end
|
669
689
|
found_attributes
|
@@ -22,9 +22,23 @@ module ActiveLdap
|
|
22
22
|
super do |host, port, method|
|
23
23
|
uri = construct_uri(host, port, method == :ssl)
|
24
24
|
with_start_tls = method == :start_tls
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
follow_referrals = follow_referrals?(options)
|
26
|
+
info = {
|
27
|
+
:uri => uri,
|
28
|
+
:with_start_tls => with_start_tls,
|
29
|
+
:follow_referrals => follow_referrals,
|
30
|
+
}
|
31
|
+
[
|
32
|
+
log("connect", info) {
|
33
|
+
JndiConnection.new(host,
|
34
|
+
port,
|
35
|
+
method,
|
36
|
+
@timeout,
|
37
|
+
follow_referrals)
|
38
|
+
},
|
39
|
+
uri,
|
40
|
+
with_start_tls,
|
41
|
+
]
|
28
42
|
end
|
29
43
|
end
|
30
44
|
|
@@ -46,12 +60,10 @@ module ActiveLdap
|
|
46
60
|
end
|
47
61
|
|
48
62
|
def search(options={}, &block)
|
49
|
-
super(options) do |
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
}
|
54
|
-
execute(:search, info, base, scope, filter, attrs, limit, &block)
|
63
|
+
super(options) do |search_options|
|
64
|
+
scope = search_options[:scope]
|
65
|
+
info = search_options.merge(scope: scope_name(scope))
|
66
|
+
execute(:search, info, search_options, &block)
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
@@ -25,6 +25,8 @@ module ActiveLdap
|
|
25
25
|
Context = naming.Context
|
26
26
|
StartTlsRequest = ldap.StartTlsRequest
|
27
27
|
Control = ldap.Control
|
28
|
+
PagedResultsControl = ldap.PagedResultsControl
|
29
|
+
PagedResultsResponseControl = ldap.PagedResultsResponseControl
|
28
30
|
|
29
31
|
CommunicationException = naming.CommunicationException
|
30
32
|
ServiceUnavailableException = naming.ServiceUnavailableException
|
@@ -73,13 +75,14 @@ module ActiveLdap
|
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
76
|
-
def initialize(host, port, method, timeout)
|
78
|
+
def initialize(host, port, method, timeout, follow_referrals)
|
77
79
|
@host = host
|
78
80
|
@port = port
|
79
81
|
@method = method
|
80
82
|
@timeout = timeout
|
81
83
|
@context = nil
|
82
84
|
@tls = nil
|
85
|
+
@follow_referrals = follow_referrals
|
83
86
|
end
|
84
87
|
|
85
88
|
def unbind
|
@@ -108,23 +111,55 @@ module ActiveLdap
|
|
108
111
|
bound?
|
109
112
|
end
|
110
113
|
|
111
|
-
def search(
|
114
|
+
def search(options)
|
115
|
+
base = options[:base]
|
116
|
+
scope = options[:scope]
|
117
|
+
filter = options[:filter]
|
118
|
+
attributes = options[:attributes]
|
119
|
+
limit = options[:limit]
|
120
|
+
use_paged_results = options[:use_paged_results]
|
121
|
+
page_size = options[:page_size]
|
122
|
+
|
112
123
|
controls = SearchControls.new
|
113
124
|
controls.search_scope = scope
|
114
125
|
|
115
126
|
controls.count_limit = limit if limit
|
116
|
-
unless
|
117
|
-
controls.returning_attributes =
|
127
|
+
unless attributes.blank?
|
128
|
+
controls.returning_attributes = attributes.to_java(:string)
|
129
|
+
end
|
130
|
+
|
131
|
+
page_cookie = nil
|
132
|
+
if use_paged_results
|
133
|
+
# https://devdocs.io/openjdk~8/javax/naming/ldap/pagedresultscontrol
|
134
|
+
@context.set_request_controls([build_paged_results_control(page_size)])
|
135
|
+
else
|
136
|
+
@context.set_request_controls([])
|
118
137
|
end
|
119
138
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
139
|
+
escaped_base = escape_dn(base)
|
140
|
+
|
141
|
+
loop do
|
142
|
+
@context.search(escaped_base, filter, controls).each do |search_result|
|
143
|
+
yield(build_raw_search_result(search_result))
|
126
144
|
end
|
127
|
-
|
145
|
+
|
146
|
+
break unless use_paged_results
|
147
|
+
|
148
|
+
# Find the paged search cookie
|
149
|
+
response_controls = @context.get_response_controls
|
150
|
+
break unless response_controls
|
151
|
+
response_controls.each do |response_control|
|
152
|
+
next unless response_control.is_a?(PagedResultsResponseControl)
|
153
|
+
page_cookie = response_control.get_cookie
|
154
|
+
break
|
155
|
+
end
|
156
|
+
|
157
|
+
break unless page_cookie
|
158
|
+
|
159
|
+
# Set paged results control so we can keep getting results.
|
160
|
+
paged_results_control =
|
161
|
+
build_paged_results_control(page_size, page_cookie)
|
162
|
+
@context.set_request_controls([paged_results_control])
|
128
163
|
end
|
129
164
|
end
|
130
165
|
|
@@ -133,25 +168,32 @@ module ActiveLdap
|
|
133
168
|
records.each do |record|
|
134
169
|
attributes.put(record.to_java_attribute)
|
135
170
|
end
|
136
|
-
@context.
|
171
|
+
@context.set_request_controls([])
|
172
|
+
@context.create_subcontext(escape_dn(dn), attributes)
|
137
173
|
end
|
138
174
|
|
139
175
|
def modify(dn, records)
|
140
176
|
items = records.collect(&:to_java_modification_item)
|
141
|
-
@context.
|
177
|
+
@context.set_request_controls([])
|
178
|
+
@context.modify_attributes(escape_dn(dn), items.to_java(ModificationItem))
|
142
179
|
end
|
143
180
|
|
144
181
|
def modify_rdn(dn, new_rdn, delete_old_rdn)
|
145
182
|
# should use mutex
|
146
183
|
delete_rdn_key = "java.naming.ldap.deleteRDN"
|
147
|
-
@context.
|
148
|
-
|
149
|
-
|
150
|
-
|
184
|
+
@context.set_request_controls([])
|
185
|
+
begin
|
186
|
+
@context.add_to_environment(delete_rdn_key, delete_old_rdn.to_s)
|
187
|
+
@context.rename(escape_dn(dn), escape_dn(new_rdn))
|
188
|
+
ensure
|
189
|
+
@context.remove_from_environment(delete_rdn_key)
|
190
|
+
end
|
151
191
|
end
|
152
192
|
|
153
193
|
def delete(dn)
|
154
|
-
|
194
|
+
escaped_dn = escape_dn(dn)
|
195
|
+
@context.set_request_controls([])
|
196
|
+
@context.destroy_subcontext(escaped_dn)
|
155
197
|
end
|
156
198
|
|
157
199
|
private
|
@@ -162,9 +204,10 @@ module ActiveLdap
|
|
162
204
|
Context::PROVIDER_URL => ldap_uri,
|
163
205
|
'com.sun.jndi.ldap.connect.timeout' => (@timeout * 1000).to_i.to_s,
|
164
206
|
'com.sun.jndi.ldap.read.timeout' => (@timeout * 1000).to_i.to_s,
|
207
|
+
'java.naming.ldap.derefAliases' => 'never',
|
208
|
+
'java.naming.referral' => @follow_referrals ? 'follow' : 'ignore',
|
165
209
|
}
|
166
|
-
|
167
|
-
context = InitialLdapContext.new(environment, nil)
|
210
|
+
context = InitialLdapContext.new(HashTable.new(environment), nil)
|
168
211
|
if @method == :start_tls
|
169
212
|
@tls = context.extended_operation(StartTlsRequest.new)
|
170
213
|
@tls.negotiate
|
@@ -185,6 +228,26 @@ module ActiveLdap
|
|
185
228
|
protocol = @method == :ssl ? "ldaps" : "ldap"
|
186
229
|
"#{protocol}://#{@host}:#{@port}/"
|
187
230
|
end
|
231
|
+
|
232
|
+
def escape_dn(dn)
|
233
|
+
javax.naming.ldap.LdapName.new(dn)
|
234
|
+
rescue Java::JavaLang::IllegalArgumentException, Java::JavaxNaming::InvalidNameException
|
235
|
+
dn
|
236
|
+
end
|
237
|
+
|
238
|
+
def build_paged_results_control(page_size, page_cookie=nil)
|
239
|
+
PagedResultsControl.new(page_size, page_cookie, Control::CRITICAL)
|
240
|
+
end
|
241
|
+
|
242
|
+
def build_raw_search_result(search_result)
|
243
|
+
attributes = {}
|
244
|
+
search_result.attributes.get_all.each do |attribute|
|
245
|
+
attributes[attribute.get_id] = attribute.get_all.collect do |value|
|
246
|
+
value.is_a?(String) ? value : String.from_java_bytes(value)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
[search_result.name_in_namespace, attributes]
|
250
|
+
end
|
188
251
|
end
|
189
252
|
end
|
190
253
|
end
|
@@ -113,25 +113,11 @@ module ActiveLdap
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def search(options={})
|
116
|
-
super(options) do |
|
116
|
+
super(options) do |search_options|
|
117
117
|
begin
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
info = {
|
123
|
-
:base => base, :scope => scope_name(scope),
|
124
|
-
:filter => filter, :attributes => attrs, :limit => limit,
|
125
|
-
}
|
126
|
-
options = {
|
127
|
-
:base => base,
|
128
|
-
:scope => scope,
|
129
|
-
:filter => filter,
|
130
|
-
:attributes => attrs,
|
131
|
-
:limit => limit,
|
132
|
-
:use_paged_results => use_paged_results
|
133
|
-
}
|
134
|
-
execute(:search_full, info, options) do |entry|
|
118
|
+
scope = search_options[:scope]
|
119
|
+
info = search_options.merge(scope: scope_name(scope))
|
120
|
+
execute(:search_full, info, search_options) do |entry|
|
135
121
|
attributes = {}
|
136
122
|
entry.attrs.each do |attr|
|
137
123
|
value = entry.vals(attr)
|
@@ -142,7 +128,10 @@ module ActiveLdap
|
|
142
128
|
rescue RuntimeError
|
143
129
|
if $!.message == "no result returned by search"
|
144
130
|
@logger.debug do
|
145
|
-
args = [
|
131
|
+
args = [
|
132
|
+
search_options[:filter],
|
133
|
+
search_options[:attributes].inspect,
|
134
|
+
]
|
146
135
|
_("No matches: filter: %s: attributes: %s") % args
|
147
136
|
end
|
148
137
|
else
|
@@ -220,15 +209,17 @@ module ActiveLdap
|
|
220
209
|
def prepare_connection(options={})
|
221
210
|
operation(options) do
|
222
211
|
@connection.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
|
223
|
-
|
224
|
-
|
225
|
-
|
212
|
+
@ldap_follow_referrals = follow_referrals?(options) ? 1 : 0
|
213
|
+
@connection.set_option(LDAP::LDAP_OPT_REFERRALS,
|
214
|
+
@ldap_follow_referrals)
|
226
215
|
end
|
227
216
|
end
|
228
217
|
|
229
218
|
def execute(method, info=nil, *args, &block)
|
230
219
|
begin
|
231
220
|
name = (info || {}).delete(:name) || method
|
221
|
+
@connection.set_option(LDAP::LDAP_OPT_REFERRALS,
|
222
|
+
@ldap_follow_referrals)
|
232
223
|
log(name, info) {@connection.send(method, *args, &block)}
|
233
224
|
rescue LDAP::ResultError
|
234
225
|
@connection.assert_error_code
|
@@ -65,12 +65,28 @@ module LDAP
|
|
65
65
|
attributes = options[:attributes]
|
66
66
|
limit = options[:limit] || 0
|
67
67
|
use_paged_results = options[:use_paged_results]
|
68
|
+
page_size = options[:page_size]
|
68
69
|
if @@have_search_ext
|
69
70
|
if use_paged_results
|
70
|
-
paged_search(base,
|
71
|
+
paged_search(base,
|
72
|
+
scope,
|
73
|
+
filter,
|
74
|
+
attributes,
|
75
|
+
limit,
|
76
|
+
page_size,
|
77
|
+
&block)
|
71
78
|
else
|
72
|
-
search_ext(base,
|
73
|
-
|
79
|
+
search_ext(base,
|
80
|
+
scope,
|
81
|
+
filter,
|
82
|
+
attributes,
|
83
|
+
false,
|
84
|
+
nil,
|
85
|
+
nil,
|
86
|
+
0,
|
87
|
+
0,
|
88
|
+
limit,
|
89
|
+
&block)
|
74
90
|
end
|
75
91
|
else
|
76
92
|
i = 0
|
@@ -120,27 +136,30 @@ module LDAP
|
|
120
136
|
end
|
121
137
|
end
|
122
138
|
|
123
|
-
def paged_search(base, scope, filter, attributes, limit, &block)
|
124
|
-
# work around a bug with openldap
|
125
|
-
page_size = 126
|
139
|
+
def paged_search(base, scope, filter, attributes, limit, page_size, &block)
|
126
140
|
cookie = ""
|
127
141
|
critical = true
|
128
|
-
|
129
142
|
loop do
|
130
143
|
ber_string = LDAP::Control.encode(page_size, cookie)
|
131
144
|
control = LDAP::Control.new(LDAP::LDAP_CONTROL_PAGEDRESULTS,
|
132
145
|
ber_string,
|
133
146
|
critical)
|
134
|
-
|
135
|
-
|
136
|
-
|
147
|
+
search_ext(base,
|
148
|
+
scope,
|
149
|
+
filter,
|
150
|
+
attributes,
|
151
|
+
false,
|
152
|
+
[control],
|
153
|
+
nil,
|
154
|
+
0,
|
155
|
+
0,
|
156
|
+
limit,
|
157
|
+
&block)
|
137
158
|
|
138
159
|
control = find_paged_results_control(@controls)
|
139
160
|
break if control.nil?
|
140
|
-
returned_size, cookie = control.decode
|
141
|
-
returned_size = returned_size.to_i
|
142
|
-
page_size = returned_size if returned_size > 0
|
143
161
|
|
162
|
+
_estimated_result_set_size, cookie = control.decode
|
144
163
|
break if cookie.empty?
|
145
164
|
end
|
146
165
|
end
|
@@ -69,25 +69,16 @@ module ActiveLdap
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def search(options={})
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
else
|
76
|
-
paged_results_supported = false
|
77
|
-
end
|
78
|
-
super(options) do |base, scope, filter, attrs, limit|
|
72
|
+
super(options) do |search_options|
|
73
|
+
scope = search_options[:scope]
|
74
|
+
info = search_options.merge(scope: scope_name(scope))
|
79
75
|
args = {
|
80
|
-
:
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:attributes
|
84
|
-
:
|
85
|
-
:
|
86
|
-
}
|
87
|
-
info = {
|
88
|
-
:base => base, :scope => scope_name(scope),
|
89
|
-
:filter => filter, :attributes => attrs, :limit => limit,
|
90
|
-
:paged_results_supported => paged_results_supported,
|
76
|
+
base: search_options[:base],
|
77
|
+
scope: scope,
|
78
|
+
filter: search_options[:filter],
|
79
|
+
attributes: search_options[:attributes],
|
80
|
+
size: search_options[:limit],
|
81
|
+
paged_searcheds_supported: search_options[:paged_results_supported],
|
91
82
|
}
|
92
83
|
execute(:search, info, args) do |entry|
|
93
84
|
attributes = {}
|
data/lib/active_ldap/base.rb
CHANGED
@@ -851,6 +851,8 @@ module ActiveLdap
|
|
851
851
|
|
852
852
|
_schema = _local_entry_attribute = nil
|
853
853
|
targets = sanitize_for_mass_assignment(new_attributes)
|
854
|
+
have_dn = false
|
855
|
+
dn_value = nil
|
854
856
|
targets.each do |key, value|
|
855
857
|
setter = "#{key}="
|
856
858
|
unless respond_to?(setter)
|
@@ -860,8 +862,15 @@ module ActiveLdap
|
|
860
862
|
_local_entry_attribute ||= local_entry_attribute
|
861
863
|
_local_entry_attribute.register(attribute)
|
862
864
|
end
|
863
|
-
|
865
|
+
case setter
|
866
|
+
when "dn=", "id="
|
867
|
+
have_dn = true
|
868
|
+
dn_value = value
|
869
|
+
else
|
870
|
+
send(setter, value)
|
871
|
+
end
|
864
872
|
end
|
873
|
+
self.dn = dn_value if have_dn
|
865
874
|
end
|
866
875
|
|
867
876
|
def to_ldif_record
|
@@ -1281,6 +1290,7 @@ module ActiveLdap
|
|
1281
1290
|
end
|
1282
1291
|
|
1283
1292
|
def compute_base
|
1293
|
+
ensure_update_dn
|
1284
1294
|
base_of_class = self.class.base
|
1285
1295
|
if @base_value.nil?
|
1286
1296
|
base_of_class
|
@@ -48,6 +48,15 @@ module ActiveLdap
|
|
48
48
|
DEFAULT_CONFIG[:retry_on_timeout] = true
|
49
49
|
DEFAULT_CONFIG[:follow_referrals] = true
|
50
50
|
|
51
|
+
# 500 is the default size limit value of OpenLDAP 2.4:
|
52
|
+
# https://openldap.org/doc/admin24/limits.html#Global%20Limits
|
53
|
+
#
|
54
|
+
# We may change this when we find LDAP server that its the default
|
55
|
+
# size limit is smaller than 500.
|
56
|
+
DEFAULT_CONFIG[:page_size] = 500
|
57
|
+
# Whether using paged results if available.
|
58
|
+
DEFAULT_CONFIG[:use_paged_results] = true
|
59
|
+
|
51
60
|
DEFAULT_CONFIG[:logger] = nil
|
52
61
|
|
53
62
|
module ClassMethods
|
@@ -103,8 +112,22 @@ module ActiveLdap
|
|
103
112
|
end
|
104
113
|
end
|
105
114
|
|
115
|
+
def parent_configuration(target)
|
116
|
+
if target.is_a?(Base)
|
117
|
+
target = target.class
|
118
|
+
else
|
119
|
+
target = target.superclass
|
120
|
+
end
|
121
|
+
while target <= Base
|
122
|
+
config = defined_configurations[target.active_connection_key]
|
123
|
+
return config if config
|
124
|
+
target = target.superclass
|
125
|
+
end
|
126
|
+
default_configuration
|
127
|
+
end
|
128
|
+
|
106
129
|
def merge_configuration(user_configuration, target=self)
|
107
|
-
configuration =
|
130
|
+
configuration = parent_configuration(target).dup
|
108
131
|
prepare_configuration(user_configuration).each do |key, value|
|
109
132
|
case key
|
110
133
|
when :base
|
@@ -6,7 +6,7 @@ module ActiveLdap
|
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
@@active_connections = {}
|
9
|
-
@@allow_concurrency =
|
9
|
+
@@allow_concurrency = true
|
10
10
|
|
11
11
|
def thread_safe_active_connections
|
12
12
|
@@active_connections[Thread.current.object_id] ||= {}
|
@@ -165,11 +165,11 @@ module ActiveLdap
|
|
165
165
|
connection.schema
|
166
166
|
end
|
167
167
|
|
168
|
-
private
|
169
168
|
def active_connection_key(k=self)
|
170
169
|
k.name.blank? ? k.object_id : k.name
|
171
170
|
end
|
172
171
|
|
172
|
+
private
|
173
173
|
def determine_active_connection_name
|
174
174
|
key = active_connection_key
|
175
175
|
if active_connections[key] or configuration(key)
|
@@ -17,11 +17,12 @@ module ActiveLdap
|
|
17
17
|
if attribute_or_name.is_a?(Schema::Attribute)
|
18
18
|
name = attribute_or_name.name
|
19
19
|
else
|
20
|
-
|
20
|
+
attribute_name = attribute_or_name.to_s
|
21
|
+
attribute = schema.attribute(attribute_name)
|
21
22
|
return nil if attribute.id.nil?
|
22
|
-
if attribute.name ==
|
23
|
-
attribute.aliases.include?(
|
24
|
-
name =
|
23
|
+
if attribute.name == attribute_name or
|
24
|
+
attribute.aliases.include?(attribute_name)
|
25
|
+
name = attribute_name
|
25
26
|
else
|
26
27
|
return nil
|
27
28
|
end
|
@@ -22,9 +22,23 @@ module ActiveLdap
|
|
22
22
|
end
|
23
23
|
|
24
24
|
module Common
|
25
|
-
VALID_SEARCH_OPTIONS = [
|
26
|
-
|
27
|
-
|
25
|
+
VALID_SEARCH_OPTIONS = [
|
26
|
+
:attribute,
|
27
|
+
:value,
|
28
|
+
:filter,
|
29
|
+
:prefix,
|
30
|
+
:classes,
|
31
|
+
:scope,
|
32
|
+
:limit,
|
33
|
+
:attributes,
|
34
|
+
:sort_by,
|
35
|
+
:order,
|
36
|
+
:connection,
|
37
|
+
:base,
|
38
|
+
:offset,
|
39
|
+
:use_paged_results,
|
40
|
+
:page_size,
|
41
|
+
]
|
28
42
|
|
29
43
|
def search(options={}, &block)
|
30
44
|
validate_search_options(options)
|
@@ -62,6 +76,8 @@ module ActiveLdap
|
|
62
76
|
:attributes => requested_attributes,
|
63
77
|
:sort_by => options[:sort_by] || sort_by,
|
64
78
|
:order => options[:order] || order,
|
79
|
+
:use_paged_results => options[:use_paged_results],
|
80
|
+
:page_size => options[:page_size],
|
65
81
|
}
|
66
82
|
options[:connection] ||= connection
|
67
83
|
values = []
|
@@ -96,10 +112,11 @@ module ActiveLdap
|
|
96
112
|
}
|
97
113
|
|
98
114
|
attribute = attr || ensure_search_attribute
|
115
|
+
escaped_value = DN.escape_value(value)
|
99
116
|
options_for_non_leaf = {
|
100
117
|
:attribute => attr,
|
101
118
|
:value => value,
|
102
|
-
:prefix => ["#{attribute}=#{
|
119
|
+
:prefix => ["#{attribute}=#{escaped_value}", prefix].compact.join(","),
|
103
120
|
:limit => 1,
|
104
121
|
:scope => :base,
|
105
122
|
}
|
@@ -81,9 +81,10 @@ module ActiveLdap
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
def reload
|
84
|
+
def reload(options={})
|
85
85
|
clear_association_cache
|
86
|
-
|
86
|
+
search_options = options.merge(value: id)
|
87
|
+
_, attributes = search(search_options).find do |_dn, _attributes|
|
87
88
|
dn == _dn
|
88
89
|
end
|
89
90
|
if attributes.nil?
|
@@ -53,15 +53,23 @@ module ActiveLdap
|
|
53
53
|
errors.empty? && output
|
54
54
|
end
|
55
55
|
|
56
|
-
def save(
|
57
|
-
|
56
|
+
def save(**options)
|
57
|
+
perform_validations(options) ? super : false
|
58
58
|
end
|
59
59
|
|
60
|
-
def save!(
|
61
|
-
|
60
|
+
def save!(**options)
|
61
|
+
perform_validations(options) ? super : raise(EntryInvalid.new(self))
|
62
62
|
end
|
63
63
|
|
64
64
|
private
|
65
|
+
def perform_validations(options)
|
66
|
+
if options[:validate] == false
|
67
|
+
true
|
68
|
+
else
|
69
|
+
valid?(options[:context])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
65
73
|
def format_validation_message(format, parameters)
|
66
74
|
format % parameters
|
67
75
|
end
|
data/lib/active_ldap/version.rb
CHANGED