activeldap 4.0.5 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +3 -1
  3. data/doc/text/development.md +26 -0
  4. data/doc/text/{news.textile → news.md} +451 -241
  5. data/doc/text/{rails.textile → rails.md} +44 -33
  6. data/doc/text/{tutorial.textile → tutorial.md} +177 -185
  7. data/lib/active_ldap/adapter/base.rb +40 -17
  8. data/lib/active_ldap/adapter/jndi.rb +21 -9
  9. data/lib/active_ldap/adapter/jndi_connection.rb +83 -20
  10. data/lib/active_ldap/adapter/ldap.rb +50 -28
  11. data/lib/active_ldap/adapter/ldap_ext.rb +32 -13
  12. data/lib/active_ldap/adapter/net_ldap.rb +26 -24
  13. data/lib/active_ldap/associations.rb +5 -5
  14. data/lib/active_ldap/attribute_methods/before_type_cast.rb +1 -1
  15. data/lib/active_ldap/attribute_methods/dirty.rb +4 -7
  16. data/lib/active_ldap/attribute_methods/query.rb +1 -1
  17. data/lib/active_ldap/attribute_methods/read.rb +5 -1
  18. data/lib/active_ldap/attribute_methods/write.rb +1 -1
  19. data/lib/active_ldap/attribute_methods.rb +1 -2
  20. data/lib/active_ldap/base.rb +61 -14
  21. data/lib/active_ldap/callbacks.rb +7 -8
  22. data/lib/active_ldap/configuration.rb +27 -3
  23. data/lib/active_ldap/connection.rb +4 -22
  24. data/lib/active_ldap/distinguished_name.rb +1 -1
  25. data/lib/active_ldap/human_readable.rb +5 -4
  26. data/lib/active_ldap/operations.rb +24 -4
  27. data/lib/active_ldap/persistence.rb +3 -2
  28. data/lib/active_ldap/populate.rb +5 -3
  29. data/lib/active_ldap/railties/controller_runtime.rb +1 -2
  30. data/lib/active_ldap/schema/syntaxes.rb +8 -4
  31. data/lib/active_ldap/validations.rb +12 -4
  32. data/lib/active_ldap/version.rb +1 -1
  33. data/lib/active_ldap.rb +0 -7
  34. data/po/en/active-ldap.po +2 -2
  35. data/po/ja/active-ldap.po +3 -3
  36. data/test/add-phonetic-attribute-options-to-slapd.ldif +3 -3
  37. data/test/al-test-utils.rb +125 -38
  38. data/test/command.rb +13 -16
  39. data/test/enable-dynamic-groups.ldif +22 -0
  40. data/test/enable-start-tls.ldif +27 -0
  41. data/test/run-test.rb +0 -4
  42. data/test/test_base.rb +223 -22
  43. data/test/test_base_per_instance.rb +33 -1
  44. data/test/test_callback.rb +10 -8
  45. data/test/test_connection.rb +4 -0
  46. data/test/test_connection_per_class.rb +34 -0
  47. data/test/test_dn.rb +7 -0
  48. data/test/test_entry.rb +1 -0
  49. data/test/test_find.rb +14 -3
  50. data/test/test_supported_control.rb +1 -1
  51. data/test/test_syntax.rb +5 -0
  52. data/test/test_validation.rb +28 -15
  53. metadata +23 -24
  54. data/README.textile +0 -141
  55. data/doc/text/development.textile +0 -54
  56. data/lib/active_ldap/timeout.rb +0 -75
  57. data/lib/active_ldap/timeout_stub.rb +0 -17
@@ -1,17 +1,18 @@
1
- h1. Tutorial
1
+ # Tutorial
2
2
 
3
- h2. Introduction
3
+ ## Introduction
4
4
 
