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 CHANGED
@@ -1,5 +1,10 @@
1
1
  = UCB::LDAP Changelog
2
2
 
3
+ == Version 1.4.1
4
+ * Remove hack that tried to persist the net-ldap connection instance as this cause problems
5
+ with leaving countless file descriptors open when run under JRuby.
6
+ * Updated bundled schema.yml file
7
+
3
8
  == Version 1.2.1, January 22, 2008
4
9
 
5
10
  * fixed bug: include UCB::LDAP call at top level that corrupted namespace
data/Manifest CHANGED
@@ -3,7 +3,6 @@ Manifest
3
3
  README
4
4
  Rakefile
5
5
  TODO
6
- init.rb
7
6
  lib/person/adv_con_person.rb
8
7
  lib/person/affiliation_methods.rb
9
8
  lib/person/generic_attributes.rb
@@ -21,4 +20,5 @@ lib/ucb_ldap_schema_attribute.rb
21
20
  lib/ucb_ldap_service.rb
22
21
  lib/ucb_ldap_student_term.rb
23
22
  schema/schema.yml
23
+ ucb_ldap.gemspec
24
24
  version.yml
data/README CHANGED
@@ -5,7 +5,7 @@ LDAP directory: http://directory.berkeley.edu
5
5
 
6
6
  ==Introduction to LDAP
7
7
  If you are blissfully ignorant of LDAP, you should familiarize yourself with some of the basics.
8
- Here is a great online resource: http://www.zytrax.com/books/ldap.
8
+ Here is a great online resource: http://www.zytrax.com/books/ldap
9
9
 
