ucb_ldap 1.3.2 → 1.4.2
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/CHANGELOG +5 -0
- data/Manifest +1 -1
- data/README +5 -5
- data/Rakefile +2 -2
- data/TODO +1 -1
- data/lib/person/affiliation_methods.rb +22 -9
- data/lib/ucb_ldap.rb +55 -58
- data/lib/ucb_ldap_entry.rb +96 -26
- data/lib/ucb_ldap_namespace.rb +17 -9
- data/lib/ucb_ldap_org.rb +130 -70
- data/lib/ucb_ldap_person.rb +26 -13
- data/lib/ucb_ldap_service.rb +4 -2
- data/schema/schema.yml +135 -2
- data/ucb_ldap.gemspec +9 -13
- data/version.yml +1 -1
- metadata +32 -25
- data/init.rb +0 -1
data/lib/ucb_ldap_namespace.rb
CHANGED
@@ -1,42 +1,50 @@
|
|
1
1
|
|
2
2
|
module UCB
|
3
3
|
module LDAP
|
4
|
+
##
|
4
5
|
# Class for accessing the Namespace/Name part of LDAP.
|
6
|
+
#
|
5
7
|
class Namespace < Entry
|
6
|
-
|
7
8
|
@tree_base = 'ou=names,ou=namespace,dc=berkeley,dc=edu'
|
8
9
|
@entity_name = 'namespaceName'
|
9
|
-
|
10
|
+
|
11
|
+
##
|
10
12
|
# Returns name
|
13
|
+
#
|
11
14
|
def name
|
12
15
|
cn.first
|
13
16
|
end
|
14
|
-
|
17
|
+
|
18
|
+
##
|
15
19
|
# Returns +Array+ of services
|
20
|
+
#
|
16
21
|
def services
|
17
22
|
berkeleyEduServices
|
18
23
|
end
|
19
|
-
|
24
|
+
|
25
|
+
##
|
20
26
|
# Returns uid
|
27
|
+
#
|
21
28
|
def uid
|
22
29
|
super.first
|
23
30
|
end
|
24
31
|
|
25
|
-
# class methods
|
26
32
|
class << self
|
27
|
-
|
33
|
+
##
|
28
34
|
# Returns an +Array+ of Namespace for _uid_.
|
35
|
+
#
|
29
36
|
def find_by_uid(uid)
|
30
37
|
search(:filter => "uid=#{uid}")
|
31
38
|
end
|
32
|
-
|
39
|
+
|
40
|
+
##
|
33
41
|
# Returns Namespace instance for _cn_.
|
42
|
+
#
|
34
43
|
def find_by_cn(cn)
|
35
44
|
search(:filter => "cn=#{cn}").first
|
36
45
|
end
|
37
|
-
|
38
46
|
end
|
39
|
-
|
40
47
|
end
|
48
|
+
|
41
49
|
end
|
42
50
|
end
|
data/lib/ucb_ldap_org.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
module UCB
|
3
3
|
module LDAP
|
4
|
-
|
4
|
+
##
|
5
5
|
# =UCB::LDAP::Org
|
6
6
|
#
|
7
7
|
# Class for accessing the Org Unit tree of the UCB LDAP directory.
|
@@ -138,84 +138,109 @@ module UCB
|
|
138
138
|
class Org < Entry
|
139
139
|
@entity_name = "org"
|
140
140
|
@tree_base = 'ou=org units,dc=berkeley,dc=edu'
|
141
|
-
|
141
|
+
|
142
|
+
##
|
142
143
|
# Returns <tt>Array</tt> of child nodes, each an instance of Org,
|
143
144
|
# sorted by department id.
|
144
|
-
|
145
|
-
|
145
|
+
#
|
146
|
+
def child_nodes()
|
147
|
+
@sorted_child_nodes ||= load_child_nodes.sort_by { |node| node.deptid }
|
146
148
|
end
|
147
|
-
|
149
|
+
|
150
|
+
##
|
148
151
|
# Returns the department id.
|
149
|
-
|
152
|
+
#
|
153
|
+
def deptid()
|
150
154
|
ou.first
|
151
155
|
end
|
152
156
|
alias :code :deptid
|
153
|
-
|
157
|
+
|
158
|
+
##
|
154
159
|
# Returns the entry's level in the Org Tree.
|
155
|
-
|
160
|
+
#
|
161
|
+
def level()
|
156
162
|
@level ||= parent_deptids.size + 1
|
157
163
|
end
|
158
|
-
|
164
|
+
|
165
|
+
##
|
159
166
|
# Returns the department name.
|
160
|
-
|
167
|
+
#
|
168
|
+
def name()
|
161
169
|
description.first
|
162
170
|
end
|
163
|
-
|
171
|
+
|
172
|
+
##
|
164
173
|
# Returns parent node's deptid
|
165
|
-
|
174
|
+
#
|
175
|
+
def parent_deptid()
|
166
176
|
@parent_deptid ||= parent_deptids.last
|
167
177
|
end
|
168
|
-
|
178
|
+
|
179
|
+
##
|
169
180
|
# Returns Array of parent deptids.
|
170
181
|
#
|
171
182
|
# Highest level is first element; immediate parent is last element.
|
172
|
-
|
183
|
+
#
|
184
|
+
def parent_deptids()
|
173
185
|
return @parent_deptids if @parent_deptids
|
174
186
|
hierarchy_array = berkeleyEduOrgUnitHierarchyString.split("-")
|
175
187
|
hierarchy_array.pop # last element is deptid ... toss it
|
176
188
|
@parent_deptids = hierarchy_array
|
177
189
|
end
|
178
|
-
|
190
|
+
|
191
|
+
##
|
179
192
|
# Returns +true+ if org is a processing unit.
|
180
|
-
|
193
|
+
#
|
194
|
+
def processing_unit?()
|
181
195
|
berkeleyEduOrgUnitProcessUnitFlag
|
182
196
|
end
|
183
|
-
|
197
|
+
|
198
|
+
##
|
184
199
|
# Return parent node which is an instance of Org.
|
185
|
-
|
200
|
+
#
|
201
|
+
def parent_node()
|
186
202
|
return nil if parent_deptids.size == 0
|
187
203
|
@parent_node ||= UCB::LDAP::Org.find_by_ou parent_deptid
|
188
204
|
end
|
189
|
-
|
205
|
+
|
206
|
+
##
|
190
207
|
# Returns <tt>Array</tt> of parent nodes which are instances of Org.
|
191
|
-
|
192
|
-
|
208
|
+
#
|
209
|
+
def parent_nodes()
|
210
|
+
@parent_nodes ||= parent_deptids.map { |deptid| UCB::LDAP::Org.find_by_ou(deptid) }
|
193
211
|
end
|
194
|
-
|
212
|
+
|
213
|
+
##
|
195
214
|
# Support for method names like level_2_code, level_2_name
|
215
|
+
#
|
196
216
|
def method_missing(method, *args) #:nodoc:
|
197
217
|
return code_or_name_at_level($1, $2) if method.to_s =~ /^level_([1-6])_(code|name)$/
|
198
218
|
super
|
199
219
|
end
|
200
|
-
|
220
|
+
|
221
|
+
##
|
201
222
|
# Return the level "n" code or name. Returns nil if level > self.level.
|
202
223
|
# Called from method_messing().
|
224
|
+
#
|
203
225
|
def code_or_name_at_level(level, code_or_name) #:nodoc:
|
204
226
|
return (code_or_name == 'code' ? code : name) if level.to_i == self.level
|
205
227
|
element = level.to_i - 1
|
206
228
|
return parent_deptids[element] if code_or_name == 'code'
|
207
229
|
parent_nodes[element] && parent_nodes[element].name
|
208
230
|
end
|
209
|
-
|
231
|
+
|
232
|
+
##
|
210
233
|
# Returns <tt>Array</tt> of UCB::LDAP::Person instances for each person
|
211
234
|
# in the org node.
|
212
|
-
|
235
|
+
#
|
236
|
+
def persons()
|
213
237
|
@persons ||= UCB::LDAP::Person.search(:filter => {:departmentnumber => ou})
|
214
238
|
end
|
215
|
-
|
239
|
+
alias :people :persons
|
240
|
+
|
216
241
|
#---
|
217
242
|
# Must be public for load_all_nodes()
|
218
|
-
def init_child_nodes #:nodoc:
|
243
|
+
def init_child_nodes() #:nodoc:
|
219
244
|
@child_nodes = []
|
220
245
|
end
|
221
246
|
|
@@ -223,65 +248,87 @@ module UCB
|
|
223
248
|
# Add node to child node array.
|
224
249
|
def push_child_node(child_node)#:nodoc:
|
225
250
|
@child_nodes ||= []
|
226
|
-
@child_nodes.
|
227
|
-
@child_nodes.
|
251
|
+
unless @child_nodes.find { |n| n.ou == child_node.ou }
|
252
|
+
@child_nodes.push(child_node)
|
253
|
+
end
|
228
254
|
end
|
229
255
|
|
230
256
|
private unless $TESTING
|
231
|
-
|
257
|
+
|
258
|
+
##
|
232
259
|
# Loads child nodes for individual node. If all_nodes_nodes()
|
233
260
|
# has been called, child nodes are all loaded/calculated.
|
261
|
+
#
|
234
262
|
def load_child_nodes
|
235
263
|
@child_nodes ||= UCB::LDAP::Org.search(:scope => 1, :base => dn, :filter => {:ou => '*'})
|
236
264
|
end
|
237
|
-
|
238
|
-
# Access to instance variables for testing
|
239
265
|
|
240
|
-
|
266
|
+
##
|
267
|
+
# Access to instance variables for testing
|
268
|
+
#
|
269
|
+
def child_nodes_i()
|
241
270
|
@child_nodes
|
242
271
|
end
|
243
272
|
|
244
|
-
|
273
|
+
|
245
274
|
class << self
|
246
275
|
public
|
247
276
|
|
277
|
+
##
|
278
|
+
# Rebuild the org tree using fresh data from ldap
|
279
|
+
#
|
280
|
+
def rebuild_node_cache
|
281
|
+
clear_all_nodes
|
282
|
+
load_all_nodes
|
283
|
+
end
|
284
|
+
|
285
|
+
##
|
248
286
|
# Returns a +Hash+ of all org nodes whose keys are deptids
|
249
287
|
# and whose values are corresponding Org instances.
|
250
|
-
|
288
|
+
#
|
289
|
+
def all_nodes()
|
251
290
|
@all_nodes ||= load_all_nodes
|
252
291
|
end
|
253
292
|
|
293
|
+
##
|
254
294
|
# Returns an instance of Org for the matching _ou_.
|
295
|
+
#
|
255
296
|
def find_by_ou(ou)
|
256
297
|
find_by_ou_from_cache(ou) || search(:filter => {:ou => ou}).first
|
257
298
|
end
|
258
|
-
|
299
|
+
|
300
|
+
##
|
259
301
|
# for backwards compatibility -- should be deprecated
|
302
|
+
#
|
260
303
|
alias :org_by_ou :find_by_ou
|
261
|
-
|
304
|
+
|
305
|
+
##
|
262
306
|
# Returns an +Array+ of all nodes in hierarchy order. If you call
|
263
307
|
# with <tt>:level</tt> option, only nodes down to that level are
|
264
308
|
# returned.
|
265
309
|
#
|
266
310
|
# Org.flattened_tree # returns all nodes
|
267
311
|
# Org.flattened_tree(:level => 3) # returns down to level 3
|
312
|
+
#
|
268
313
|
def flattened_tree(options={})
|
269
314
|
@flattened_tree ||= build_flattened_tree
|
270
315
|
return @flattened_tree unless options[:level]
|
271
|
-
@flattened_tree.reject{|o| o.level > options[:level]}
|
316
|
+
@flattened_tree.reject { |o| o.level > options[:level] }
|
272
317
|
end
|
273
|
-
|
274
|
-
|
318
|
+
|
319
|
+
##
|
320
|
+
# Loads all org nodes and stores them in Hash returned by all_nodes().
|
275
321
|
# Subsequent calls to find_by_ou() will be from cache and not
|
276
322
|
# require a trip to the LDAP server.
|
277
|
-
|
323
|
+
#
|
324
|
+
def load_all_nodes()
|
278
325
|
return @all_nodes if @all_nodes
|
279
326
|
return nodes_from_test_cache if $TESTING && @test_node_cache
|
280
327
|
|
281
|
-
@all_nodes = {}
|
282
328
|
bind_for_whole_tree
|
283
|
-
search(
|
284
|
-
|
329
|
+
@all_nodes = search.inject({}) do |accum, org|
|
330
|
+
accum[org.deptid] = org if org.deptid != "Org Units"
|
331
|
+
accum
|
285
332
|
end
|
286
333
|
|
287
334
|
build_test_node_cache if $TESTING
|
@@ -289,81 +336,94 @@ module UCB
|
|
289
336
|
UCB::LDAP.clear_authentication
|
290
337
|
@all_nodes
|
291
338
|
end
|
292
|
-
|
339
|
+
|
340
|
+
##
|
293
341
|
# Returns the root node in the Org Tree.
|
294
|
-
|
342
|
+
#
|
343
|
+
def root_node()
|
295
344
|
load_all_nodes
|
296
|
-
find_by_ou
|
345
|
+
find_by_ou('UCBKL')
|
297
346
|
end
|
298
347
|
|
299
348
|
private unless $TESTING
|
300
|
-
|
349
|
+
|
350
|
+
##
|
301
351
|
# Use bind that allows for retreiving entire org tree in one search.
|
302
|
-
|
352
|
+
#
|
353
|
+
def bind_for_whole_tree()
|
303
354
|
username = "uid=istaswa-ruby,ou=applications,dc=berkeley,dc=edu"
|
304
355
|
password = "t00lBox12"
|
305
356
|
UCB::LDAP.authenticate(username, password)
|
306
357
|
end
|
307
|
-
|
358
|
+
|
359
|
+
##
|
308
360
|
# Returns an instance of Org from the local if cache exists, else +nil+.
|
361
|
+
#
|
309
362
|
def find_by_ou_from_cache(ou) #:nodoc:
|
310
363
|
return nil if ou.nil?
|
311
364
|
return nil unless @all_nodes
|
312
365
|
@all_nodes[ou.upcase]
|
313
366
|
end
|
314
|
-
|
367
|
+
|
368
|
+
##
|
315
369
|
# Returns cached nodes if we are testing and have already
|
316
370
|
# fetched all the nodes.
|
317
|
-
|
371
|
+
#
|
372
|
+
def nodes_from_test_cache()
|
318
373
|
@all_nodes = {}
|
319
|
-
@test_node_cache.each{|k, v| @all_nodes[k] = v.clone}
|
374
|
+
@test_node_cache.each { |k, v| @all_nodes[k] = v.clone }
|
320
375
|
calculate_all_child_nodes
|
321
376
|
@all_nodes
|
322
377
|
end
|
323
|
-
|
378
|
+
|
379
|
+
##
|
324
380
|
# Build cache of all nodes. Only used during testing.
|
381
|
+
#
|
325
382
|
def build_test_node_cache()
|
326
383
|
@test_node_cache = {}
|
327
|
-
@all_nodes.each{|k, v| @test_node_cache[k] = v.clone}
|
384
|
+
@all_nodes.each { |k, v| @test_node_cache[k] = v.clone }
|
328
385
|
end
|
329
|
-
|
386
|
+
|
387
|
+
##
|
330
388
|
# Will calculate child_nodes for every node.
|
331
|
-
|
332
|
-
|
333
|
-
|
389
|
+
#
|
390
|
+
def calculate_all_child_nodes()
|
391
|
+
@all_nodes.values.each { |node| node.init_child_nodes }
|
334
392
|
@all_nodes.values.each do |node|
|
335
393
|
next if node.deptid == 'UCBKL' || node.deptid == "Org Units"
|
336
|
-
parent_node = find_by_ou_from_cache
|
337
|
-
parent_node.push_child_node
|
394
|
+
parent_node = find_by_ou_from_cache(node.parent_deptids.last)
|
395
|
+
parent_node.push_child_node(node)
|
338
396
|
end
|
339
397
|
end
|
340
|
-
|
398
|
+
|
399
|
+
##
|
341
400
|
# Builds flattened tree. See RDoc for flattened_tree() for details.
|
342
|
-
|
401
|
+
#
|
402
|
+
def build_flattened_tree()
|
343
403
|
load_all_nodes
|
344
404
|
@flattened_tree = []
|
345
405
|
add_to_flattened_tree UCB::LDAP::Org.root_node
|
346
406
|
@flattened_tree
|
347
407
|
end
|
348
|
-
|
408
|
+
|
409
|
+
##
|
349
410
|
# Adds a node and its children to @flattened_tree.
|
411
|
+
#
|
350
412
|
def add_to_flattened_tree(node)
|
351
413
|
@flattened_tree.push node
|
352
|
-
node.child_nodes.each{|child| add_to_flattened_tree child}
|
414
|
+
node.child_nodes.each { |child| add_to_flattened_tree child }
|
353
415
|
end
|
354
416
|
|
355
417
|
# Direct access to instance variables for unit testing
|
356
418
|
|
357
|
-
def all_nodes_i
|
419
|
+
def all_nodes_i()
|
358
420
|
@all_nodes
|
359
421
|
end
|
360
422
|
|
361
|
-
def clear_all_nodes
|
423
|
+
def clear_all_nodes()
|
362
424
|
@all_nodes = nil
|
363
425
|
end
|
364
|
-
|
365
|
-
end # end of class methods
|
366
|
-
|
426
|
+
end
|
367
427
|
end
|
368
428
|
end
|
369
429
|
end
|
data/lib/ucb_ldap_person.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
module UCB::LDAP
|
3
|
+
##
|
3
4
|
# =UCB::LDAP::Person
|
4
5
|
#
|
5
6
|
# Class for accessing the People tree of the UCB LDAP directory.
|
@@ -55,51 +56,57 @@ module UCB::LDAP
|
|
55
56
|
# See Ldap::Entry for general information on accessing attribute values.
|
56
57
|
#
|
57
58
|
class Person < Entry
|
58
|
-
class RecordNotFound <
|
59
|
-
end
|
59
|
+
class RecordNotFound < StandardError; end
|
60
60
|
|
61
61
|
include AffiliationMethods
|
62
62
|
include GenericAttributes
|
63
63
|
|
64
64
|
@entity_name = 'person'
|
65
65
|
@tree_base = 'ou=people,dc=berkeley,dc=edu'
|
66
|
-
|
67
66
|
|
68
67
|
class << self
|
69
|
-
|
68
|
+
##
|
70
69
|
# Returns an instance of Person for given _uid_.
|
70
|
+
#
|
71
71
|
def find_by_uid(uid)
|
72
72
|
uid = uid.to_s
|
73
73
|
find_by_uids([uid]).first
|
74
74
|
end
|
75
75
|
alias :person_by_uid :find_by_uid
|
76
|
-
|
76
|
+
|
77
|
+
##
|
77
78
|
# Returns an +Array+ of Person for given _uids_.
|
79
|
+
#
|
78
80
|
def find_by_uids(uids)
|
79
81
|
return [] if uids.size == 0
|
80
82
|
filters = uids.map{|uid| Net::LDAP::Filter.eq("uid", uid)}
|
81
83
|
search(:filter => self.combine_filters(filters, '|'))
|
82
84
|
end
|
83
85
|
alias :persons_by_uids :find_by_uids
|
84
|
-
|
86
|
+
|
87
|
+
##
|
85
88
|
# Exclude test entries from search results unless told otherwise.
|
89
|
+
#
|
86
90
|
def search(args) #:nodoc:
|
87
91
|
results = super
|
88
|
-
include_test_entries? ? results : results.reject{|person| person.test?}
|
92
|
+
include_test_entries? ? results : results.reject { |person| person.test? }
|
89
93
|
end
|
90
|
-
|
94
|
+
|
95
|
+
##
|
91
96
|
# If <tt>true</tt> test entries are included in search results
|
92
97
|
# (defalut is <tt>false</tt>).
|
98
|
+
#
|
93
99
|
def include_test_entries?
|
94
100
|
@include_test_entries ? true : false
|
95
101
|
end
|
96
|
-
|
102
|
+
|
103
|
+
##
|
97
104
|
# Setter for include_test_entries?
|
105
|
+
#
|
98
106
|
def include_test_entries=(include_test_entries)
|
99
107
|
@include_test_entries = include_test_entries
|
100
108
|
end
|
101
|
-
|
102
|
-
end # end of class methods
|
109
|
+
end
|
103
110
|
|
104
111
|
|
105
112
|
def deptid
|
@@ -110,23 +117,29 @@ module UCB::LDAP
|
|
110
117
|
def dept_name
|
111
118
|
berkeleyEduUnitCalNetDeptName
|
112
119
|
end
|
113
|
-
|
120
|
+
|
121
|
+
##
|
114
122
|
# Returns +Array+ of JobAppointment for this Person.
|
115
123
|
# Requires a bind with access to job appointments.
|
116
124
|
# See UCB::LDAP.authenticate().
|
125
|
+
#
|
117
126
|
def job_appointments
|
118
127
|
@job_appointments ||= JobAppointment.find_by_uid(uid)
|
119
128
|
end
|
120
|
-
|
129
|
+
|
130
|
+
##
|
121
131
|
# Returns +Array+ of StudentTerm for this Person.
|
122
132
|
# Requires a bind with access to student terms.
|
123
133
|
# See UCB::LDAP.authenticate().
|
134
|
+
#
|
124
135
|
def student_terms
|
125
136
|
@student_terms ||= StudentTerm.find_by_uid(uid)
|
126
137
|
end
|
127
138
|
|
139
|
+
##
|
128
140
|
# Returns instance of UCB::LDAP::Org corresponding to
|
129
141
|
# primary department.
|
142
|
+
#
|
130
143
|
def org_node
|
131
144
|
@org_node ||= UCB::LDAP::Org.find_by_ou(deptid)
|
132
145
|
end
|