5
- ActiveLdap is a novel way of interacting with LDAP. Most interaction with
6
- LDAP is done using clunky LDIFs, web interfaces, or with painful APIs that
7
- required a thick reference manual nearby. ActiveLdap aims to fix that.
8
- Inspired by "ActiveRecord":http://activerecord.rubyonrails.org, ActiveLdap provides an
9
- object oriented interface to LDAP entries.
5
+ ActiveLdap is a novel way of interacting with LDAP. Most interaction
6
+ with LDAP is done using clunky LDIFs, web interfaces, or with painful
7
+ APIs that required a thick reference manual nearby. ActiveLdap aims to
8
+ fix that. Inspired by [Active
9
+ Record](https://rubygems.org/gems/activerecord), ActiveLdap provides
10
+ an object oriented interface to LDAP entries.
10
11
 
11
12
  The target audience is system administrators and LDAP users everywhere that
12
13
  need quick, clean access to LDAP in Ruby.
13
14
 
14
- h3. What's LDAP?
15
+ ### What's LDAP?
15
16
 
16
17
  LDAP stands for "Lightweight Directory Access Protocol." Basically this means
17
18
  that it is the protocol used for accessing LDAP servers. LDAP servers
@@ -23,10 +24,10 @@ authorization server for Unix systems. (Unfortunately, I've yet to try this
23
24
  against Microsoft's ActiveDirectory, despite what the name implies.)
24
25
 
25
26
  Further reading:
26
- * "RFC1777":http://www.faqs.org/rfcs/rfc1777.html - Lightweight Directory Access Protocol
27
- * "OpenLDAP":http://www.openldap.org
27
+ * [RFC1777](https://tools.ietf.org/html/rfc1777) - Lightweight Directory Access Protocol
28
+ * [OpenLDAP](https://www.openldap.org)
28
29
 
29
- h3. So why use ActiveLdap?
30
+ ### So why use ActiveLdap?
30
31
 
31
32
  Using LDAP directly (even with the excellent Ruby/LDAP), leaves you bound to
32
33
  the world of the predefined LDAP API. While this API is important for many
@@ -35,70 +36,68 @@ arrays of LDAP.mod entries make code harder to read, less intuitive, and just
35
36
  less fun to write. Hopefully, ActiveLdap will remedy all of these
36
37
  problems!
37
38
 
38
- h2. Getting Started
39
+ ## Getting Started
39
40
 
40
- h3. Requirements
41
+ ### Requirements
41
42
 
42
- * A Ruby implementation: "Ruby":http://www.ruby-lang.org 1.8.x, 1.9.1 or "JRuby":http://jruby.codehaus.org/
43
- * A LDAP library: "Ruby/LDAP":http://code.google.com/p/ruby-activeldap/wiki/RubyLDAP (for Ruby), "Net::LDAP":http://rubyforge.org/projects/net-ldap/ (for Ruby or JRuby) or JNDI (for JRuby)
44
- * A LDAP server: "OpenLDAP":http://www.openldap.org, etc
45
- ** Your LDAP server must allow root_dse queries to allow for schema queries
43
+ * A Ruby implementation: [Ruby](https://www.ruby-lang.org) or [JRuby](https://www.jruby.org/)
44
+ * A LDAP library: [Ruby/LDAP](https://rubygems.org/gems/ruby-ldap) (for Ruby), [Net::LDAP](https://rubygems.org/gems/net-ldap) (for Ruby or JRuby) or JNDI (for JRuby)
45
+ * A LDAP server: [OpenLDAP](https://www.openldap.org/), etc
46
+ * Your LDAP server must allow `root_dse` queries to allow for schema queries
46
47
 
47
- h3. Installation
48
+ ### Installation
48
49
 
49
50
  Assuming all the requirements are installed, you can install by gem.
50
51
 
51
- <pre>
52
- !!!plain
52
+ ```console
53
53
  # gem install activeldap
54
- </pre>
54
+ ```
55
55
 
56
56
  Now as a quick test, you can run:
57
57
 
58
- <pre>
59
- $ irb -rubygems
58
+ ```console
59
+ $ irb
60
60
  irb> require 'active_ldap'
61
61
  => true
62
62
  irb> exit
63
- </pre>
63
+ ```
64
64
 
65
65
  If the require returns false or an exception is raised, there has been a
66
- problem with the installation. You may need to customize what setup.rb does on
67
- install.
66
+ problem with the installation.
68
67
 
69
- h2. Usage
68
+ ## Usage
70
69
 
71
70
  This section covers using ActiveLdap from writing extension classes to
72
71
  writing applications that use them.
73
72
 
74
73
  Just to give a taste of what's to come, here is a quick example using irb:
75
74
 
76
- <pre>
75
+ ```text
77
76
  irb> require 'active_ldap'
78
- </pre>
77
+ ```
79
78
 
80
79
  Call setup_connection method for connect to LDAP server. In this case, LDAP server
81
80
  is localhost, and base of LDAP tree is "dc=dataspill,dc=org".
82
81
 
83
- <pre>
82
+ ```text
84
83
  irb> ActiveLdap::Base.setup_connection :host => 'localhost', :base => 'dc=dataspill,dc=org'
85
- </pre>
84
+ ```
86
85
 
87
86
  Here's an extension class that maps to the LDAP Group objects:
88
87
 
89
- <pre>
88
+ ```text
90
89
  irb> class Group < ActiveLdap::Base
91
90
  irb* ldap_mapping
92
91
  irb* end
93
- </pre>
92
+ ```
94
93
 
95
- In the above code, Group class handles sub tree of ou=Groups
96
- tha is :base value specified by setup_connection. A instance
97
- of Group class represents a LDAP object under ou=Gruops.
94
+ In the above code, Group class handles sub tree of `ou=Groups`
95
+ that is `:base` value specified by setup_connection. A instance
96
+ of Group class represents a LDAP object under `ou=Groups`.
98
97
 
99
98
  Here is the Group class in use:
100
99
 
101
- <pre>
100
+ ```text
102
101
  # Get all group names
103
102
  irb> all_groups = Group.find(:all, '*').collect {|group| group.cn}
104
103
  => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
@@ -114,48 +113,47 @@ irb> group.cn
114
113
  # Get gid_number of the develop group
115
114
  irb> group.gid_number
116
115
  => "1003"
117
- </pre>
116
+ ```
118
117
 
119
118
  That's it! No let's get back in to it.
120
119
 
121
- h3. Extension Classes
120
+ ### Extension Classes
122
121
 
123
122
  Extension classes are classes that are subclassed from ActiveLdap::Base. They
124
123
  are used to represent objects in your LDAP server abstractly.
125
124
 
126
- h4. Why do I need them?
125
+ #### Why do I need them?
127
126
 
128
127
  Extension classes are what make ActiveLdap "active"! They do all the
129
128
  background work to make easy-to-use objects by mapping the LDAP object's
130
129
  attributes on to a Ruby class.
131
130
 
132
131
 
133
- h4. Special Methods
132
+ #### Special Methods
134
133
 
135
134
  I will briefly talk about each of the methods you can use when defining an
136
135
  extension class. In the above example, I only made one special method call
137
136
  inside the Group class. More than likely, you will want to more than that.
138
137
 
139
- h5. ldap_mapping
138
+ ##### `ldap_mapping`
140
139
 
141
140
  ldap_mapping is the only required method to setup an extension class for use
142
141
  with ActiveLdap. It must be called inside of a subclass as shown above.
143
142
 
144
143
  Below is a much more realistic Group class:
145
144
 
146
- <pre>
145
+ ```ruby
147
146
  class Group < ActiveLdap::Base
148
147
  ldap_mapping :dn_attribute => 'cn',
149
148
  :prefix => 'ou=Groups', :classes => ['top', 'posixGroup'],
150
149
  :scope => :one
151
150
  end
152
- </pre>
151
+ ```
153
152
 
154
153
  As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
155
154
  my LDAP tree looks something like this:
156
155
 
157
- <pre>
158
- !!!plain
156
+ ```text
159
157
  * dc=dataspill,dc=org
160
158
  |- ou=People,dc=dataspill,dc=org
161
159
  |+ ou=Groups,dc=dataspill,dc=org
@@ -163,26 +161,25 @@ my LDAP tree looks something like this:
163
161
  |- cn=develop,ou=Groups,dc=dataspill,dc=org
164
162
  |- cn=root,ou=Groups,dc=dataspill,dc=org
165
163
  |- ...
166
- </pre>
164
+ ```
167
165
 
168
166
  Under ou=People I store user objects, and under ou=Groups, I store group
169
- objects. What |ldap_mapping| has done is mapped the class in to the LDAP tree
170
- abstractly. With the given :dn_attributes and :prefix, it will only work for
171
- entries under ou=Groups,dc=dataspill,dc=org using the primary attribute 'cn'
167
+ objects. What `ldap_mapping` has done is mapped the class in to the LDAP tree
168
+ abstractly. With the given `:dn_attributes` and `:prefix`, it will only work for
169
+ entries under `ou=Groups,dc=dataspill,dc=org` using the primary attribute 'cn'
172
170
  as the beginning of the distinguished name.
173
171
 
174
172
  Just for clarity, here's how the arguments map out:
175
173
 
176
- <pre>
177
- !!!plain
174
+ ```text
178
175
  cn=develop,ou=Groups,dc=dataspill,dc=org
179
176
  ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
180
177
  :dn_attribute | |
181
178
  :prefix |
182
179
  :base from setup_connection
183
- </pre>
180
+ ```
184
181
 
185
- :scope tells ActiveLdap to only search under ou=Groups, and not to look deeper
182
+ `:scope` tells ActiveLdap to only search under ou=Groups, and not to look deeper
186
183
  for dn_attribute matches.
187
184
  (e.g. cn=develop,ou=DevGroups,ou=Groups,dc=dataspill,dc=org)
188
185
  You can choose value from between :sub, :one and :base.
@@ -209,46 +206,45 @@ case, it would be 'ou=Groups'.
209
206
  :prefix.
210
207
 
211
208
 
212
- h5. belongs_to
209
+ ##### `belongs_to`
213
210
 
214
211
  This method allows an extension class to make use of other extension classes
215
212
  tying objects together across the LDAP tree. Often, user objects will be
216
213
  members of, or belong_to, Group objects.
217
214
 
218
- <pre>
219
- !!!plain
215
+ ```text
220
216
  * dc=dataspill,dc=org
221
217
  |+ ou=People,dc=dataspill,dc=org
222
218
  \
223
219
  |- uid=drewry,ou=People,dc=dataspill,dc=org
224
220
  |- ou=Groups,dc=dataspill,dc=org
225
- </pre>
221
+ ```
226
222
 
227
223
 
228
224
  In the above tree, one such example would be user 'drewry' who is a part of the
229
225
  group 'develop'. You can see this by looking at the 'memberUid' field of 'develop'.
230
226
 
231
- <pre>
227
+ ```text
232
228
  irb> develop = Group.find('develop')
233
229
  => ...
234
230
  irb> develop.memberUid
235
231
  => ['drewry', 'builder']
236
- </pre>
232
+ ```
237
233
 
238
234
  If we look at the LDAP entry for 'drewry', we do not see any references to
239
235
  group 'develop'. In order to remedy that, we can use belongs_to
240
236
 
241
- <pre>
237
+ ```text
242
238
  irb> class User < ActiveLdap::Base
243
239
  irb* ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People', :classes => ['top','account']
244
240
  irb* belongs_to :groups, :class_name => 'Group', :many => 'memberUid', :foreign_key => 'uid'
245
241
  irb* end
246
- </pre>
242
+ ```
247
243
 
248
244
  Now, class User will have a method called 'groups' which will retrieve all
249
245
  Group objects that a user is in.
250
246
 
251
- <pre>
247
+ ```text
252
248
  irb> me = User.find('drewry')
253
249
  irb> me.groups
254
250
  => #<ActiveLdap::Association::BelongsToMany...> # Enumerable object
@@ -258,22 +254,22 @@ irb> me.groups.each { |group| p group.cn };nil
258
254
  "develop"
259
255
  => nil
260
256
  (Note: nil is just there to make the output cleaner...)
261
- </pre>
257
+ ```
262
258
 
263
259
  TIP: If you weren't sure what the distinguished name attribute was for Group,
264
260
  you could also do the following:
265
261
 
266
- <pre>
262
+ ```text
267
263
  irb> me.groups.each { |group| p group.id };nil
268
264
  "cdrom"
269
265
  "audio"
270
266
  "develop"
271
267
  => nil
272
- </pre>
268
+ ```
273
269
 
274
270
  Now let's talk about the arguments of belongs_to. We use the following code that extends Group group a bit for explain:
275
271
 
276
- <pre>
272
+ ```ruby
277
273
  class User < ActiveLdap::Base
278
274
  ldap_mapping :dn_attribute => 'uid', :prefix => 'People', :classes => ['top','account']
279
275
 
@@ -285,42 +281,42 @@ class User < ActiveLdap::Base
285
281
  belongs_to :groups, :foreign_key => 'uid',
286
282
  :class_name => 'Group', :many => 'memberUid',
287
283
  end
288
- </pre>
284
+ ```
289
285
 
290
286
  The first argument is the name of the method you wish to create. In this case, we created a method called primary_group and groups using the symbol :primary_group and :groups. The next collection of arguments are actually a Hash (as with ldap_mapping).
291
287
 
292
- :foreign_key tells belongs_to what attribute Group objects have that match the related object's attribute. If :foreign_key is left off of the argument list, it is assumed to be the dn_attribute.
288
+ `:foreign_key` tells `belongs_to` what attribute Group objects have that match the related object's attribute. If `:foreign_key` is left off of the argument list, it is assumed to be the dn_attribute.
293
289
 
294
290
  In the example, uid is used for :foreign_key. It may confuse you.
295
291
 
296
- ActiveLdap uses :foreign_key as "own attribute name". So it
297
- may not be "foreign key". You can consider :foreign_key just
292
+ ActiveLdap uses `:foreign_key` as "own attribute name". So it
293
+ may not be "foreign key". You can consider `:foreign_key` just
298
294
  as a relation key.
299
295
 
300
- :primary_key is treated as "related object's attribute name"
296
+ `:primary_key` is treated as "related object's attribute name"
301
297
  as we discussed later.
302
298
 
303
- :class_name should be a string that has the name of a class
299
+ `:class_name` should be a string that has the name of a class
304
300
  you've already included. If your class is inside of a module,
305
301
  be sure to put the whole name, e.g.
306
- @:class_name => "MyLdapModule::Group"@.
302
+ `:class_name => "MyLdapModule::Group"`.
307
303
 
308
- :many and :primary_key are similar. Both of them specifies attribute name of related object specified by :foreign_key. Those values are attribute name that can be used by object of class specified by :class_name.
304
+ `:many` and `:primary_key` are similar. Both of them specifies attribute name of related object specified by `:foreign_key`. Those values are attribute name that can be used by object of class specified by `:class_name`.
309
305
 
310
- Relation is resolved by searching entries of :class_name class with :foreign_key attribute value. Search target attribute for it is :primary_key or :many. primary_group method in the above example searches Group objects with User object's gidNumber value as Group object's gidNumber value. Matched Group objects are belonged objects.
306
+ Relation is resolved by searching entries of `:class_name` class with `:foreign_key` attribute value. Search target attribute for it is `:primary_key` or `:many`. primary_group method in the above example searches Group objects with User object's gidNumber value as Group object's gidNumber value. Matched Group objects are belonged objects.
311
307
 
312
- :parimary_key is used for an object just belongs to an object. The first matched object is treated as beloned object.
308
+ `:parimary_key` is used for an object just belongs to an object. The first matched object is treated as beloned object.
313
309
 
314
- :many is used for an object belongs to many objects. All of matched objects are treated as belonged objects.
310
+ `:many` is used for an object belongs to many objects. All of matched objects are treated as belonged objects.
315
311
 
316
- h5. has_many
312
+ ##### `has_many`
317
313
 
318
314
  This method is the opposite of belongs_to. Instead of checking other objects in
319
315
  other parts of the LDAP tree to see if you belong to them, you have multiple
320
316
  objects from other trees listed in your object. To show this, we can just
321
317
  invert the example from above:
322
318
 
323
- <pre>
319
+ ```ruby
324
320
  class Group < ActiveLdap::Base
325
321
  ldap_mapping :dn_attribute => 'cn', :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
326
322
 
@@ -332,104 +328,104 @@ class Group < ActiveLdap::Base
332
328
  has_many :members, :wrap => "memberUid",
333
329
  :class_name => "User", :primary_key => 'uid'
334
330
  end
335
- </pre>
331
+ ```
336
332
 
337
333
  Now we can see that group develop has user 'drewry' as a member, and it can
338
- even return all responses in object form just like belongs_to methods.
334
+ even return all responses in object form just like `belongs_to` methods.
339
335
 
340
- <pre>
336
+ ```text
341
337
  irb> develop = Group.find('develop')
342
338
  => ...
343
339
  irb> develop.members
344
340
  => #<ActiveLdap::Association::HasManyWrap:..> # Enumerable object
345
341
  irb> develop.members.map{|member| member.id}
346
342
  => ["drewry", "builder"]
347
- </pre>
343
+ ```
348
344
 
349
- The arguments for has_many follow the exact same idea that belongs_to's
345
+ The arguments for `has_many` follow the exact same idea that `belongs_to`'s
350
346
  arguments followed. :wrap's contents are used to search for matching
351
- :primary_key content. If :primary_key is not specified, it defaults to the
352
- dn_attribute of the specified :class_name.
347
+ `:primary_key` content. If `:primary_key` is not specified, it defaults to the
348
+ dn_attribute of the specified `:class_name`.
353
349
 
354
- h3. Using these new classes
350
+ ### Using these new classes
355
351
 
356
352
  These new classes have many method calls. Many of them are automatically
357
353
  generated to provide access to the LDAP object's attributes. Other were defined
358
- during class creation by special methods like belongs_to. There are a few other
354
+ during class creation by special methods like `belongs_to`. There are a few other
359
355
  methods that do not fall in to these categories.
360
356
 
361
- h4. .find
357
+ #### `.find`
362
358
 
363
- .find is a class method that is accessible from
359
+ `.find` is a class method that is accessible from
364
360
  any subclass of Base that has 'ldap_mapping' called. When
365
- called .first(:first) returns the first match of the given class.
361
+ called `.first(:first)` returns the first match of the given class.
366
362
 
367
- <pre>
363
+ ```text
368
364
  irb> Group.find(:first, 'deve*").cn
369
365
  => "develop"
370
- </pre>
366
+ ```
371
367
 
372
368
  In this simple example, Group.find took the search string of 'deve*' and
373
369
  searched for the first match in Group where the dn_attribute matched the
374
370
  query. This is the simplest example of .find.
375
371
 
376
- <pre>
372
+ ```text
377
373
  irb> Group.find(:all).collect {|group| group.cn}
378
374
  => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
379
- </pre>
375
+ ```
380
376
 
381
377
  Here .find(:all) returns all matches to the same query. Both .find(:first) and
382
378
  .find(:all) also can take more expressive arguments:
383
379
 
384
- <pre>
380
+ ```text
385
381
  irb> Group.find(:all, :attribute => 'gidNumber', :value => '1003').collect {|group| group.cn}
386
382
  => ["develop"]
387
- </pre>
383
+ ```
388
384
 
389
385
  So it is pretty clear what :attribute and :value do - they are used to query as
390
- :attribute=:value.
386
+ `:attribute=:value`.
391
387
 
392
388
  If :attribute is unspecified, it defaults to the dn_attribute.
393
389
 
394
390
  It is also possible to override :attribute and :value by specifying :filter. This
395
391
  argument allows the direct specification of a LDAP filter to retrieve objects by.
396
392
 
397
- h5. Using the :filter option
393
+ ##### Using the :filter option
398
394
 
399
395
  The filter option lets you pass in an LDAP query string.
400
396
  For example retrieving all groups with cn which starts with @'dev'@ and has @guid@ == 1:
401
397
 
402
- <pre>
398
+ ```text
403
399
  irb> Group.find(:all, :filter => '(&(cn=dev*)(guid=1))').collect {|group| group.cn}
404
400
  => ["develop"]
405
- </pre>
401
+ ```
406
402
 
407
403
  It also allows a hash like sintax (sparing you the need to write the query by hand ):
408
404
 
409
- <pre>
405
+ ```text
410
406
  irb> Group.find(:all, :filter => {:cn => 'dev*', :guid => 1 }).collect {|group| group.cn}
411
407
  => ["develop", "developers", "sys", "sysadmin"]
412
- </pre>
408
+ ```
413
409
 
414
410
  You can build complex queries combining the hash syntax with arrays and @:or@ and @:and@ operators retrieving all users whose name contains 'john' or cn ends with 'smith' or contains 'liz'
415
411
 
416
- <pre>
412
+ ```text
417
413
  irb> User.find(:all, filter: [:or, [:or, { :cn => '*smith', :name => '*john*'} ], { cn: '*liz*' }]).collect(&:cn)
418
414
  => ['john.smith', 'jane.smith', 'john tha ripper', 'liz.taylor', ...]
419
- </pre>
415
+ ```
420
416
 
421
- h4. .search
417
+ #### .search
422
418
 
423
419
  .search is a class method that is accessible from any subclass of Base, and Base.
424
420
  It lets the user perform an arbitrary search against the current LDAP connection
425
421
  irrespetive of LDAP mapping data. This is meant to be useful as a utility method
426
422
  to cover 80% of the cases where a user would want to use Base.connection directly.
427
423
 
428
- <pre>
424
+ ```text
429
425
  irb> Base.search(:base => 'dc=example,dc=com', :filter => '(uid=roo*)',
430
426
  :scope => :sub, :attributes => ['uid', 'cn'])
431
427
  => [["uid=root,ou=People,dc=dataspill,dc=org",{"cn"=>["root"], "uidNumber"=>["0"]}]
432
- </pre>
428
+ ```
433
429
 
434
430
  You can specify the :filter, :base, :scope, and :attributes, but they all have defaults --
435
431
  * :filter defaults to objectClass=* - usually this isn't what you want
@@ -437,41 +433,41 @@ You can specify the :filter, :base, :scope, and :attributes, but they all have d
437
433
  * :scope defaults to :sub. Usually you won't need to change it (You can choose value also from between :one and :base)
438
434
  * :attributes defaults to [] and is the list of attributes you want back. Empty means all of them.
439
435
 
440
- h4. #valid?
436
+ #### #valid?
441
437
 
442
438
  valid? is a method that verifies that all attributes that are required by the
443
439
  objects current objectClasses are populated.
444
440
 
445
- h4. #save
441
+ #### #save
446
442
 
447
443
  save is a method that writes any changes to an object back to the LDAP server.
448
444
  It automatically handles the addition of new objects, and the modification of
449
445
  existing ones.
450
446
 
451
- h4. .exists?
447
+ #### .exists?
452
448
 
453
449
  exists? is a simple method which returns true is the current object exists in
454
450
  LDAP, or false if it does not.
455
451
 
456
- <pre>
452
+ ```text
457
453
  irb> User.exists?("dshadsadsa")
458
454
  => false
459
- </pre>
455
+ ```
460
456
 
461
457
 
462
- h3. ActiveLdap::Base
458
+ ### ActiveLdap::Base
463
459
 
464
460
  ActiveLdap::Base has come up a number of times in the examples above. Every
465
461
  time, it was being used as the super class for the wrapper objects. While this
466
462
  is it's main purpose, it also handles quite a bit more in the background.
467
463
 
468
- h4. What is it?
464
+ #### What is it?
469
465
 
470
466
  ActiveLdap::Base is the heart of ActiveLdap. It does all the schema
471
467
  parsing for validation and attribute-to-method mangling as well as manage the
472
468
  connection to LDAP.
473
469
 
474
- h5. setup_connection
470
+ ##### setup_connection
475
471
 
476
472
  Base.setup_connection takes many (optional) arguments and is used to
477
473
  connect to the LDAP server. Sometimes you will want to connect anonymously
@@ -485,7 +481,7 @@ server allows anonymous binding, and you only want to access data in a
485
481
  read-only fashion, you won't need to call Base.setup_connection. Here
486
482
  is a fully parameterized call:
487
483
 
488
- <pre>
484
+ ```ruby
489
485
  Base.setup_connection(
490
486
  :host => 'ldap.dataspill.org',
491
487
  :port => 389,
@@ -496,7 +492,7 @@ Base.setup_connection(
496
492
  :allow_anonymous => false,
497
493
  :try_sasl => false
498
494
  )
499
- </pre>
495
+ ```
500
496
 
501
497
  There are quite a few arguments, but luckily many of them have safe defaults:
502
498
  * :host defaults to "127.0.0.1".
@@ -550,51 +546,51 @@ in an internal class variable which is used to cache the
550
546
  information without ditching the defaults passed in from
551
547
  configuration.rb
552
548
 
553
- h5. connection
549
+ ##### connection
554
550
 
555
551
  Base.connection returns the ActiveLdap::Connection object.
556
552
 
557
- h3. Exceptions
553
+ ### Exceptions
558
554
 
559
555
  There are a few custom exceptions used in ActiveLdap. They are detailed below.
560
556
 
561
- h4. DeleteError
557
+ #### DeleteError
562
558
 
563
559
  This exception is raised when #delete fails. It will include LDAP error
564
560
  information that was passed up during the error.
565
561
 
566
- h4. SaveError
562
+ #### SaveError
567
563
 
568
564
  This exception is raised when there is a problem in #save updating or creating
569
565
  an LDAP entry. Often the error messages are cryptic. Looking at the server
570
566
  logs or doing an "Wireshark":http://www.wireshark.org dump of the connection will
571
567
  often provide better insight.
572
568
 
573
- h4. AuthenticationError
569
+ #### AuthenticationError
574
570
 
575
571
  This exception is raised during Base.setup_connection if no valid authentication methods
576
572
  succeeded.
577
573
 
578
- h4. ConnectionError
574
+ #### ConnectionError
579
575
 
580
576
  This exception is raised during Base.setup_connection if no valid
581
577
  connection to the LDAP server could be created. Check you
582
578
  Base.setup_connection arguments, and network connectivity! Also check
583
579
  your LDAP server logs to see if it ever saw the request.
584
580
 
585
- h4. ObjectClassError
581
+ #### ObjectClassError
586
582
 
587
583
  This exception is raised when an object class is used that is not defined
588
584
  in the schema.
589
585
 
590
- h3. Others
586
+ ### Others
591
587
 
592
588
  Other exceptions may be raised by the Ruby/LDAP module, or by other subsystems.
593
589
  If you get one of these exceptions and think it should be wrapped, write me an
594
590
  email and let me know where it is and what you expected. For faster results,
595
591
  email a patch!
596
592
 
597
- h3. Putting it all together
593
+ ### Putting it all together
598
594
 
599
595
  Now that all of the components of ActiveLdap have been covered, it's time
600
596
  to put it all together! The rest of this section will show the steps to setup
@@ -603,50 +599,48 @@ above.
603
599
 
604
600
  All of the scripts here are in the package's examples/ directory.
605
601
 
606
- h4. Setting up
602
+ #### Setting up
607
603
 
608
604
  Create directory for scripts.
609
605
 
610
- <pre>
611
- !!!plain
606
+ ```console
612
607
  % mkdir -p ldapadmin/objects
613
- </pre>
608
+ ```
614
609
 
615
610
  In ldapadmin/objects/ create the file user.rb:
616
611
 
617
- <pre>
612
+ ```ruby
618
613
  require 'objects/group'
619
614
 
620
615
  class User < ActiveLdap::Base
621
616
  ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People', :classes => ['person', 'posixAccount']
622
617
  belongs_to :groups, :class_name => 'Group', :many => 'memberUid'
623
618
  end
624
- </pre>
619
+ ```
625
620
 
626
621
  In ldapadmin/objects/ create the file group.rb:
627
622
 
628
- <pre>
623
+ ```ruby
629
624
  class Group < ActiveLdap::Base
630
625
  ldap_mapping :classes => ['top', 'posixGroup'], :prefix => 'ou=Groups'
631
626
  has_many :members, :class_name => "User", :wrap => "memberUid"
632
627
  has_many :primary_members, :class_name => 'User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
633
628
  end
634
- </pre>
629
+ ```
635
630
 
636
631
  Now, we can write some small scripts to do simple management tasks.
637
632
 
638
- h4. Creating LDAP entries
633
+ #### Creating LDAP entries
639
634
 
640
635
  Now let's create a really dumb script for adding users - ldapadmin/useradd:
641
636
 
642
- <pre>
637
+ ```ruby
643
638
  #!/usr/bin/ruby -W0
644
639
 
645
640
  base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
646
641
  $LOAD_PATH << File.join(base, "lib")
647
642
  $LOAD_PATH << File.join(base, "examples")
648
643
 
649
- require 'rubygems'
650
644
  require 'active_ldap'
651
645
  require 'objects/user'
652
646
  require 'objects/group'
@@ -686,20 +680,19 @@ unless user.save
686
680
  puts user.errors.full_messages
687
681
  exit 1
688
682
  end
689
- </pre>
683
+ ```
690
684
 
691
- h4. Managing LDAP entries
685
+ #### Managing LDAP entries
692
686
 
693
687
  Now let's create another dumb script for modifying users - ldapadmin/usermod:
694
688
 
695
- <pre>
689
+ ```ruby
696
690
  #!/usr/bin/ruby -W0
697
691
 
698
692
  base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
699
693
  $LOAD_PATH << File.join(base, "lib")
700
694
  $LOAD_PATH << File.join(base, "examples")
701
695
 
702
- require 'rubygems'
703
696
  require 'active_ldap'
704
697
  require 'objects/user'
705
698
  require 'objects/group'
@@ -736,20 +729,19 @@ unless user.save
736
729
  puts user.errors.full_messages
737
730
  exit 1
738
731
  end
739
- </pre>
732
+ ```
740
733
 
741
- h4. Removing LDAP entries
734
+ #### Removing LDAP entries
742
735
 
743
736
  Now let's create more one for deleting users - ldapadmin/userdel:
744
737
 
745
- <pre>
738
+ ```ruby
746
739
  #!/usr/bin/ruby -W0
747
740
 
748
741
  base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
749
742
  $LOAD_PATH << File.join(base, "lib")
750
743
  $LOAD_PATH << File.join(base, "examples")
751
744
 
752
- require 'rubygems'
753
745
  require 'active_ldap'
754
746
  require 'objects/user'
755
747
  require 'objects/group'
@@ -778,20 +770,20 @@ unless User.exists?(name)
778
770
  end
779
771
 
780
772
  User.destroy(name)
781
- </pre>
773
+ ```
782
774
 
783
- h3. Advanced Topics
775
+ ### Advanced Topics
784
776
 
785
777
  Below are some situation tips and tricks to get the most out of ActiveLdap.
786
778
 
787
779
 
788
- h4. Binary data and other subtypes
780
+ #### Binary data and other subtypes
789
781
 
790
782
  Sometimes, you may want to store attributes with language specifiers, or
791
783
  perhaps in binary form. This is (finally!) fully supported. To do so,
792
784
  follow the examples below:
793
785
 
794
- <pre>
786
+ ```text
795
787
  irb> user = User.new('drewry')
796
788
  => ...
797
789
  # This adds a cn entry in lang-en and whatever the server default is.
@@ -803,7 +795,7 @@ irb> user.cn
803
795
  irb> user.user_certificate = File.read('example.der')
804
796
  => ...
805
797
  irb> user.save
806
- </pre>
798
+ ```
807
799
 
808
800
  So that's a lot to take in. Here's what is going on. I just set the LDAP
809
801
  object's cn to "wad" and cn:lang-en-us to ["wad", "Will Drewry"].
@@ -815,9 +807,9 @@ get wrapped in @{'binary' => value}@ if you don't do it. This keeps your #writes
815
807
  from breaking, and my code from crying. For correctness, I could have easily
816
808
  done the following:
817
809
 
818
- <pre>
810
+ ```text
819
811
  irb> user.user_certificate = {'binary' => File.read('example.der')}
820
- </pre>
812
+ ```
821
813
 
822
814
  You should note that some binary data does not use the binary subtype all the time.
823
815
  One example is jpegPhoto. You can use it as jpegPhoto;binary or just as jpegPhoto.
@@ -829,9 +821,9 @@ LDAP site policy and not by any programmatic means.
829
821
  The only subtypes defined in LDAPv3 are lang-* and binary. These can be nested
830
822
  though:
831
823
 
832
- <pre>
824
+ ```text
833
825
  irb> user.cn = [{'lang-ja' => {'binary' => 'some Japanese'}}]
834
- </pre>
826
+ ```
835
827
 
836
828
  As I understand it, OpenLDAP does not support nested subtypes, but some
837
829
  documentation I've read suggests that Netscape's LDAP server does. I only
@@ -841,7 +833,7 @@ goes!
841
833
 
842
834
  And that pretty much wraps up this section.
843
835
 
844
- h4. Further integration with your environment aka namespacing
836
+ #### Further integration with your environment aka namespacing
845
837
 
846
838
  If you want this to cleanly integrate into your system-wide Ruby include path,
847
839
  you should put your extension classes inside a custom module.
@@ -851,28 +843,28 @@ Example:
851
843
 
852
844
  ./myldap.rb:
853
845
 
854
- <pre>
846
+ ```ruby
855
847
  require 'active_ldap'
856
848
  require 'myldap/user'
857
849
  require 'myldap/group'
858
850
  module MyLDAP
859
851
  end
860
- </pre>
852
+ ```
861
853
 
862
854
  ./myldap/user.rb:
863
855
 
864
- <pre>
856
+ ```ruby
865
857
  module MyLDAP
866
858
  class User < ActiveLdap::Base
867
859
  ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People', :classes => ['top', 'account', 'posixAccount']
868
860
  belongs_to :groups, :class_name => 'MyLDAP::Group', :many => 'memberUid'
869
861
  end
870
862
  end
871
- </pre>
863
+ ```
872
864
 
873
865
  ./myldap/group.rb:
874
866
 
875
- <pre>
867
+ ```ruby
876
868
  module MyLDAP
877
869
  class Group < ActiveLdap::Base
878
870
  ldap_mapping :classes => ['top', 'posixGroup'], :prefix => 'ou=Groups'
@@ -880,54 +872,54 @@ module MyLDAP
880
872
  has_many :primary_members, :class_name => 'MyLDAP::User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
881
873
  end
882
874
  end
883
- </pre>
875
+ ```
884
876
 
885
877
  Now in your local applications, you can call
886
878
 
887
- <pre>
879
+ ```ruby
888
880
  require 'myldap'
889
881
 
890
882
  MyLDAP::Group.new('foo')
891
883
  ...
892
- </pre>
884
+ ```
893
885
 
894
886
  and everything should work well.
895
887
 
896
888
 
897
- h4. force array results for single values
889
+ #### force array results for single values
898
890
 
899
891
  Even though ActiveLdap attempts to maintain programmatic ease by
900
892
  returning Array values only. By specifying 'true' as an argument to
901
893
  any attribute method you will get back a Array if it is single value.
902
894
  Here's an example:
903
895
 
904
- <pre>
896
+ ```text
905
897
  irb> user = User.new('drewry')
906
898
  => ...
907
899
  irb> user.cn(true)
908
900
  => ["Will Drewry"]
909
- </pre>
901
+ ```
910
902
 
911
- h4. Dynamic attribute crawling
903
+ #### Dynamic attribute crawling
912
904
 
913
905
  If you use tab completion in irb, you'll notice that you /can/ tab complete the dynamic
914
906
  attribute methods. You can still see which methods are for attributes using
915
907
  Base#attribute_names:
916
908
 
917
- <pre>
909
+ ```text
918
910
  irb> d = Group.new('develop')
919
911
  => ...
920
912
  irb> d.attribute_names
921
913
  => ["gidNumber", "cn", "memberUid", "commonName", "description", "userPassword", "objectClass"]
922
- </pre>
914
+ ```
923
915
 
924
916
 
925
- h4. Juggling multiple LDAP connections
917
+ #### Juggling multiple LDAP connections
926
918
 
927
919
  In the same vein as the last tip, you can use multiple LDAP connections by
928
920
  per class as follows:
929
921
 
930
- <pre>
922
+ ```text
931
923
  irb> anon_class = Class.new(Base)
932
924
  => ...
933
925
  irb> anon_class.setup_connection
@@ -936,11 +928,11 @@ irb> auth_class = Class.new(Base)
936
928
  => ...
937
929
  irb> auth_class.setup_connection(:password_block => lambda{'mypass'})
938
930
  => ...
939
- </pre>
931
+ ```
940
932
 
941
933
  This can be useful for doing authentication tests and other such tricks.
942
934
 
943
- h4. :try_sasl
935
+ #### :try_sasl
944
936
 
945
937
  If you have the Ruby/LDAP package with the SASL/GSSAPI patch from Ian
946
938
  MacDonald's web site, you can use Kerberos to bind to your LDAP server. By
@@ -949,7 +941,7 @@ default, :try_sasl is false.
949
941
  Also note that you must be using OpenLDAP 2.1.29 or higher to use SASL/GSSAPI
950
942
  due to some bugs in older versions of OpenLDAP.
951
943
 
952
- h4. Don't be afraid! [Internals]
944
+ #### Don't be afraid! [Internals]
953
945
 
954
946
  Don't be afraid to add more methods to the extensions classes and to
955
947
  experiment. That's exactly how I ended up with this package. If you come up
@@ -959,7 +951,7 @@ The internal structure of ActiveLdap::Base, and thus all its subclasses, is
959
951
  still in flux. I've tried to minimize the changes to the overall API, but
960
952
  the internals are still rough around the edges.
961
953
 
962
- h5. Where's ldap_mapping data stored? How can I get to it?
954
+ ##### Where's ldap_mapping data stored? How can I get to it?
963
955
 
964
956
  When you call ldap_mapping, it overwrites several class methods inherited
965
957
  from Base:
@@ -974,7 +966,7 @@ from any new instance methods you define:
974
966
  * Base#required_classes()
975
967
  * Base#dn_attribute()
976
968
 
977
- h5. What else?
969
+ ##### What else?
978
970
 
979
971
  Well if you want to use the LDAP connection for anything, I'd suggest still
980
972
  calling Base.connection to get it. There really aren't many other internals
@@ -987,12 +979,12 @@ any methods you write might need to figure it out. I'd suggest just
987
979
  calling self[attribname] to get the value, but if that's not good enough,
988
980
  you can call look up the stored name by #to_real_attribute_name as follows:
989
981
 
990
- <pre>
982
+ ```text
991
983
  irb> User.find(:first).instance_eval do
992
984
  irb> to_real_attribute_name('commonName')
993
985
  irb> end
994
986
  => 'cn'
995
- </pre>
987
+ ```
996
988
 
997
989
  This tells you the name the attribute is stored in behind the scenes (@data).
998
990
  Again, self[attribname] should be enough for most extensions, but if not,
@@ -1001,16 +993,16 @@ it's probably safe to dabble here.
1001
993
  Also, if you like to look up all aliases for an attribute, you can call the
1002
994
  following:
1003
995
 
1004
- <pre>
996
+ ```text
1005
997
  irb> User.schema.attribute_type 'cn', 'NAME'
1006
998
  => ["cn", "commonName"]
1007
- </pre>
999
+ ```
1008
1000
 
1009
1001
  This is discovered automagically from the LDAP server's schema.
1010
1002
 
1011
- h2. Limitations
1003
+ ## Limitations
1012
1004
 
1013
- h3. Speed
1005
+ ### Speed
1014
1006
 
1015
1007
  Currently, ActiveLdap could be faster. I have some recursive type
1016
1008
  checking going on which slows object creation down, and I'm sure there
@@ -1018,7 +1010,7 @@ are many, many other places optimizations can be done. Feel free
1018
1010
  to send patches, or just hang in there until I can optimize away the
1019
1011
  slowness.
1020
1012
 
1021
- h2. Feedback
1013
+ ## Feedback
1022
1014
 
1023
1015
  Any and all feedback and patches are welcome. I am very excited about this
1024
1016
  package, and I'd like to see it prove helpful to more people than just myself.