10
10
  The RDoc for the ruby-net-ldap Gem (http://rubyfurnace.com/docs/ruby-net-ldap-0.0.4/classes/Net/LDAP.html) also has a good introduction to LDAP.
11
11
 
@@ -29,7 +29,7 @@ See UCB::LDAP::Entry for more information.
29
29
 
30
30
  Search the Person tree getting back UCB::LDAP::Person instances:
31
31
 
32
- person = UCB::LDAP::Person.person_by_uid "123"
32
+ person = UCB::LDAP::Person.find_by_uid("123")
33
33
 
34
34
  person.firstname #=> "John"
35
35
  person.affiliations #=> ['EMPLOYEE-TYPE-STAFF']
@@ -56,11 +56,11 @@ See UCB::LDAP::Org for more information.
56
56
  If you want access the directory anonomously, no credentials are required.
57
57
  If you want to access via a privileged bind, authenticate before querying:
58
58
 
59
- p = UCB::LDAP::Person.person_by_uid("123")
59
+ p = UCB::LDAP::Person.find_by_uid("123")
60
60
  p.non_public_attr #=> NoMethodError
61
61
 
62
62
  UCB::LDAP.authenticate("mybind", "mypassword")
63
- p = UCB::LDAP::Person.person_by_uid("123")
63
+ p = UCB::LDAP::Person.find_by_uid("123")
64
64
  p.non_public_attr #=> "some value"
65
65
 
66
66
  === Privileged Binds and Rails
@@ -70,7 +70,7 @@ See UCB::LDAP.bind_for_rails()
70
70
  ==Dependencies
71
71
 
72
72
  * Net::LDAP
73
- * Ruby 1.8.2 or better
73
+ * Ruby 1.8.5 or better
74
74
 
75
75
  ==Authors
76
76
 
data/Rakefile CHANGED
@@ -3,14 +3,14 @@ require 'rake'
3
3
  require 'echoe'
4
4
  require 'hanna/rdoctask'
5
5
 
6
- Echoe.new('ucb_ldap', '1.3.2') do |p|
6
+ Echoe.new('ucb_ldap', '1.4.2') do |p|
7
7
  p.description = "Convenience classes for interacing with UCB's LDAP directory"
8
8
  p.url = "http://ucbrb.rubyforge.org/ucb_ldap"
9
9
  p.author = "Steven Hansen, Steve Downey, Lucas Rockwell"
10
10
  p.email = "runner@berkeley.edu"
11
11
  p.ignore_pattern = ["svn_user.yml", "tasks/ucb_ldap.rake", "spec/**/**", "test/**/**"]
12
12
  p.project = "ucbrb"
13
- p.runtime_dependencies = ["ruby-net-ldap >= 0.0.4"]
13
+ p.runtime_dependencies = ["ruby-net-ldap >=0.0.4"]
14
14
  p.rdoc_options = "-o doc --inline-source -T hanna lib/*.rb"
15
15
  p.rdoc_pattern = ["README", "lib/**/**"]
16
16
  end
data/TODO CHANGED
@@ -1,2 +1,2 @@
1
- = TODO List for UCB::LDAP
1
+ * Make thread safe, mutex around search?
2
2
 
@@ -2,25 +2,31 @@
2
2
 
3
3
  module UCB::LDAP
4
4
  module AffiliationMethods
5
-
6
- # Returns an <tt>Array</tt> of Person's affiliations.
5
+
6
+ ##
7
+ # Returns an <tt>Array</tt> of Person's affiliations.
8
+ #
7
9
  def affiliations
8
10
  @affiliations ||= berkeleyEduAffiliations.map { |a| a.upcase }
9
11
  end
10
-
12
+
13
+ ##
11
14
  # Returns <tt>true</tt> if entry's affiliations contain _affiliation_.
12
15
  #
13
16
  # Case-insensitive.
17
+ #
14
18
  def has_affiliation?(affiliation)
15
19
  affiliations.include?(affiliation.upcase)
16
20
  end
17
-
21
+
22
+ ##
18
23
  # Returns <tt>true</tt> if Person's affiliations contain at least one affiliation of a particular type.
19
24
  #
20
25
  # p = Person.find_by_uid ...
21
26
  # p.affiliations #=> ['EMPLOYEE-TYPE-STAFF']
22
27
  # p.has_affiliation_of_type?(:employee) #=> true
23
28
  # p.has_affiliation_of_type?(:student) #=> false
29
+ #
24
30
  def has_affiliation_of_type?(affiliation_type)
25
31
  aff_type_string = affiliation_type.to_s.upcase
26
32
  affiliations.find{|a| a =~ /^#{aff_type_string}-TYPE-/} ? true : false
@@ -30,8 +36,10 @@ module UCB::LDAP
30
36
  ############################################
31
37
  # Determine if the person is an EMPLOYEE #
32
38
  ############################################
33
-
39
+
40
+ ##
34
41
  # Returns <tt>true</tt> if entry has the "staff" affiliation.
42
+ #
35
43
  def employee_staff?
36
44
  has_affiliation? 'EMPLOYEE-TYPE-STAFF'
37
45
  end
@@ -56,8 +64,10 @@ module UCB::LDAP
56
64
  ##########################################
57
65
  # Determine if the person is a STUDENT #
58
66
  ##########################################
59
-
67
+
68
+ ##
60
69
  # Returns +true+ if is an expired student.
70
+ #
61
71
  def student_expired?
62
72
  has_affiliation? 'STUDENT-STATUS-EXPIRED'
63
73
  end
@@ -73,9 +83,11 @@ module UCB::LDAP
73
83
  def student_not_registered?
74
84
  has_affiliation? 'STUDENT-TYPE-NOT REGISTERED'
75
85
  end
76
-
86
+
87
+ ##
77
88
  # Returns <tt>true</tt> if entry has a studend affiliation and
78
89
  # is not expired.
90
+ #
79
91
  def student?
80
92
  has_affiliation_of_type?(:student) && !student_expired?
81
93
  end
@@ -100,9 +112,11 @@ module UCB::LDAP
100
112
  def affiliate_directory_only?
101
113
  has_affiliation? 'AFFILIATE-TYPE-DIRECTORY ONLY'
102
114
  end
103
-
115
+
116
+ ##
104
117
  # Note: there are actually 2 types of visting affiliaties, visiting student and
105
118
  # visiting scholars. But for now we will generalize.
119
+ #
106
120
  def affiliate_visiting?
107
121
  has_affiliation? 'AFFILIATE-TYPE-VISITING'
108
122
  end
@@ -209,4 +223,3 @@ module UCB::LDAP
209
223
 
210
224
  end
211
225
  end
212
-
data/lib/ucb_ldap.rb CHANGED
@@ -1,4 +1,3 @@
1
- #
2
1
  require 'rubygems'
3
2
  require 'net/ldap'
4
3
  require 'time'
@@ -19,8 +18,8 @@ require 'ucb_ldap_student_term'
19
18
  require 'ucb_ldap_affiliation'
20
19
  require 'ucb_ldap_service'
21
20
 
22
-
23
21
  module UCB #:nodoc:
22
+ ##
24
23
  # =UCB::LDAP
25
24
  #
26
25
  # <b>If you are doing searches that don't require a privileged bind
@@ -37,29 +36,34 @@ module UCB #:nodoc:
37
36
 
38
37
  HOST_PRODUCTION = 'ldap.berkeley.edu'
39
38
  HOST_TEST = 'ldap-test.berkeley.edu'
40
-
41
- # class methods
39
+
42
40
  class << self
43
-
41
+ ##
44
42
  # Give (new) bind credentials to LDAP. An attempt will be made
45
43
  # to bind and will raise BindFailedException if bind fails.
46
44
  #
47
45
  # Call clear_authentication() to remove privileged bind.
46
+ #
48
47
  def authenticate(username, password)
49
48
  @username, @password = username, password
50
- new_net_ldap # to force bind()
49
+ new_net_ldap() # to force bind()
51
50
  end
52
-
51
+
52
+ ##
53
53
  # Removes current bind (username, password).
54
- def clear_authentication
54
+ #
55
+ def clear_authentication()
55
56
  authenticate(nil, nil)
56
57
  end
57
-
58
+
59
+ ##
58
60
  # Returns LDAP host used for lookups. Default is HOST_PRODUCTION.
59
- def host
61
+ #
62
+ def host()
60
63
  @host || HOST_PRODUCTION
61
64
  end
62
-
65
+
66
+ ##
63
67
  # Setter for #host.
64
68
  #
65
69
  # Note: validation of host is deferred until a search is performed
@@ -67,13 +71,15 @@ module UCB #:nodoc:
67
71
  # raise ConnectionFailedException.
68
72
  #---
69
73
  # Don't want to reconnect unless host really changed.
74
+ #
70
75
  def host=(host)
71
76
  if host != @host
72
77
  @host = host
73
78
  @net_ldap = nil
74
79
  end
75
80
  end
76
-
81
+
82
+ ##
77
83
  # Returns Net::LDAP instance that is used by UCB::LDAP::Entry
78
84
  # and subclasses for directory searches.
79
85
  #
@@ -81,19 +87,21 @@ module UCB #:nodoc:
81
87
  # sub-classes of Entry.
82
88
  #
83
89
  # Note: callers should not cache the results of this call unless they
84
- # are prepared to handle timed-out connections (which this method does).
85
- def net_ldap
86
- connection_open? ? @net_ldap : new_net_ldap
90
+ # are prepared to handle timed-out connections (which this method does).
91
+ #
92
+ def net_ldap()
93
+ @net_ldap ||= new_net_ldap
87
94
  end
88
95
 
89
- def password #:nodoc:
96
+ def password() #:nodoc:
90
97
  @password
91
98
  end
92
99
 
93
- def username #:nodoc:
100
+ def username() #:nodoc:
94
101
  @username
95
102
  end
96
-
103
+
104
+ ##
97
105
  # If you are using UCB::LDAP in a Rails application you can specify binds on a
98
106
  # per-environment basis, just as you can with database credentials.
99
107
  #
@@ -113,6 +121,7 @@ module UCB #:nodoc:
113
121
  #
114
122
  # Runtime error will be raised if bind_file not found or if environment key not
115
123
  # found in bind_file.
124
+ #
116
125
  def bind_for_rails(bind_file = "#{RAILS_ROOT}/config/ldap.yml", environment = RAILS_ENV)
117
126
  bind(bind_file, environment)
118
127
  end
@@ -123,85 +132,73 @@ module UCB #:nodoc:
123
132
  bind = binds[environment] || raise("Can't find environment=#{environment} in bind file")
124
133
  authenticate(bind['username'], bind['password'])
125
134
  end
126
-
135
+
136
+ ##
127
137
  # Returns +arg+ as a Ruby +Date+ in local time zone. Returns +nil+ if +arg+ is +nil+.
138
+ #
128
139
  def local_date_parse(arg)
129
140
  arg.nil? ? nil : Date.parse(Time.parse(arg.to_s).localtime.to_s)
130
141
  end
131
-
142
+
143
+ ##
132
144
  # Returns +arg+ as a Ruby +DateTime+ in local time zone. Returns +nil+ if +arg+ is +nil+.
145
+ #
133
146
  def local_datetime_parse(arg)
134
147
  arg.nil? ? nil : DateTime.parse(Time.parse(arg.to_s).localtime.to_s)
135
148
  end
136
149
 
137
150
  private unless $TESTING
138
-
151
+
152
+ ##
139
153
  # The value of the :auth parameter for Net::LDAP.new().
140
- def authentication_information
154
+ #
155
+ def authentication_information()
141
156
  password.nil? ?
142
157
  {:method => :anonymous} :
143
158
  {:method => :simple, :username => username, :password => password}
144
159
  end
145
-
146
- # Returns +true+ if we have a Net::LDAP instance with an open
147
- # connection.
148
- def connection_open?
149
- @net_ldap.nil? ? false : ldap_ping
150
- rescue
151
- false
152
- end
153
-
160
+
161
+ ##
154
162
  # Returns +true+ if connection simple search works.
155
- def ldap_ping
163
+ #
164
+ def ldap_ping()
156
165
  search_attrs = {
157
166
  :base => "",
158
167
  :scope => Net::LDAP::SearchScope_BaseObject,
159
168
  :attributes => [1.1]
160
169
  }
161
170
  result = false
162
- @net_ldap.search(search_attrs){result = true}
171
+ @net_ldap.search(search_attrs) { result = true }
163
172
  result
164
173
  end
165
-
166
- # Returns new Net::LDAP instance. Also
167
- # reaches into the Net::LDAP to set the @open_connection instance
168
- # variable.
174
+
175
+ ##
176
+ # Returns new Net::LDAP instance.
169
177
  #
170
- # Warning: this seems to be contrary to the Net::LDAP author's
171
- # intent and may break with future versions of Net::LDAP.
172
178
  def new_net_ldap()
173
- @net_ldap = Net::LDAP.new(
179
+ params = {
174
180
  :host => host,
175
181
  :auth => authentication_information,
176
182
  :port => 636,
177
183
  :encryption => {:method =>:simple_tls}
178
- )
179
- @net_ldap.instance_variable_set(:@open_connection, new_net_ldap_connection)
184
+ }
185
+ @net_ldap = Net::LDAP.new(params)
180
186
  @net_ldap.bind || raise(BindFailedException)
181
187
  @net_ldap
188
+ rescue Net::LDAP::LdapError => e
189
+ raise(BindFailedException)
182
190
  end
183
-
184
- # Return a new Net::LDAP::Connection
185
- def new_net_ldap_connection
186
- Net::LDAP::Connection.new(
187
- :host => host,
188
- :port => 636,
189
- :encryption => {:method => :simple_tls}
190
- )
191
- rescue Net::LDAP::LdapError
192
- raise UCB::LDAP::ConnectionFailedException
193
- end
194
-
191
+
192
+ ##
195
193
  # Used for testing
196
- def clear_instance_variables
194
+ #
195
+ def clear_instance_variables()
197
196
  @host = nil
198
197
  @net_ldap = nil
199
198
  @username = nil
200
199
  @password = nil
201
200
  end
202
-
203
201
  end
204
-
205
- end
202
+ end
206
203
  end
207
204
 
@@ -1,5 +1,6 @@
1
1
  module UCB
2
2
  module LDAP
3
+ ##
3
4
  # = UCB::LDAP::Entry
4
5
  #
5
6
  # Abstract class representing an entry in the UCB LDAP directory. You
@@ -75,12 +76,14 @@ module UCB
75
76
  # * #delete/#delete! - instance methods that do LDAP delete
76
77
  #
77
78
  class Entry
78
-
79
+
80
+ ##
79
81
  # Returns new instance of UCB::LDAP::Entry. The argument
80
82
  # net_ldap_entry is an instance of Net::LDAP::Entry.
81
83
  #
82
84
  # You should not need to create any UCB::LDAP::Entry instances;
83
85
  # they are created by calls to UCB::LDAP.search and friends.
86
+ #
84
87
  def initialize(net_ldap_entry) #:nodoc:
85
88
  # Don't store Net::LDAP entry in object since it uses the block
86
89
  # initialization method of Hash which can't be marshalled ... this
@@ -90,7 +93,8 @@ module UCB
90
93
  @attributes[canonical(attr)] = value.map{|v| v.dup}
91
94
  end
92
95
  end
93
-
96
+
97
+ ##
94
98
  # <tt>Hash</tt> of attributes returned from underlying NET::LDAP::Entry
95
99
  # instance. Hash keys are #canonical attribute names, hash values are attribute
96
100
  # values <em>as returned from LDAP</em>, i.e. arrays.
@@ -98,11 +102,14 @@ module UCB
98
102
  # You should most likely be referencing attributes as if they were
99
103
  # instance methods rather than directly through this method. See top of
100
104
  # this document.
105
+ #
101
106
  def attributes
102
107
  @attributes
103
108
  end
104
-
109
+
110
+ ##
105
111
  # Returns the value of the <em>Distinguished Name</em> attribute.
112
+ #
106
113
  def dn
107
114
  attributes[canonical(:dn)]
108
115
  end
@@ -110,7 +117,8 @@ module UCB
110
117
  def canonical(string_or_symbol) #:nodoc:
111
118
  self.class.canonical(string_or_symbol)
112
119
  end
113
-
120
+
121
+ ##
114
122
  # Update an existing entry. Returns entry if successful else false.
115
123
  #
116
124
  # attrs = {:attr1 => "new_v1", :attr2 => "new_v2"}
@@ -124,18 +132,24 @@ module UCB
124
132
  end
125
133
  false
126
134
  end
127
-
128
- # Same as #update_attributes(), but raises DirectoryNotUpdated on failure.
135
+
136
+ ##
137
+ # Same as #update_attributes(), but raises DirectoryNotUpdated on failure.
138
+ #
129
139
  def update_attributes!(attrs)
130
140
  update_attributes(attrs) || raise(DirectoryNotUpdatedException)
131
141
  end
132
-
142
+
143
+ ##
133
144
  # Delete entry. Returns +true+ on sucess, +false+ on failure.
145
+ #
134
146
  def delete
135
147
  net_ldap.delete(:dn => dn)
136
148
  end
137
-
149
+
150
+ ##
138
151
  # Same as #delete() except raises DirectoryNotUpdated on failure.
152
+ #
139
153
  def delete!
140
154
  delete || raise(DirectoryNotUpdatedException)
141
155
  end
@@ -146,30 +160,38 @@ module UCB
146
160
 
147
161
 
148
162
  private unless $TESTING
149
-
163
+
164
+ ##
150
165
  # Used to get/set attribute values.
151
166
  #
152
167
  # If we can't make an attribute name out of method, let
153
168
  # regular method_missing() handle it.
169
+ #
154
170
  def method_missing(method, *args) #:nodoc:
155
171
  setter_method?(method) ? value_setter(method, *args) : value_getter(method)
156
172
  rescue BadAttributeNameException
157
173
  return super
158
174
  end
159
-
175
+
176
+ ##
160
177
  # Returns +true+ if _method_ is a "setter", i.e., ends in "=".
178
+ #
161
179
  def setter_method?(method)
162
180
  method.to_s[-1, 1] == "="
163
181
  end
164
-
165
- # Called by method_missing() to get an attribute value.
182
+
183
+ ##
184
+ # Called by method_missing() to get an attribute value.
185
+ #
166
186
  def value_getter(method)
167
187
  schema_attribute = self.class.schema_attribute(method)
168
188
  raw_value = attributes[canonical(schema_attribute.name)]
169
189
  schema_attribute.get_value(raw_value)
170
190
  end
171
-
172
- # Called by method_missing() to set an attribute value.
191
+
192
+ ##
193
+ # Called by method_missing() to set an attribute value.
194
+ #
173
195
  def value_setter(method, *args)
174
196
  schema_attribute = self.class.schema_attribute(method.to_s.chop)
175
197
  attr_key = canonical(schema_attribute.name)
@@ -220,10 +242,12 @@ module UCB
220
242
  #
221
243
  def create(args)
222
244
  args[:attributes][:objectclass] = object_classes
223
- net_ldap.add(args) or return false
245
+ result = net_ldap.add(args)
246
+ result or return false
224
247
  find_by_dn(args[:dn])
225
248
  end
226
-
249
+
250
+ ##
227
251
  # Returns entry whose distinguised name is _dn_.
228
252
  def find_by_dn(dn)
229
253
  search(
@@ -232,12 +256,14 @@ module UCB
232
256
  :filter => "objectClass=*"
233
257
  ).first
234
258
  end
235
-
259
+
260
+ ##
236
261
  # Same as #create(), but raises DirectoryNotUpdated on failure.
237
262
  def create!(args)
238
263
  create(args) || raise(DirectoryNotUpdatedException)
239
264
  end
240
-
265
+
266
+ ##
241
267
  # Returns a new Net::LDAP::Filter that is the result of combining
242
268
  # <em>filters</em> using <em>operator</em> (<em>filters</em> is
243
269
  # an +Array+ of Net::LDAP::Filter).
@@ -253,7 +279,8 @@ module UCB
253
279
  def combine_filters(filters, operator = '&')
254
280
  filters.inject{|accum, filter| accum.send(operator, filter)}
255
281
  end
256
-
282
+
283
+ ##
257
284
  # Returns Net::LDAP::Filter. Allows for <em>filter</em> to
258
285
  # be a +Hash+ of :key => value. Filters are combined with "&".
259
286
  #
@@ -271,7 +298,8 @@ module UCB
271
298
  end
272
299
  combine_filters(filters, "&")
273
300
  end
274
-
301
+
302
+ ##
275
303
  # Returns +Array+ of object classes making up this type of LDAP entity.
276
304
  def object_classes
277
305
  @object_classes ||= UCB::LDAP::Schema.schema_hash[entity_name]["objectClasses"]
@@ -281,14 +309,45 @@ module UCB
281
309
  @unique_object_class ||= UCB::LDAP::Schema.schema_hash[entity_name]["uniqueObjectClass"]
282
310
  end
283
311
 
312
+ ##
313
+ # returns an Array of symbols where each symbol is the name of
314
+ # a required attribute for the Entry
315
+ def required_attributes
316
+ required_schema_attributes.keys
317
+ end
318
+
319
+ ##
320
+ # returns Hash of SchemaAttribute objects that are required
321
+ # for the Entry. Each SchemaAttribute object is keyed to the
322
+ # attribute's name.
323
+ #
324
+ # Note: required_schema_attributes will not return aliases, it
325
+ # only returns the original attributes
326
+ #
327
+ # Example:
328
+ # Person.required_schema_attribues[:cn]
329
+ # => <UCB::LDAP::Schema::Attribute:0x11c6b68>
330
+ #
331
+ def required_schema_attributes
332
+ required_atts = schema_attributes_hash.reject { |key, value| !value.required? }
333
+ required_atts.reject do |key, value|
334
+ aliases = value.aliases.map { |a| canonical(a) }
335
+ aliases.include?(key)
336
+ end
337
+ end
338
+
339
+ ##
284
340
  # Returns an +Array+ of Schema::Attribute for the entity.
341
+ #
285
342
  def schema_attributes_array
286
343
  @schema_attributes_array || set_schema_attributes
287
344
  @schema_attributes_array
288
345
  end
289
-
346
+
347
+ ##
290
348
  # Returns as +Hash+ whose keys are the canonical attribute names
291
349
  # and whose values are the corresponding Schema::Attributes.
350
+ #
292
351
  def schema_attributes_hash
293
352
  @schema_attributes_hash || set_schema_attributes
294
353
  @schema_attributes_hash
@@ -298,7 +357,8 @@ module UCB
298
357
  schema_attributes_hash[canonical(attribute_name)] ||
299
358
  raise(BadAttributeNameException, "'#{attribute_name}' is not a recognized attribute name")
300
359
  end
301
-
360
+
361
+ ##
302
362
  # Returns Array of UCB::LDAP::Entry for entries matching _args_.
303
363
  # When called from a subclass, returns Array of subclass instances.
304
364
  #
@@ -325,27 +385,35 @@ module UCB
325
385
  end
326
386
  results
327
387
  end
328
-
388
+
389
+ ##
329
390
  # Returns the canonical representation of a symbol or string so
330
391
  # we can look up attributes in a number of ways.
392
+ #
331
393
  def canonical(string_or_symbol)
332
394
  string_or_symbol.to_s.downcase.to_sym
333
395
  end
334
-
396
+
397
+ ##
335
398
  # Returns underlying Net::LDAP instance.
399
+ #
336
400
  def net_ldap #:nodoc:
337
401
  UCB::LDAP.net_ldap
338
402
  end
339
403
 
340
404
  private unless $TESTING
341
-
405
+
406
+ ##
342
407
  # Schema entity name. Set in each subclass.
408
+ #
343
409
  def entity_name
344
410
  @entity_name
345
411
  end
346
-
412
+
413
+ ##
347
414
  # Want an array of Schema::Attributes as well as a hash
348
415
  # of all possible variations on a name pointing to correct array element.
416
+ #
349
417
  def set_schema_attributes
350
418
  @schema_attributes_array = []
351
419
  @schema_attributes_hash = {}
@@ -360,10 +428,12 @@ module UCB
360
428
  raise "Error loading schema attributes for entity_name '#{entity_name}'"
361
429
  end
362
430
 
431
+ ##
363
432
  # Returns tree base for LDAP searches. Subclasses each have
364
433
  # their own value.
365
434
  #
366
435
  # Can be overridden in #search by passing in a <tt>:base</tt> parm.
436
+ ##
367
437
  def tree_base
368
438
  @tree_base
369
439
  end