ruby-activeldap 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/Manifest.txt +91 -25
- data/README +22 -0
- data/Rakefile +41 -8
- data/TODO +1 -6
- data/examples/config.yaml.example +5 -0
- data/examples/example.der +0 -0
- data/examples/example.jpg +0 -0
- data/examples/groupadd +41 -0
- data/examples/groupdel +35 -0
- data/examples/groupls +49 -0
- data/examples/groupmod +42 -0
- data/examples/lpasswd +55 -0
- data/examples/objects/group.rb +13 -0
- data/examples/objects/ou.rb +4 -0
- data/examples/objects/user.rb +20 -0
- data/examples/ouadd +38 -0
- data/examples/useradd +45 -0
- data/examples/useradd-binary +50 -0
- data/examples/userdel +34 -0
- data/examples/userls +50 -0
- data/examples/usermod +42 -0
- data/examples/usermod-binary-add +47 -0
- data/examples/usermod-binary-add-time +51 -0
- data/examples/usermod-binary-del +48 -0
- data/examples/usermod-lang-add +43 -0
- data/lib/active_ldap.rb +213 -214
- data/lib/active_ldap/adapter/base.rb +461 -0
- data/lib/active_ldap/adapter/ldap.rb +232 -0
- data/lib/active_ldap/adapter/ldap_ext.rb +69 -0
- data/lib/active_ldap/adapter/net_ldap.rb +288 -0
- data/lib/active_ldap/adapter/net_ldap_ext.rb +29 -0
- data/lib/active_ldap/association/belongs_to.rb +3 -1
- data/lib/active_ldap/association/belongs_to_many.rb +5 -6
- data/lib/active_ldap/association/has_many.rb +9 -17
- data/lib/active_ldap/association/has_many_wrap.rb +4 -5
- data/lib/active_ldap/attributes.rb +4 -0
- data/lib/active_ldap/base.rb +201 -56
- data/lib/active_ldap/configuration.rb +11 -1
- data/lib/active_ldap/connection.rb +15 -9
- data/lib/active_ldap/distinguished_name.rb +246 -0
- data/lib/active_ldap/ldap_error.rb +74 -0
- data/lib/active_ldap/object_class.rb +9 -5
- data/lib/active_ldap/schema.rb +50 -9
- data/lib/active_ldap/validations.rb +11 -13
- data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +7 -0
- data/rails/plugin/active_ldap/generators/scaffold_al/templates/ldap.yml +21 -0
- data/rails/plugin/active_ldap/init.rb +10 -4
- data/test/al-test-utils.rb +46 -3
- data/test/run-test.rb +16 -4
- data/test/test-unit-ext/always-show-result.rb +28 -0
- data/test/test-unit-ext/priority.rb +163 -0
- data/test/test_adapter.rb +81 -0
- data/test/test_attributes.rb +8 -1
- data/test/test_base.rb +132 -3
- data/test/test_base_per_instance.rb +14 -3
- data/test/test_connection.rb +19 -0
- data/test/test_dn.rb +161 -0
- data/test/test_find.rb +24 -0
- data/test/test_object_class.rb +15 -2
- data/test/test_schema.rb +108 -1
- metadata +111 -41
- data/lib/active_ldap/adaptor/base.rb +0 -29
- data/lib/active_ldap/adaptor/ldap.rb +0 -466
- data/lib/active_ldap/ldap.rb +0 -113
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/ruby -W0
|
2
|
+
|
3
|
+
base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
4
|
+
$LOAD_PATH << File.join(base, "lib")
|
5
|
+
$LOAD_PATH << File.join(base, "examples")
|
6
|
+
|
7
|
+
require 'active_ldap'
|
8
|
+
require 'objects/user'
|
9
|
+
require 'objects/group'
|
10
|
+
|
11
|
+
argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
|
12
|
+
opts.banner += " USER_NAME CN UID"
|
13
|
+
end
|
14
|
+
|
15
|
+
if argv.size == 3
|
16
|
+
name, cn, uid = argv
|
17
|
+
else
|
18
|
+
$stderr.puts opts
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
pwb = Proc.new do |user|
|
23
|
+
ActiveLdap::Command.read_password("[#{user}] Password: ")
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveLdap::Base.establish_connection(:password_block => pwb,
|
27
|
+
:allow_anonymous => false)
|
28
|
+
|
29
|
+
unless User.exists?(name)
|
30
|
+
$stderr.puts("User #{name} doesn't exist.")
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
user = User.find(name)
|
35
|
+
user.cn = cn
|
36
|
+
user.uid_number = uid
|
37
|
+
user.gid_number = uid
|
38
|
+
|
39
|
+
if user.classes.include?('strongAuthenticationUser')
|
40
|
+
user.user_certificate = nil
|
41
|
+
user.remove_class('strongAuthenticationUser')
|
42
|
+
end
|
43
|
+
|
44
|
+
unless user.save
|
45
|
+
puts "failed"
|
46
|
+
puts user.errors.full_messages
|
47
|
+
exit 1
|
48
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/ruby -W0
|
2
|
+
|
3
|
+
base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
4
|
+
$LOAD_PATH << File.join(base, "lib")
|
5
|
+
$LOAD_PATH << File.join(base, "examples")
|
6
|
+
|
7
|
+
require 'active_ldap'
|
8
|
+
require 'objects/user'
|
9
|
+
require 'objects/group'
|
10
|
+
|
11
|
+
argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
|
12
|
+
opts.banner += " USER_NAME CN UID"
|
13
|
+
end
|
14
|
+
|
15
|
+
if argv.size == 3
|
16
|
+
name, cn, uid = argv
|
17
|
+
else
|
18
|
+
$stderr.puts opts
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
pwb = Proc.new do |user|
|
23
|
+
ActiveLdap::Command.read_password("[#{user}] Password: ")
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveLdap::Base.establish_connection(:password_block => pwb,
|
27
|
+
:allow_anonymous => false)
|
28
|
+
|
29
|
+
unless User.exists?(name)
|
30
|
+
$stderr.puts("User #{name} doesn't exist.")
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
user = User.find(name)
|
35
|
+
user.cn = [cn, {'lang-en-us' => cn}]
|
36
|
+
user.uid_number = uid
|
37
|
+
user.gid_number = uid
|
38
|
+
|
39
|
+
unless user.save
|
40
|
+
puts "failed"
|
41
|
+
puts user.errors.full_messages
|
42
|
+
exit 1
|
43
|
+
end
|
data/lib/active_ldap.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
|
-
# = Ruby/ActiveLdap
|
2
|
+
# = Ruby/ActiveLdap
|
3
3
|
#
|
4
4
|
# "Ruby/ActiveLdap" Copyright (C) 2004,2005 Will Drewry mailto:will@alum.bu.edu
|
5
5
|
#
|
6
6
|
# == Introduction
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# Ruby/ActiveLdap is a novel way of interacting with LDAP. Most interaction with
|
9
9
|
# LDAP is done using clunky LDIFs, web interfaces, or with painful APIs that
|
10
10
|
# required a thick reference manual nearby. Ruby/ActiveLdap aims to fix that.
|
11
11
|
# Inspired by ActiveRecord[http://activerecord.rubyonrails.org], Ruby/ActiveLdap provides an
|
12
12
|
# object oriented interface to LDAP entries.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# The target audience is system administrators and LDAP users everywhere that
|
15
15
|
# need quick, clean access to LDAP in Ruby.
|
16
|
-
#
|
16
|
+
#
|
17
17
|
# === What's LDAP?
|
18
|
-
#
|
18
|
+
#
|
19
19
|
# LDAP stands for "Lightweight Directory Access Protocol." Basically this means
|
20
20
|
# that it is the protocol used for accessing LDAP servers. LDAP servers
|
21
21
|
# lightweight directories. An LDAP server can contain anything from a simple
|
@@ -24,32 +24,32 @@
|
|
24
24
|
# assume some familiarity with using LDAP as a centralized authentication and
|
25
25
|
# authorization server for Unix systems. (Unfortunately, I've yet to try this
|
26
26
|
# against Microsoft's ActiveDirectory, despite what the name implies.)
|
27
|
-
#
|
28
|
-
# Further reading:
|
27
|
+
#
|
28
|
+
# Further reading:
|
29
29
|
# * RFC1777[http://www.faqs.org/rfcs/rfc1777.html] - Lightweight Directory Access Protocol
|
30
30
|
# * OpenLDAP[http://www.openldap.org]
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# === So why use Ruby/ActiveLdap?
|
33
|
-
#
|
33
|
+
#
|
34
34
|
# Well if you like to fumble around in the dark, dank innards of LDAP, you can
|
35
35
|
# quit reading now. However, if you'd like a cleaner way to integrate LDAP in to
|
36
36
|
# your existing code, hopefully that's why you'll want to use Ruby/ActiveLdap.
|
37
|
-
#
|
37
|
+
#
|
38
38
|
# Using LDAP directly (even with the excellent Ruby/LDAP), leaves you bound to
|
39
39
|
# the world of the predefined LDAP API. While this API is important for many
|
40
40
|
# reasons, having to extract code out of LDAP search blocks and create huge
|
41
41
|
# arrays of LDAP.mod entries make code harder to read, less intuitive, and just
|
42
42
|
# less fun to write. Hopefully, Ruby/ActiveLdap will remedy all of these
|
43
43
|
# problems!
|
44
|
-
#
|
44
|
+
#
|
45
45
|
# == Getting Started
|
46
|
-
#
|
46
|
+
#
|
47
47
|
# Ruby/ActiveLdap does have some overhead when you get started. You must not
|
48
48
|
# only install the package and all of it's requirements, but you must also make
|
49
49
|
# customizations that will let it work in your environment.
|
50
|
-
#
|
50
|
+
#
|
51
51
|
# === Requirements
|
52
|
-
#
|
52
|
+
#
|
53
53
|
# * Ruby[http://www.ruby-lang.org] 1.8.x
|
54
54
|
# * Ruby/LDAP[http://ruby-ldap.sourceforge.net]
|
55
55
|
# * Log4r[http://log4r.sourceforge.net]
|
@@ -57,134 +57,134 @@
|
|
57
57
|
# * An LDAP server compatible with Ruby/LDAP: OpenLDAP[http://www.openldap.org], etc
|
58
58
|
# - Your LDAP server must allow root_dse queries to allow for schema queries
|
59
59
|
# * Examples also require: Ruby/Password[http://raa.ruby-lang.org/project/ruby-password/]
|
60
|
-
#
|
60
|
+
#
|
61
61
|
# === Installation
|
62
|
-
#
|
62
|
+
#
|
63
63
|
# Assuming all the requirements are installed, you can install by grabbing the latest tgz file from
|
64
64
|
# the download site[http://projects.dataspill.org/libraries/ruby/activeldap/download.html].
|
65
|
-
#
|
65
|
+
#
|
66
66
|
# The following steps will get the Ruby/ActiveLdap installed in no time!
|
67
|
-
#
|
67
|
+
#
|
68
68
|
# $ tar -xzvf ruby-activeldap-current.tgz
|
69
69
|
# $ cd ruby-activeldap-VERSION
|
70
|
-
#
|
70
|
+
#
|
71
71
|
# Edit lib/active_ldap/configuration.rb replacing values to match what will work
|
72
72
|
# with your LDAP servers. Please note that those variables are required, but can
|
73
73
|
# be overridden in any program as detailed later in this document. Also make
|
74
74
|
# sure that "ROOT" stays all upcase.
|
75
|
-
#
|
75
|
+
#
|
76
76
|
# Now run:
|
77
|
-
#
|
77
|
+
#
|
78
78
|
# $ ruby setup.rb config
|
79
79
|
# $ ruby setup.rb setup
|
80
80
|
# $ (as root) ruby setup.rb install
|
81
|
-
#
|
81
|
+
#
|
82
82
|
# Now as a quick test, you can run:
|
83
|
-
#
|
83
|
+
#
|
84
84
|
# $ irb
|
85
85
|
# irb> require 'active_ldap'
|
86
86
|
# => true
|
87
87
|
# irb> exit
|
88
|
-
#
|
88
|
+
#
|
89
89
|
# If the require returns false or an exception is raised, there has been a
|
90
90
|
# problem with the installation. You may need to customize what setup.rb does on
|
91
91
|
# install.
|
92
|
-
#
|
93
|
-
#
|
92
|
+
#
|
93
|
+
#
|
94
94
|
# === Customizations
|
95
|
-
#
|
95
|
+
#
|
96
96
|
# Now that Ruby/ActiveLdap is installed and working, we still have a few more
|
97
97
|
# steps to make it useful for programming.
|
98
|
-
#
|
98
|
+
#
|
99
99
|
# Let's say that you are writing a Ruby program for managing user and group
|
100
100
|
# accounts in LDAP. I will use this as the running example throughout the
|
101
101
|
# document.
|
102
|
-
#
|
102
|
+
#
|
103
103
|
# You will want to make a directory called 'ldapadmin' wherever is convenient. Under this directory,
|
104
104
|
# you'll want to make sure you have a 'lib' directory.
|
105
|
-
#
|
105
|
+
#
|
106
106
|
# $ cd ~
|
107
107
|
# $ mkdir ldapadmin
|
108
108
|
# $ cd ldapadmin
|
109
109
|
# $ mkdir lib
|
110
110
|
# $ cd lib
|
111
|
-
#
|
111
|
+
#
|
112
112
|
# The lib directory is where we'll be making customizations. You can, of course,
|
113
113
|
# make this changes somewhere in Ruby's default search path to make this
|
114
114
|
# accessible to every Ruby scripts. Enough of my babbling, I'm sure you'd like to
|
115
115
|
# know what we're going to put in lib/.
|
116
|
-
#
|
116
|
+
#
|
117
117
|
# We're going to put extension classes in there. What are extension classes you say . . .
|
118
|
-
#
|
119
|
-
#
|
118
|
+
#
|
119
|
+
#
|
120
120
|
# == Usage
|
121
|
-
#
|
121
|
+
#
|
122
122
|
# This section covers using Ruby/ActiveLdap from writing extension classes to
|
123
123
|
# writing applications that use them.
|
124
|
-
#
|
124
|
+
#
|
125
125
|
# Just to give a taste of what's to come, here is a quick example using irb:
|
126
|
-
#
|
126
|
+
#
|
127
127
|
# irb> require 'active_ldap'
|
128
|
-
#
|
128
|
+
#
|
129
129
|
# Here's an extension class that maps to the LDAP Group objects:
|
130
|
-
#
|
130
|
+
#
|
131
131
|
# irb> class Group < ActiveLdap::Base
|
132
132
|
# irb* ldap_mapping
|
133
133
|
# irb* end
|
134
|
-
#
|
134
|
+
#
|
135
135
|
# Here is the Group class in use:
|
136
|
-
#
|
136
|
+
#
|
137
137
|
# irb> all_groups = Group.find(:all, '*').collect {|group| group.cn}
|
138
138
|
# => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
|
139
|
-
#
|
139
|
+
#
|
140
140
|
# irb> group = Group.find("develop")
|
141
141
|
# => #<Group:0x..........>
|
142
|
-
#
|
142
|
+
#
|
143
143
|
# irb> group.members.collect {|member| member.uid}
|
144
144
|
# => ["drewry"]
|
145
|
-
#
|
145
|
+
#
|
146
146
|
# irb> group.cn
|
147
147
|
# => "develop"
|
148
|
-
#
|
148
|
+
#
|
149
149
|
# irb> group.gid_number
|
150
150
|
# => "1003"
|
151
|
-
#
|
151
|
+
#
|
152
152
|
# That's it! No let's get back in to it.
|
153
153
|
#
|
154
154
|
# === Extension Classes
|
155
|
-
#
|
155
|
+
#
|
156
156
|
# Extension classes are classes that are subclassed from ActiveLdap::Base. They
|
157
157
|
# are used to represent objects in your LDAP server abstractly.
|
158
|
-
#
|
158
|
+
#
|
159
159
|
# ==== Why do I need them?
|
160
|
-
#
|
160
|
+
#
|
161
161
|
# Extension classes are what make Ruby/ActiveLdap "active"! They do all the
|
162
162
|
# background work to make easy-to-use objects by mapping the LDAP object's
|
163
163
|
# attributes on to a Ruby class.
|
164
|
-
#
|
165
|
-
#
|
164
|
+
#
|
165
|
+
#
|
166
166
|
# ==== Special Methods
|
167
|
-
#
|
167
|
+
#
|
168
168
|
# I will briefly talk about each of the methods you can use when defining an
|
169
169
|
# extension class. In the above example, I only made one special method call
|
170
170
|
# inside the Group class. More than likely, you will want to more than that.
|
171
|
-
#
|
171
|
+
#
|
172
172
|
# ===== ldap_mapping
|
173
|
-
#
|
173
|
+
#
|
174
174
|
# ldap_mapping is the only required method to setup an extension class for use
|
175
175
|
# with Ruby/ActiveLdap. It must be called inside of a subclass as shown above.
|
176
|
-
#
|
176
|
+
#
|
177
177
|
# Below is a much more realistic Group class:
|
178
|
-
#
|
178
|
+
#
|
179
179
|
# class Group < ActiveLdap::Base
|
180
180
|
# ldap_mapping :dn_attribute => 'cn',
|
181
181
|
# :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
|
182
182
|
# :scope => LDAP::LDAP_SCOPE_ONELEVEL
|
183
183
|
# end
|
184
|
-
#
|
185
|
-
# As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
|
184
|
+
#
|
185
|
+
# As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
|
186
186
|
# my LDAP tree looks something like this:
|
187
|
-
#
|
187
|
+
#
|
188
188
|
# * dc=dataspill,dc=org
|
189
189
|
# |- ou=People,dc=dataspill,dc=org
|
190
190
|
# |+ ou=Groups,dc=dataspill,dc=org
|
@@ -192,24 +192,24 @@
|
|
192
192
|
# |- cn=develop,ou=Groups,dc=dataspill,dc=org
|
193
193
|
# |- cn=root,ou=Groups,dc=dataspill,dc=org
|
194
194
|
# |- ...
|
195
|
-
#
|
195
|
+
#
|
196
196
|
# Under ou=People I store user objects, and under ou=Groups, I store group
|
197
197
|
# objects. What |ldap_mapping| has done is mapped the class in to the LDAP tree
|
198
198
|
# abstractly. With the given :dnattr and :prefix, it will only work for entries
|
199
199
|
# under ou=Groups,dc=dataspill,dc=org using the primary attribute 'cn' as the
|
200
200
|
# beginning of the distinguished name.
|
201
|
-
#
|
201
|
+
#
|
202
202
|
# Just for clarity, here's how the arguments map out:
|
203
|
-
#
|
203
|
+
#
|
204
204
|
# cn=develop,ou=Groups,dc=dataspill,dc=org
|
205
205
|
# ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
|
206
206
|
# :dn_attribute | |
|
207
207
|
# :prefix |
|
208
208
|
# :base from configuration.rb
|
209
|
-
#
|
209
|
+
#
|
210
210
|
# :scope tells ActiveLdap to only search under ou=Groups, and not to look deeper
|
211
211
|
# for dnattr matches. (e.g. cn=develop,ou=DevGroups,ou=Groups,dc=dataspill,dc=org)
|
212
|
-
#
|
212
|
+
#
|
213
213
|
# Something's missing: :classes. :classes is used to tell Ruby/ActiveLdap what
|
214
214
|
# the minimum requirement is when creating a new object. LDAP uses objectClasses
|
215
215
|
# to define what attributes a LDAP object may have. Ruby/ActiveLdap needs to know
|
@@ -222,48 +222,48 @@
|
|
222
222
|
# implementation choices with most LDAP servers, once an object is created, its
|
223
223
|
# structural objectclasses may not be removed (or replaced). Setting a sane default
|
224
224
|
# may help avoid programmer error later.
|
225
|
-
#
|
225
|
+
#
|
226
226
|
# :classes isn't the only optional argument. If :dn_attribute is left off,
|
227
227
|
# it defaults to underscored class name or 'cn'. If :prefix is left off,
|
228
228
|
# it will default to 'ou=PLURALIZED_CLASSNAME'. In this
|
229
229
|
# case, it would be 'ou=Groups'.
|
230
|
-
#
|
230
|
+
#
|
231
231
|
# :classes should be an Array. :dn_attribute should be a String and so should
|
232
232
|
# :prefix.
|
233
|
-
#
|
234
|
-
#
|
233
|
+
#
|
234
|
+
#
|
235
235
|
# ===== belongs_to
|
236
|
-
#
|
236
|
+
#
|
237
237
|
# This method allows an extension class to make use of other extension classes
|
238
238
|
# tying objects together across the LDAP tree. Often, user objects will be
|
239
239
|
# members of, or belong_to, Group objects.
|
240
|
-
#
|
240
|
+
#
|
241
241
|
# * dc=dataspill,dc=org
|
242
242
|
# |+ ou=People,dc=dataspill,dc=org
|
243
243
|
# \
|
244
244
|
# |- uid=drewry,ou=People,dc=dataspill,dc=org
|
245
245
|
# |- ou=Groups,dc=dataspill,dc=org
|
246
|
-
#
|
247
|
-
#
|
246
|
+
#
|
247
|
+
#
|
248
248
|
# In the above tree, one such example would be user 'drewry' who is a part of the
|
249
249
|
# group 'develop'. You can see this by looking at the 'memberUid' field of 'develop'.
|
250
|
-
#
|
250
|
+
#
|
251
251
|
# irb> develop = Group.find('develop')
|
252
252
|
# => ...
|
253
253
|
# irb> develop.memberUid
|
254
254
|
# => ['drewry', 'builder']
|
255
|
-
#
|
255
|
+
#
|
256
256
|
# If we look at the LDAP entry for 'drewry', we do not see any references to
|
257
257
|
# group 'develop'. In order to remedy that, we can use belongs_to
|
258
|
-
#
|
258
|
+
#
|
259
259
|
# irb> class User < ActiveLdap::Base
|
260
260
|
# irb* ldap_mapping :dn_attribute => 'uid', :prefix => 'People', :classes => ['top','account']
|
261
261
|
# irb* belongs_to :groups, :class => 'Group', :many => 'memberUid', :foreign_key => 'uid'
|
262
262
|
# irb* end
|
263
|
-
#
|
263
|
+
#
|
264
264
|
# Now, class User will have a method called 'groups' which will retrieve all
|
265
265
|
# Group objects that a user is in.
|
266
|
-
#
|
266
|
+
#
|
267
267
|
# irb> me = User.find('drewry')
|
268
268
|
# irb> me.groups
|
269
269
|
# => [#<Group:0x000001 ...>, #<Group:0x000002 ...>, ...]
|
@@ -273,16 +273,16 @@
|
|
273
273
|
# "develop"
|
274
274
|
# => nil
|
275
275
|
# (Note: nil is just there to make the output cleaner...)
|
276
|
-
#
|
276
|
+
#
|
277
277
|
# TIP: If you weren't sure what the distinguished name attribute was for Group,
|
278
278
|
# you could also do the following:
|
279
|
-
#
|
279
|
+
#
|
280
280
|
# irb> me.groups.each { |group| p group.id };nil
|
281
281
|
# "cdrom"
|
282
282
|
# "audio"
|
283
283
|
# "develop"
|
284
284
|
# => nil
|
285
|
-
#
|
285
|
+
#
|
286
286
|
# Now let's talk about the arguments. The first argument is the name of the
|
287
287
|
# method you wish to create. In this case, we created a method called groups
|
288
288
|
# using the symbol :groups. The next collection of arguments are actually a Hash
|
@@ -294,78 +294,78 @@
|
|
294
294
|
# should be looked up in Group under the primary key. If :foreign_key is left
|
295
295
|
# off of the argument list, it is assumed to be the dn_attribute. With this in
|
296
296
|
# mind, the above definition could become:
|
297
|
-
#
|
297
|
+
#
|
298
298
|
# irb> class User < ActiveLdap::Base
|
299
299
|
# irb* ldap_mapping :dnattr => 'uid', :prefix => 'People', :classes => ['top','account']
|
300
300
|
# irb* belongs_to :groups, :class => 'Group', :many => 'memberUid'
|
301
301
|
# irb* end
|
302
|
-
#
|
302
|
+
#
|
303
303
|
# In addition, you can do simple membership tests by doing the following:
|
304
|
-
#
|
304
|
+
#
|
305
305
|
# irb> me.groups.member? 'root'
|
306
306
|
# => false
|
307
307
|
# irb> me.groups.member? 'develop'
|
308
308
|
# => true
|
309
|
-
#
|
309
|
+
#
|
310
310
|
# ===== has_many
|
311
|
-
#
|
311
|
+
#
|
312
312
|
# This method is the opposite of belongs_to. Instead of checking other objects in
|
313
313
|
# other parts of the LDAP tree to see if you belong to them, you have multiple
|
314
314
|
# objects from other trees listed in your object. To show this, we can just
|
315
315
|
# invert the example from above:
|
316
|
-
#
|
316
|
+
#
|
317
317
|
# class Group < ActiveLdap::Base
|
318
318
|
# ldap_mapping :dn_attribute => 'cn', :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
|
319
319
|
# has_many :members, :class => "User", :wrap => "memberUid", :primary_key => 'uid'
|
320
320
|
# end
|
321
|
-
#
|
321
|
+
#
|
322
322
|
# Now we can see that group develop has user 'drewry' as a member, and it can
|
323
323
|
# even return all responses in object form just like belongs_to methods.
|
324
|
-
#
|
324
|
+
#
|
325
325
|
# irb> develop = Group.find('develop')
|
326
326
|
# => ...
|
327
327
|
# irb> develop.members
|
328
328
|
# => [#<User:0x000001 ...>, #<User:...>]
|
329
|
-
#
|
330
|
-
#
|
329
|
+
#
|
330
|
+
#
|
331
331
|
# The arguments for has_many follow the exact same idea that belongs_to's
|
332
332
|
# arguments followed. :wrap's contents are used to search for matching
|
333
333
|
# :primary_key content. If :primary_key is not specified, it defaults to the
|
334
334
|
# dn_attribute of the specified :class.
|
335
|
-
#
|
335
|
+
#
|
336
336
|
# === Using these new classes
|
337
|
-
#
|
337
|
+
#
|
338
338
|
# These new classes have many method calls. Many of them are automatically
|
339
339
|
# generated to provide access to the LDAP object's attributes. Other were defined
|
340
340
|
# during class creation by special methods like belongs_to. There are a few other
|
341
341
|
# methods that do not fall in to these categories.
|
342
|
-
#
|
343
|
-
#
|
342
|
+
#
|
343
|
+
#
|
344
344
|
# ==== .find
|
345
|
-
#
|
345
|
+
#
|
346
346
|
# .find is a class method that is accessible from any subclass of Base that has
|
347
347
|
# 'ldap_mapping' called. When called it returns the first match of the given
|
348
348
|
# class.
|
349
|
-
#
|
349
|
+
#
|
350
350
|
# irb> Group.find('*').cn
|
351
351
|
# => "root"
|
352
|
-
#
|
352
|
+
#
|
353
353
|
# In this simple example, Group.find took the search string of 'deve*' and
|
354
354
|
# searched for the first match in Group where the dnattr matched the query. This
|
355
355
|
# is the simplest example of .find.
|
356
|
-
#
|
356
|
+
#
|
357
357
|
# irb> Group.find(:all, '*').collect {|group| group.cn}
|
358
358
|
# => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
|
359
|
-
#
|
359
|
+
#
|
360
360
|
# Here .find(:all) returns all matches to the same query. Both .find and
|
361
361
|
# .find(:all) also can take more expressive arguments:
|
362
|
-
#
|
362
|
+
#
|
363
363
|
# irb> Group.find(:all, :attribute => 'gidNumber', :value => '1003').collect {|group| group.cn}
|
364
364
|
# => ["develop"]
|
365
|
-
#
|
365
|
+
#
|
366
366
|
# So it is pretty clear what :attribute and :value do - they are used to query as
|
367
367
|
# :attribute=:value.
|
368
|
-
#
|
368
|
+
#
|
369
369
|
# If :attribute is unspecified, it defaults to the dn_attribute.
|
370
370
|
#
|
371
371
|
# It is also possible to override :attribute and :value by specifying :filter. This
|
@@ -387,87 +387,83 @@
|
|
387
387
|
# * :attributes defaults to [] and is the list of attributes you want back. Empty means all of them.
|
388
388
|
#
|
389
389
|
# ==== #valid?
|
390
|
-
#
|
390
|
+
#
|
391
391
|
# valid? is a method that verifies that all attributes that are required by the
|
392
392
|
# objects current objectClasses are populated.
|
393
|
-
#
|
393
|
+
#
|
394
394
|
# ==== #save
|
395
|
-
#
|
395
|
+
#
|
396
396
|
# save is a method that writes any changes to an object back to the LDAP server.
|
397
397
|
# It automatically handles the addition of new objects, and the modification of
|
398
398
|
# existing ones.
|
399
|
-
#
|
399
|
+
#
|
400
400
|
# ==== .exists?
|
401
|
-
#
|
401
|
+
#
|
402
402
|
# exists? is a simple method which returns true is the current object exists in
|
403
403
|
# LDAP, or false if it does not.
|
404
|
-
#
|
404
|
+
#
|
405
405
|
# irb> User.exists?("dshadsadsa")
|
406
406
|
# => false
|
407
|
-
#
|
408
|
-
#
|
407
|
+
#
|
408
|
+
#
|
409
409
|
# === ActiveLdap::Base
|
410
|
-
#
|
410
|
+
#
|
411
411
|
# ActiveLdap::Base has come up a number of times in the examples above. Every
|
412
412
|
# time, it was being used as the super class for the wrapper objects. While this
|
413
413
|
# is it's main purpose, it also handles quite a bit more in the background.
|
414
|
-
#
|
414
|
+
#
|
415
415
|
# ==== What is it?
|
416
|
-
#
|
416
|
+
#
|
417
417
|
# ActiveLdap::Base is the heart of Ruby/ActiveLdap. It does all the schema
|
418
418
|
# parsing for validation and attribute-to-method mangling as well as manage the
|
419
419
|
# connection to LDAP.
|
420
|
-
#
|
420
|
+
#
|
421
421
|
# ===== establish_connection
|
422
|
-
#
|
422
|
+
#
|
423
423
|
# Base.establish_connection takes many (optional) arguments and is used to
|
424
424
|
# connect to the LDAP server. Sometimes you will want to connect anonymously
|
425
|
-
# and other times over TLS with user credentials. Base.
|
426
|
-
# all of that for you.
|
427
|
-
#
|
428
|
-
#
|
425
|
+
# and other times over TLS with user credentials. Base.establish_connection is
|
426
|
+
# here to do all of that for you.
|
427
|
+
#
|
428
|
+
#
|
429
429
|
# By default, if you call any subclass of Base, such as Group, it will call
|
430
430
|
# Base.establish_connection() if these is no active LDAP connection. If your
|
431
431
|
# server allows anonymous binding, and you only want to access data in a
|
432
432
|
# read-only fashion, you won't need to call Base.establish_connection. Here
|
433
433
|
# is a fully parameterized call:
|
434
|
-
#
|
435
|
-
# Base.
|
434
|
+
#
|
435
|
+
# Base.establish_connection(
|
436
436
|
# :host => 'ldap.dataspill.org',
|
437
437
|
# :port => 389,
|
438
438
|
# :base => 'dc=dataspill,dc=org',
|
439
|
-
# :bind_format => "uid=%s,ou=People,dc=dataspill,dc=org",
|
440
439
|
# :logger => log4r_obj,
|
441
|
-
# :
|
440
|
+
# :bind_dn => "uid=drewry,ou=People,dc=dataspill,dc=org",
|
442
441
|
# :password_block => Proc.new { 'password12345' },
|
443
442
|
# :allow_anonymous => false,
|
444
443
|
# :try_sasl => false
|
445
444
|
# )
|
446
|
-
#
|
445
|
+
#
|
447
446
|
# There are quite a few arguments, but luckily many of them have safe defaults:
|
448
447
|
# * :host defaults to @@host from configuration.rb waaay back at the setup.rb stage.@
|
449
448
|
# * :port defaults to @@port from configuration.rb as well
|
450
449
|
# * :base defaults to Base.base() from configuration.rb
|
451
|
-
# * :
|
450
|
+
# * :bind_dn defaults @@bind_format from configuration.rb
|
452
451
|
# * :logger defaults to a Log4r object that prints fatal messages to stderr
|
453
|
-
# * :user defaults to ENV['user']
|
454
452
|
# * :password_block defaults to nil
|
455
453
|
# * :allow_anonymous defaults to true
|
456
454
|
# * :try_sasl defaults to false - see Advanced Topics for more on this one.
|
457
|
-
#
|
458
|
-
#
|
455
|
+
#
|
456
|
+
#
|
459
457
|
# Most of these are obvious, but I'll step through them for completeness:
|
460
458
|
# * :host defines the LDAP server hostname to connect to.
|
461
459
|
# * :port defines the LDAP server port to connect to.
|
462
460
|
# * :method defines the type of connection - :tls, :ssl, :plain
|
463
461
|
# * :base specifies the LDAP search base to use with the prefixes defined in all
|
464
462
|
# subclasses.
|
465
|
-
# * :
|
463
|
+
# * :bind_dn specifies what your server expects when attempting to bind with
|
466
464
|
# credentials.
|
467
465
|
# * :logger accepts a custom log4r object to integrate with any other logging
|
468
466
|
# your application uses.
|
469
|
-
# * :user gives the username to substitute into bind_format for binding with
|
470
|
-
# credentials
|
471
467
|
# * :password_block, if defined, give the Proc block for acquiring the password
|
472
468
|
# * :password, if defined, give the user's password as a String
|
473
469
|
# * :store_password indicates whether the password should be stored, or if used
|
@@ -483,13 +479,13 @@
|
|
483
479
|
# * :timeout - time in seconds - defaults to disabled. This CAN interrupt search() requests. Be warned.
|
484
480
|
# * :retry_on_timeout - whether to reconnect when timeouts occur. Defaults to true
|
485
481
|
# See lib/configuration.rb for defaults for each option
|
486
|
-
#
|
482
|
+
#
|
487
483
|
# Base.establish_connection both connects and binds in one step. It follows
|
488
484
|
# roughly the following approach:
|
489
|
-
#
|
485
|
+
#
|
490
486
|
# * Connect to host:port using :method
|
491
|
-
#
|
492
|
-
# * If
|
487
|
+
#
|
488
|
+
# * If bind_dn and password_block/password, attempt to bind with credentials.
|
493
489
|
# * If that fails or no password_block and anonymous allowed, attempt to bind
|
494
490
|
# anonymously.
|
495
491
|
# * If that fails, error out.
|
@@ -497,62 +493,62 @@
|
|
497
493
|
# On connect, the configuration options passed in are stored in an internal class variable
|
498
494
|
# @configuration which is used to cache the information without ditching the defaults passed in
|
499
495
|
# from configuration.rb
|
500
|
-
#
|
496
|
+
#
|
501
497
|
# ===== connection
|
502
|
-
#
|
498
|
+
#
|
503
499
|
# Base.connection returns the ActiveLdap::Connection object.
|
504
|
-
#
|
500
|
+
#
|
505
501
|
# === Exceptions
|
506
|
-
#
|
502
|
+
#
|
507
503
|
# There are a few custom exceptions used in Ruby/ActiveLdap. They are detailed below.
|
508
|
-
#
|
504
|
+
#
|
509
505
|
# ==== DeleteError
|
510
|
-
#
|
506
|
+
#
|
511
507
|
# This exception is raised when #delete fails. It will include LDAP error
|
512
508
|
# information that was passed up during the error.
|
513
|
-
#
|
509
|
+
#
|
514
510
|
# ==== SaveError
|
515
|
-
#
|
511
|
+
#
|
516
512
|
# This exception is raised when there is a problem in #save updating or creating
|
517
513
|
# an LDAP entry. Often the error messages are cryptic. Looking at the server
|
518
514
|
# logs or doing an Ethereal[http://www.ethereal.com] dump of the connection will
|
519
515
|
# often provide better insight.
|
520
|
-
#
|
516
|
+
#
|
521
517
|
# ==== AuthenticationError
|
522
|
-
#
|
518
|
+
#
|
523
519
|
# This exception is raised during Base.establish_connection if no valid authentication methods
|
524
520
|
# succeeded.
|
525
|
-
#
|
521
|
+
#
|
526
522
|
# ==== ConnectionError
|
527
|
-
#
|
528
|
-
# This exception is raised during Base.
|
529
|
-
# LDAP server could be created. Check you configuration.rb,
|
530
|
-
# arguments, and network connectivity! Also check
|
531
|
-
# if it ever saw the request.
|
523
|
+
#
|
524
|
+
# This exception is raised during Base.establish_connection if no valid
|
525
|
+
# connection to the LDAP server could be created. Check you configuration.rb,
|
526
|
+
# Base.establish_connection arguments, and network connectivity! Also check
|
527
|
+
# your LDAP server logs to see if it ever saw the request.
|
532
528
|
#
|
533
529
|
# ==== ObjectClassError
|
534
530
|
#
|
535
531
|
# This exception is raised when an object class is used that is not defined
|
536
532
|
# in the schema.
|
537
|
-
#
|
533
|
+
#
|
538
534
|
# === Others
|
539
|
-
#
|
535
|
+
#
|
540
536
|
# Other exceptions may be raised by the Ruby/LDAP module, or by other subsystems.
|
541
537
|
# If you get one of these exceptions and think it should be wrapped, write me an
|
542
538
|
# email and let me know where it is and what you expected. For faster results,
|
543
539
|
# email a patch!
|
544
|
-
#
|
540
|
+
#
|
545
541
|
# === Putting it all together
|
546
|
-
#
|
542
|
+
#
|
547
543
|
# Now that all of the components of Ruby/ActiveLdap have been covered, it's time
|
548
544
|
# to put it all together! The rest of this section will show the steps to setup
|
549
545
|
# example user and group management scripts for use with the LDAP tree described
|
550
546
|
# above.
|
551
|
-
#
|
547
|
+
#
|
552
548
|
# All of the scripts here are in the package's examples/ directory.
|
553
|
-
#
|
549
|
+
#
|
554
550
|
# ==== Setting up lib/
|
555
|
-
#
|
551
|
+
#
|
556
552
|
# In ldapadmin/lib/ create the file user.rb:
|
557
553
|
# cat <<EOF
|
558
554
|
# class User < ActiveLdap::Base
|
@@ -560,7 +556,7 @@
|
|
560
556
|
# belongs_to :groups, :class => 'Group', :wrap => 'memberUid'
|
561
557
|
# end
|
562
558
|
# EOF
|
563
|
-
#
|
559
|
+
#
|
564
560
|
# In ldapadmin/lib/ create the file group.rb:
|
565
561
|
# cat <<EOF
|
566
562
|
# class Group < ActiveLdap::Base
|
@@ -569,20 +565,20 @@
|
|
569
565
|
# has_many :primary_members, :class => 'User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
|
570
566
|
# end # Group
|
571
567
|
# EOF
|
572
|
-
#
|
568
|
+
#
|
573
569
|
# Now, we can write some small scripts to do simple management tasks.
|
574
|
-
#
|
570
|
+
#
|
575
571
|
# ==== Creating LDAP entries
|
576
|
-
#
|
572
|
+
#
|
577
573
|
# Now let's create a really dumb script for adding users - ldapadmin/useradd:
|
578
|
-
#
|
574
|
+
#
|
579
575
|
# #!/usr/bin/ruby -W0
|
580
|
-
#
|
576
|
+
#
|
581
577
|
# require 'active_ldap'
|
582
578
|
# require 'lib/user'
|
583
579
|
# require 'lib/group'
|
584
580
|
# require 'password'
|
585
|
-
#
|
581
|
+
#
|
586
582
|
# argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
|
587
583
|
# opts.banner += " USER_NAME CN UID"
|
588
584
|
# end
|
@@ -620,15 +616,15 @@
|
|
620
616
|
# end
|
621
617
|
#
|
622
618
|
# ==== Managing LDAP entries
|
623
|
-
#
|
619
|
+
#
|
624
620
|
# Now let's create another dumb script for modifying users - ldapadmin/usermod:
|
625
|
-
#
|
621
|
+
#
|
626
622
|
# #!/usr/bin/ruby -W0
|
627
|
-
#
|
623
|
+
#
|
628
624
|
# require 'active_ldap'
|
629
625
|
# require 'lib/user'
|
630
626
|
# require 'lib/group'
|
631
|
-
#
|
627
|
+
#
|
632
628
|
# argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
|
633
629
|
# opts.banner += " USER_NAME CN UID"
|
634
630
|
# end
|
@@ -663,16 +659,16 @@
|
|
663
659
|
# end
|
664
660
|
#
|
665
661
|
# ==== Removing LDAP entries
|
666
|
-
#
|
662
|
+
#
|
667
663
|
# And finally, a dumb script for removing user - ldapadmin/userdel:
|
668
|
-
#
|
669
|
-
#
|
664
|
+
#
|
665
|
+
#
|
670
666
|
# #!/usr/bin/ruby -W0
|
671
|
-
#
|
667
|
+
#
|
672
668
|
# require 'active_ldap'
|
673
669
|
# require 'lib/user'
|
674
670
|
# require 'lib/group'
|
675
|
-
#
|
671
|
+
#
|
676
672
|
# argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
|
677
673
|
# opts.banner += " USER_NAME"
|
678
674
|
# end
|
@@ -699,9 +695,9 @@
|
|
699
695
|
# User.destroy(name)
|
700
696
|
#
|
701
697
|
# === Advanced Topics
|
702
|
-
#
|
698
|
+
#
|
703
699
|
# Below are some situation tips and tricks to get the most out of Ruby/ActiveLdap.
|
704
|
-
#
|
700
|
+
#
|
705
701
|
#
|
706
702
|
# ==== Binary data and other subtypes
|
707
703
|
#
|
@@ -721,14 +717,14 @@
|
|
721
717
|
# => ...
|
722
718
|
# irb> user.save
|
723
719
|
#
|
724
|
-
# So that's a lot to take in. Here's what is going on. I just set the LDAP
|
720
|
+
# So that's a lot to take in. Here's what is going on. I just set the LDAP
|
725
721
|
# object's cn to "wad" and cn:lang-en-us to ["wad", "Will Drewry"].
|
726
722
|
# Anytime a LDAP subtype is required, you must encapsulate the data in a Hash.
|
727
723
|
#
|
728
724
|
# But wait a minute, I just read in a binary certificate without wrapping it up.
|
729
|
-
# So any binary attribute _that requires ;binary subtyping_ will automagically
|
730
|
-
# get wrapped in {'binary' => value} if you don't do it. This keeps your #writes
|
731
|
-
# from breaking, and my code from crying. For correctness, I could have easily
|
725
|
+
# So any binary attribute _that requires ;binary subtyping_ will automagically
|
726
|
+
# get wrapped in {'binary' => value} if you don't do it. This keeps your #writes
|
727
|
+
# from breaking, and my code from crying. For correctness, I could have easily
|
732
728
|
# done the following:
|
733
729
|
#
|
734
730
|
# irb> user.user_certificate = {'binary' => File.read('example.der')}
|
@@ -737,37 +733,37 @@
|
|
737
733
|
# One example is jpegPhoto. You can use it as jpegPhoto;binary or just as jpegPhoto.
|
738
734
|
# Since the schema dictates that it is a binary value, Ruby/ActiveLdap will write
|
739
735
|
# it as binary, but the subtype will not be automatically appended as above. The
|
740
|
-
# use of the subtype on attributes like jpegPhoto is ultimately decided by the
|
736
|
+
# use of the subtype on attributes like jpegPhoto is ultimately decided by the
|
741
737
|
# LDAP site policy and not by any programmatic means.
|
742
738
|
#
|
743
739
|
# The only subtypes defined in LDAPv3 are lang-* and binary. These can be nested
|
744
740
|
# though:
|
745
741
|
#
|
746
742
|
# irb> user.cn = [{'lang-JP-jp' => {'binary' => 'somejp'}}]
|
747
|
-
#
|
743
|
+
#
|
748
744
|
# As I understand it, OpenLDAP does not support nested subtypes, but some
|
749
745
|
# documentation I've read suggests that Netscape's LDAP server does. I only
|
750
|
-
# have access to OpenLDAP. If anyone tests this out, please let me know how it
|
746
|
+
# have access to OpenLDAP. If anyone tests this out, please let me know how it
|
751
747
|
# goes!
|
752
748
|
#
|
753
749
|
#
|
754
750
|
# And that pretty much wraps up this section.
|
755
751
|
#
|
756
752
|
# ==== Further integration with your environment aka namespacing
|
757
|
-
#
|
753
|
+
#
|
758
754
|
# If you want this to cleanly integrate into your system-wide Ruby include path,
|
759
755
|
# you should put your extension classes inside a custom module.
|
760
|
-
#
|
761
|
-
#
|
756
|
+
#
|
757
|
+
#
|
762
758
|
# Example:
|
763
|
-
#
|
759
|
+
#
|
764
760
|
# ./myldap.rb:
|
765
761
|
# require 'active_ldap'
|
766
762
|
# require 'myldap/user'
|
767
763
|
# require 'myldap/group'
|
768
764
|
# module MyLDAP
|
769
765
|
# end
|
770
|
-
#
|
766
|
+
#
|
771
767
|
# ./myldap/user.rb:
|
772
768
|
# module MyLDAP
|
773
769
|
# class User < ActiveLdap::Base
|
@@ -775,7 +771,7 @@
|
|
775
771
|
# belongs_to :groups, :class => 'MyLDAP::Group', :many => 'memberUid'
|
776
772
|
# end
|
777
773
|
# end
|
778
|
-
#
|
774
|
+
#
|
779
775
|
# ./myldap/group.rb:
|
780
776
|
# module MyLDAP
|
781
777
|
# class Group < ActiveLdap::Base
|
@@ -784,21 +780,21 @@
|
|
784
780
|
# has_many :primary_members, :class => 'MyLDAP::User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
|
785
781
|
# end
|
786
782
|
# end
|
787
|
-
#
|
783
|
+
#
|
788
784
|
# Now in your local applications, you can call
|
789
|
-
#
|
785
|
+
#
|
790
786
|
# require 'myldap'
|
791
|
-
#
|
787
|
+
#
|
792
788
|
# MyLDAP::Group.new('foo')
|
793
789
|
# ...
|
794
|
-
#
|
790
|
+
#
|
795
791
|
# and everything should work well.
|
796
|
-
#
|
792
|
+
#
|
797
793
|
#
|
798
794
|
# ==== force array results for single values
|
799
795
|
#
|
800
|
-
# Even though Ruby/ActiveLdap attempts to maintain programmatic ease by
|
801
|
-
# returning Array values only. By specifying 'true' as an argument to
|
796
|
+
# Even though Ruby/ActiveLdap attempts to maintain programmatic ease by
|
797
|
+
# returning Array values only. By specifying 'true' as an argument to
|
802
798
|
# any attribute method you will get back a Array if it is single value.
|
803
799
|
# Here's an example:
|
804
800
|
#
|
@@ -808,33 +804,33 @@
|
|
808
804
|
# => ["Will Drewry"]
|
809
805
|
#
|
810
806
|
# ==== Dynamic attribute crawling
|
811
|
-
#
|
812
|
-
# If you use tab completion in irb, you'll notice that you /can/ tab complete the dynamic
|
813
|
-
# attribute methods. You can still see which methods are for attributes using
|
807
|
+
#
|
808
|
+
# If you use tab completion in irb, you'll notice that you /can/ tab complete the dynamic
|
809
|
+
# attribute methods. You can still see which methods are for attributes using
|
814
810
|
# Base#attribute_names:
|
815
|
-
#
|
811
|
+
#
|
816
812
|
# irb> d = Group.new('develop')
|
817
813
|
# => ...
|
818
814
|
# irb> d.attribute_names
|
819
815
|
# => ["gidNumber", "cn", "memberUid", "commonName", "description", "userPassword", "objectClass"]
|
820
|
-
#
|
821
|
-
#
|
816
|
+
#
|
817
|
+
#
|
822
818
|
# ==== Juggling multiple LDAP connections
|
823
|
-
#
|
819
|
+
#
|
824
820
|
# In the same vein as the last tip, you can use multiple LDAP connections by
|
825
821
|
# per class as follows:
|
826
|
-
#
|
822
|
+
#
|
827
823
|
# irb> anon_class = Class.new(Base)
|
828
824
|
# => ...
|
829
825
|
# irb> anon_class.establish_connection
|
830
826
|
# => ...
|
831
827
|
# irb> auth_class = Class.new(Base)
|
832
828
|
# => ...
|
833
|
-
# irb> auth_class.establish_connection(password_block => {'mypass'})
|
829
|
+
# irb> auth_class.establish_connection(:password_block => {'mypass'})
|
834
830
|
# => ...
|
835
|
-
#
|
831
|
+
#
|
836
832
|
# This can be useful for doing authentication tests and other such tricks.
|
837
|
-
#
|
833
|
+
#
|
838
834
|
# ==== :try_sasl
|
839
835
|
#
|
840
836
|
# If you have the Ruby/LDAP package with the SASL/GSSAPI patch from Ian
|
@@ -898,7 +894,7 @@
|
|
898
894
|
# == Limitations
|
899
895
|
#
|
900
896
|
# === Speed
|
901
|
-
#
|
897
|
+
#
|
902
898
|
# Currently, Ruby/ActiveLdap could be faster. I have some recursive type
|
903
899
|
# checking going on which slows object creation down, and I'm sure there
|
904
900
|
# are many, many other places optimizations can be done. Feel free
|
@@ -911,9 +907,6 @@
|
|
911
907
|
# package, and I'd like to see it prove helpful to more people than just myself.
|
912
908
|
#
|
913
909
|
|
914
|
-
# Blanket warning hiding. Remove for debugging
|
915
|
-
$VERBOSE, verbose = false, $VERBOSE
|
916
|
-
|
917
910
|
if RUBY_PLATFORM.match('linux')
|
918
911
|
require 'active_ldap/timeout'
|
919
912
|
else
|
@@ -942,14 +935,14 @@ require 'active_ldap/configuration'
|
|
942
935
|
require 'active_ldap/connection'
|
943
936
|
require 'active_ldap/attributes'
|
944
937
|
require 'active_ldap/object_class'
|
945
|
-
require 'active_ldap/
|
938
|
+
require 'active_ldap/distinguished_name'
|
946
939
|
|
947
940
|
require_gem_if_need.call("active_record/base", "activerecord")
|
948
941
|
require 'active_ldap/validations'
|
949
942
|
require 'active_ldap/callbacks'
|
950
943
|
|
951
944
|
module ActiveLdap
|
952
|
-
VERSION = "0.8.
|
945
|
+
VERSION = "0.8.2"
|
953
946
|
end
|
954
947
|
|
955
948
|
ActiveLdap::Base.class_eval do
|
@@ -962,4 +955,10 @@ ActiveLdap::Base.class_eval do
|
|
962
955
|
include ActiveLdap::Callbacks
|
963
956
|
end
|
964
957
|
|
965
|
-
|
958
|
+
unless defined?(ACTIVE_LDAP_CONNECTION_ADAPTERS)
|
959
|
+
ACTIVE_LDAP_CONNECTION_ADAPTERS = %w(ldap net_ldap)
|
960
|
+
end
|
961
|
+
|
962
|
+
ACTIVE_LDAP_CONNECTION_ADAPTERS.each do |adapter|
|
963
|
+
require "active_ldap/adapter/#{adapter}"
|
964
|
+
end
|