irjudson-dm-ldap-adapter 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/LICENSE +20 -0
- data/Manifest.txt +13 -0
- data/README.txt +107 -0
- data/Rakefile +30 -0
- data/TODO +0 -0
- data/lib/ldap_adapter.rb +348 -0
- data/lib/ldap_adapter/version.rb +5 -0
- data/spec/integration/ldap_adapter_spec.rb +6 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/install.rb +13 -0
- data/tasks/spec.rb +25 -0
- metadata +89 -0
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Montana State University
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
= dm-ldap-adapter
|
2
|
+
|
3
|
+
A DataMapper adapter for Lightweight Directory Access Protocol (LDAP) servers.
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
DM LDAP Adapter enables the creation of application objects that map
|
8
|
+
against an existing LDAP server. For example, a "user" can map against
|
9
|
+
the posixAccount schema in an LDAP server providing uidNumber,
|
10
|
+
gidNumber, uid, homeDirectory and userPassword. These are intended to
|
11
|
+
map to unix accounts so that authentication on unix systems can be
|
12
|
+
centrally managed by the LDAP server.
|
13
|
+
|
14
|
+
Currently, mapping LDAP schemas to application objects must be done
|
15
|
+
manually by the developer, but the intent is to create a set of
|
16
|
+
objects corresponding to the set of most commonly used LDAP schemas so
|
17
|
+
application developers can leverage them with less effort.
|
18
|
+
|
19
|
+
DataMapper.setup(:default, {
|
20
|
+
:adapter => 'ldap',
|
21
|
+
:host => 'localhost',
|
22
|
+
:port => '389',
|
23
|
+
:base => "ou=people,dc=example,dc=com",
|
24
|
+
:username => "cn=admin,dc=example,dc=com",
|
25
|
+
:password => "exPa5$w0rd"
|
26
|
+
})
|
27
|
+
|
28
|
+
|
29
|
+
class User
|
30
|
+
include DataMapper::Resource
|
31
|
+
|
32
|
+
@@base = "ou=people,dc=example,dc=com"
|
33
|
+
|
34
|
+
@@objectclass = [ "top", "person", "organizationalPerson", "inetOrgPerson",
|
35
|
+
"extensibleObject", "shadowAccount", "posixAccount" ]
|
36
|
+
|
37
|
+
property :username, String, :field => "uid", :key => true
|
38
|
+
property :uuid, String, :field => "uniqueidentifier"
|
39
|
+
property :name, String, :field => "cn"
|
40
|
+
property :first_name, String, :field => "givenname"
|
41
|
+
property :last_name, String, :field => "sn"
|
42
|
+
property :mail, String, :field => "mail"
|
43
|
+
property :groupid, Integer, :field => "gidnumber"
|
44
|
+
property :userid, Integer, :field => "uidnumber"
|
45
|
+
property :homedirectory, String, :field => "homedirectory"
|
46
|
+
|
47
|
+
def objectclass
|
48
|
+
@@objectclass
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_dn
|
52
|
+
"uid=#{netid},#{@@base}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
This is exactly like normal datamapper models, with a couple of extras
|
57
|
+
to make LDAP function.
|
58
|
+
|
59
|
+
@@base is a class variable that defines where in the LDAP hierarchy
|
60
|
+
this class of objects reside, it represents a path from the root. This
|
61
|
+
is important because each piece of ldap data is uniquely identified by
|
62
|
+
a distinguisedName which is the key attribute + @@base. For example,
|
63
|
+
the distinguishedName "uid=testuser,ou=people,dc=example,dc=com"
|
64
|
+
uniquely identifies the test user in the LDAP server.
|
65
|
+
|
66
|
+
@@objectclass is the list of LDAP schemas that are required to define
|
67
|
+
this particular LDAP object. Each schema contributes some set of
|
68
|
+
attributes that, when taken together, define all the objects at that
|
69
|
+
location in the LDAP tree. This list is required when new resources
|
70
|
+
are created in LDAP, but ideally should be hidden from the application
|
71
|
+
developer.
|
72
|
+
|
73
|
+
== Code
|
74
|
+
|
75
|
+
# Create
|
76
|
+
user = User.new(:username => "dmtest", :uuid => UUID.random_create().to_s,
|
77
|
+
:name => "DataMapper Test", :homedirectory => "/home/dmtest",
|
78
|
+
:first_name => "DataMapperTest", :last_name => "User",
|
79
|
+
:userid => 3, :groupid => 500)
|
80
|
+
|
81
|
+
user.save
|
82
|
+
|
83
|
+
# Retrieve
|
84
|
+
user = User.first(:username => 'dmtest')
|
85
|
+
puts user
|
86
|
+
|
87
|
+
# Modify
|
88
|
+
user.update_attributes(:name => 'DM Test')
|
89
|
+
user.save
|
90
|
+
puts user
|
91
|
+
|
92
|
+
# Delete
|
93
|
+
result = user.destroy
|
94
|
+
puts "Result: #{result}"
|
95
|
+
|
96
|
+
== TODO:
|
97
|
+
|
98
|
+
- Figure out a good testing strategy, get standard adapter tests in place
|
99
|
+
|
100
|
+
- Finish query implementation (limit, order, etc)
|
101
|
+
|
102
|
+
- Consider making pre-mapped resources corresponding to the most
|
103
|
+
commonly used LDAP object types so applications can use them without
|
104
|
+
duplication of effort for each application.
|
105
|
+
|
106
|
+
- Documentation clean up
|
107
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'hoe'
|
4
|
+
|
5
|
+
ROOT = Pathname(__FILE__).dirname.expand_path
|
6
|
+
JRUBY = RUBY_PLATFORM =~ /java/
|
7
|
+
WINDOWS = Gem.win_platform?
|
8
|
+
SUDO = (WINDOWS || JRUBY) ? '' : ('sudo' unless ENV['SUDOLESS'])
|
9
|
+
|
10
|
+
require ROOT + 'lib/ldap_adapter/version'
|
11
|
+
|
12
|
+
# define some constants to help with task files
|
13
|
+
GEM_NAME = 'dm-ldap-adapter'
|
14
|
+
GEM_VERSION = DataMapper::LdapAdapter::VERSION
|
15
|
+
|
16
|
+
Hoe.spec(GEM_NAME) do |p|
|
17
|
+
p.developer('Ivan R. Judson', 'ivan.judson [a] montana [d] edu')
|
18
|
+
|
19
|
+
p.description = 'A DataMapper Adapter for LDAP.'
|
20
|
+
p.summary = 'A DataMapper Adapter for LDAP (The Lightweight Directory Access Protocol)'
|
21
|
+
p.url = 'http://github.com/irjudson/dm-ldap-adapter'
|
22
|
+
|
23
|
+
p.clean_globs |= %w[ log pkg coverage ]
|
24
|
+
p.spec_extras = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO History.txt ] }
|
25
|
+
|
26
|
+
p.extra_deps << ['dm-core', "0.9.11"]
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
Pathname.glob(ROOT.join('tasks/**/*.rb').to_s).each { |f| require f }
|
data/TODO
ADDED
File without changes
|
data/lib/ldap_adapter.rb
ADDED
@@ -0,0 +1,348 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'net/ldap'
|
3
|
+
|
4
|
+
module DataMapper
|
5
|
+
module Adapters
|
6
|
+
# The documentation for this adapter was taken from
|
7
|
+
#
|
8
|
+
# lib/dm-core/adapters/in_memory_adapter.rb
|
9
|
+
#
|
10
|
+
# Which is intended as a general source of documentation for the
|
11
|
+
# implementation to be followed by all DataMapper adapters. The
|
12
|
+
# implementor is well advised to read over the adapter before
|
13
|
+
# implementing their own.
|
14
|
+
#
|
15
|
+
class LdapAdapter < AbstractAdapter
|
16
|
+
##
|
17
|
+
# Used by DataMapper to put records into a data-store: "INSERT"
|
18
|
+
# in SQL-speak. It takes an array of the resources (model
|
19
|
+
# instances) to be saved. Resources each have a key that can be
|
20
|
+
# used to quickly look them up later without searching, if the
|
21
|
+
# adapter supports it.
|
22
|
+
#
|
23
|
+
# @param [Array<DataMapper::Resource>] resources
|
24
|
+
# The set of resources (model instances)
|
25
|
+
#
|
26
|
+
# @return [Integer]
|
27
|
+
# The number of records that were actually saved into the
|
28
|
+
# data-store
|
29
|
+
#
|
30
|
+
# @api semipublic
|
31
|
+
def create(resources)
|
32
|
+
|
33
|
+
created = 0
|
34
|
+
resources.each do |resource|
|
35
|
+
# Convert resources into LDAP (which just takes a hash!)
|
36
|
+
ldap_obj = convert_resource_to_hash(resource)
|
37
|
+
dn = resource.make_dn
|
38
|
+
ldap_obj[:objectclass] = resource.objectclass
|
39
|
+
|
40
|
+
if ldap_obj.nil? || dn.nil?
|
41
|
+
puts "Problem converting resource to hash for LdapAdapter"
|
42
|
+
return -1
|
43
|
+
end
|
44
|
+
|
45
|
+
# Call LDAP create
|
46
|
+
begin
|
47
|
+
@ldap.add(:dn => dn, :attributes => ldap_obj)
|
48
|
+
rescue Net::LDAP::LdapError => e
|
49
|
+
puts "There was an error adding the ldap object: ", e
|
50
|
+
puts " => #{@ldap.get_operation_result.message}"
|
51
|
+
return -1
|
52
|
+
end
|
53
|
+
|
54
|
+
# Accumulate successful create calls to return
|
55
|
+
if @ldap.get_operation_result.code == 0
|
56
|
+
created = created + 1
|
57
|
+
else
|
58
|
+
puts "LDAP Add Error: #{@ldap.get_operation_result.message}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return number created
|
63
|
+
return created
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Used by DataMapper to update the attributes on existing
|
68
|
+
# records in a data-store: "UPDATE" in SQL-speak. It takes a
|
69
|
+
# hash of the attributes to update with, as well as a query
|
70
|
+
# object that specifies which resources should be updated.
|
71
|
+
#
|
72
|
+
# @param [Hash] attributes
|
73
|
+
# A set of key-value pairs of the attributes to update the
|
74
|
+
# resources with.
|
75
|
+
# @param [DataMapper::Query] query
|
76
|
+
# The query that should be used to find the resource(s) to update.
|
77
|
+
#
|
78
|
+
# @return [Integer]
|
79
|
+
# the number of records that were successfully updated
|
80
|
+
#
|
81
|
+
# @api semipublic
|
82
|
+
def update(attributes, query)
|
83
|
+
updated = 0
|
84
|
+
|
85
|
+
# Convert query conditions to ldap filter
|
86
|
+
filter = convert_conditions(query.conditions)
|
87
|
+
|
88
|
+
# Convert attributes/query into LDAP
|
89
|
+
entries = @ldap.search(:filter => filter)
|
90
|
+
|
91
|
+
# Process updates (being careful to distinguish between add and update
|
92
|
+
entries.each do |entry|
|
93
|
+
existing = entry.attribute_names.map { |a| a.to_s }
|
94
|
+
attributes.each do |attribute, value|
|
95
|
+
property = attribute.field.to_s
|
96
|
+
|
97
|
+
ops = []
|
98
|
+
if existing.include?(property)
|
99
|
+
ops << [:replace, attribute.field.to_sym, value]
|
100
|
+
else
|
101
|
+
ops << [:add, attribute.field.to_sym, value]
|
102
|
+
end
|
103
|
+
|
104
|
+
@ldap.modify(:dn => entry.dn, :operations => ops)
|
105
|
+
|
106
|
+
if @ldap.get_operation_result.code == 0
|
107
|
+
updated = updated + 1
|
108
|
+
else
|
109
|
+
puts "LDAP Modify Error: #{@ldap.get_operation_result.message}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return Number updated
|
115
|
+
return updated
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Look up a single record from the data-store. "SELECT ... LIMIT
|
120
|
+
# 1" in SQL. Used by Model#get to find a record by its
|
121
|
+
# identifier(s), and Model#first to find a single record by some
|
122
|
+
# search query.
|
123
|
+
#
|
124
|
+
# @param [DataMapper::Query] query
|
125
|
+
# The query to be used to locate the resource.
|
126
|
+
#
|
127
|
+
# @return [DataMapper::Resource]
|
128
|
+
# A Resource object representing the record that was found, or
|
129
|
+
# nil for no matching records.
|
130
|
+
#
|
131
|
+
# @api semipublic
|
132
|
+
def read_one(query)
|
133
|
+
# Call read_many(query)
|
134
|
+
all_results = self.read_many(query)
|
135
|
+
|
136
|
+
# Return first result
|
137
|
+
return all_results.first
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Looks up a collection of records from the data-store: "SELECT" in SQL.
|
142
|
+
# Used by Model#all to search for a set of records; that set is in a
|
143
|
+
# DataMapper::Collection object.
|
144
|
+
#
|
145
|
+
# @param [DataMapper::Query] query
|
146
|
+
# The query to be used to seach for the resources
|
147
|
+
#
|
148
|
+
# @return [DataMapper::Collection]
|
149
|
+
# A collection of all the resources found by the query.
|
150
|
+
#
|
151
|
+
# @api semipublic
|
152
|
+
def read_many(query)
|
153
|
+
resources = Array.new
|
154
|
+
|
155
|
+
# Convert query conditions to ldap filter
|
156
|
+
filter = convert_conditions(query.conditions)
|
157
|
+
|
158
|
+
# Convert attributes/query into LDAP
|
159
|
+
@ldap.search(:filter => filter, :return_result => false) do |entry|
|
160
|
+
values = query.fields.collect do |field|
|
161
|
+
entry[field.field.to_sym].first
|
162
|
+
end
|
163
|
+
resources << query.model.load(values, query)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Return Results
|
167
|
+
resources
|
168
|
+
end
|
169
|
+
|
170
|
+
alias :read :read_many
|
171
|
+
|
172
|
+
##
|
173
|
+
# Destroys all the records matching the given query. "DELETE" in SQL.
|
174
|
+
#
|
175
|
+
# @param [DataMapper::Query] query
|
176
|
+
# The query used to locate the resources to be deleted.
|
177
|
+
#
|
178
|
+
# @return [Integer]
|
179
|
+
# The number of records that were deleted.
|
180
|
+
#
|
181
|
+
# @api semipublic
|
182
|
+
def delete(query)
|
183
|
+
|
184
|
+
deleted = 0
|
185
|
+
|
186
|
+
# Convert query conditions to ldap filter
|
187
|
+
filter = convert_conditions(query.conditions)
|
188
|
+
|
189
|
+
# Convert attributes/query into LDAP
|
190
|
+
entries = @ldap.search(:filter => filter)
|
191
|
+
|
192
|
+
# Call LDAP Delete
|
193
|
+
entries.each do |entry|
|
194
|
+
result = @ldap.delete(:dn => entry.dn)
|
195
|
+
|
196
|
+
if @ldap.get_operation_result.code == 0
|
197
|
+
deleted = deleted + 1
|
198
|
+
else
|
199
|
+
puts "LDAP Delete Error: #{@ldap.get_operation_result.message}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Return number successfully deleted
|
204
|
+
return deleted
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
##
|
210
|
+
# Make a new instance of the adapter. The @model_records ivar is
|
211
|
+
# the 'data-store' for this adapter. It is not shared amongst
|
212
|
+
# multiple incarnations of this adapter, eg
|
213
|
+
# DataMapper.setup(:default, :adapter => :in_memory);
|
214
|
+
# DataMapper.setup(:alternate, :adapter => :in_memory) do not
|
215
|
+
# share the data-store between them.
|
216
|
+
#
|
217
|
+
# @param [String, Symbol] name
|
218
|
+
# The name of the DataMapper::Repository using this adapter.
|
219
|
+
# @param [String, Hash] uri_or_options
|
220
|
+
# The connection uri string, or a hash of options to set up
|
221
|
+
# the adapter
|
222
|
+
#
|
223
|
+
# @api semipublic
|
224
|
+
def initialize(name, uri_or_options)
|
225
|
+
super
|
226
|
+
|
227
|
+
if uri_or_options.class
|
228
|
+
@identity_maps = {}
|
229
|
+
end
|
230
|
+
|
231
|
+
@options = Hash.new
|
232
|
+
|
233
|
+
# Let's play with Options
|
234
|
+
@options[:attributes] = nil
|
235
|
+
@options[:scope] = Net::LDAP::SearchScope_WholeSubtree
|
236
|
+
@options[:filter] = nil
|
237
|
+
@options[:auth] = { :method => :simple }
|
238
|
+
|
239
|
+
uri_or_options.each do |k,v|
|
240
|
+
@options[k] = v
|
241
|
+
end
|
242
|
+
|
243
|
+
# if uri_or_options.is_a?(String)
|
244
|
+
# begin
|
245
|
+
# opt_array = URI.split(uri_or_options)
|
246
|
+
# @options[:scheme] = opt_array[0]
|
247
|
+
# @options[:auth][:username],@options[:auth][:password] = opt_array[1].split(':')
|
248
|
+
# @options[:host] = opt_array[2]
|
249
|
+
# @options[:port] = opt_array[3]
|
250
|
+
|
251
|
+
# # Registry from URI not used
|
252
|
+
# # @options[:registry] = opt_array[4]
|
253
|
+
|
254
|
+
# @options[:base] = opt_array[5]
|
255
|
+
|
256
|
+
# # Opaque from URI not used
|
257
|
+
# # @options[:opaque] = opt_array[6]
|
258
|
+
|
259
|
+
# # This is where the rest of the string is kept
|
260
|
+
# # According to the LDAP url spec it should look like
|
261
|
+
# # ?attributes?scope?filter, e.g.
|
262
|
+
# # ?uid?sub?(uid=username), however
|
263
|
+
# # URI strip appears to lose the first ?
|
264
|
+
# # So we parse it all out
|
265
|
+
# @options[:attributes],@options[:scope],@options[:filter] = opt_array[7].split('?')
|
266
|
+
# @options[:fragment] = opt_array[8]
|
267
|
+
# rescue InvalidURIError => e
|
268
|
+
# puts "Error parsing options for ldap adapter"
|
269
|
+
# end
|
270
|
+
# else
|
271
|
+
# @options.merge!(uri_or_options.dup)
|
272
|
+
|
273
|
+
# @options[:auth][:username] = @options[:username]
|
274
|
+
# @options[:auth][:password] = @options[:password]
|
275
|
+
|
276
|
+
# @options.delete(:adapter)
|
277
|
+
# @options.delete(:username)
|
278
|
+
# @options.delete(:password)
|
279
|
+
# @options.delete(:attributes)
|
280
|
+
# @options.delete(:filter)
|
281
|
+
# end
|
282
|
+
|
283
|
+
# Deal with SSL stuff
|
284
|
+
if @options[:scheme] == "ldaps" || @options[:port] == "636"
|
285
|
+
@options[:encryption] = { :method => :simple_tls }
|
286
|
+
end
|
287
|
+
|
288
|
+
puts "Options: #{@options.inspect}"
|
289
|
+
|
290
|
+
# Create the new LDAP client stub
|
291
|
+
@ldap = Net::LDAP.new(@options)
|
292
|
+
|
293
|
+
if ! @ldap.bind
|
294
|
+
puts "Tried to bind with options: #{@options.inspect}"
|
295
|
+
puts "Result: #{@ldap.get_operation_result.code}"
|
296
|
+
puts "Message: #{@ldap.get_operation_result.message}"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def convert_resource_to_hash(resource)
|
301
|
+
result = Hash.new
|
302
|
+
resource.send(:properties).each do |p|
|
303
|
+
result[p.field.to_sym] = p.get!(resource) unless p.get!(resource).nil?
|
304
|
+
end
|
305
|
+
result
|
306
|
+
end
|
307
|
+
|
308
|
+
def convert_conditions(conditions)
|
309
|
+
filters = Array.new
|
310
|
+
conditions.each do |condition|
|
311
|
+
case condition[0]
|
312
|
+
when :eql
|
313
|
+
filters << Net::LDAP::Filter.eq(condition[1].field(), condition[2].to_s)
|
314
|
+
when :lt
|
315
|
+
fle = Net::LDAP::Filter.le(condition[1].field(), condition[2].to_s)
|
316
|
+
fe = Net::LDAP::Filter.eq(condition[1].field(), condition[2].to_s)
|
317
|
+
filters << fle & ! fe
|
318
|
+
when :gt
|
319
|
+
fge = Net::LDAP::Filter.ge(condition[1].field(), condition[2].to_s)
|
320
|
+
fe = Net::LDAP::Filter.eq(condition[1].field(), condition[2].to_s)
|
321
|
+
filters << fge & ! fe
|
322
|
+
when :lte
|
323
|
+
filters << Net::LDAP::Filter.le(condition[1].field(), condition[2].to_s)
|
324
|
+
when :gte
|
325
|
+
filters << Net::LDAP::Filter.ge(condition[1].field(), condition[2].to_s)
|
326
|
+
when :not : puts "!"
|
327
|
+
filters << Net::LDAP::Filter.ne(condition[1].field(), condition[2].to_s)
|
328
|
+
when :like
|
329
|
+
filters << Net::LDAP::Filter.eq(condition[1].field(), condition[2].to_s)
|
330
|
+
else
|
331
|
+
puts "Unknown condition: #{condition[0]}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# Put them all together with an AND
|
336
|
+
ldap_filter = nil
|
337
|
+
filters.each do |filter|
|
338
|
+
if ldap_filter.nil?
|
339
|
+
ldap_filter = filter
|
340
|
+
else
|
341
|
+
ldap_filter = ldap_filter & filter
|
342
|
+
end
|
343
|
+
end
|
344
|
+
ldap_filter
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/install.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
def sudo_gem(cmd)
|
2
|
+
sh "#{SUDO} #{RUBY} -S gem #{cmd}", :verbose => false
|
3
|
+
end
|
4
|
+
|
5
|
+
desc "Install #{GEM_NAME} #{GEM_VERSION}"
|
6
|
+
task :install => [ :package ] do
|
7
|
+
sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
|
11
|
+
task :uninstall => [ :clobber ] do
|
12
|
+
sudo_gem "uninstall #{GEM_NAME} -v#{GEM_VERSION} -Ix"
|
13
|
+
end
|
data/tasks/spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
begin
|
2
|
+
gem 'rspec', '~>1.1.11'
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
task :default => [ :spec ]
|
7
|
+
|
8
|
+
desc 'Run specifications'
|
9
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
10
|
+
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
11
|
+
t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
|
12
|
+
|
13
|
+
begin
|
14
|
+
gem 'rcov', '~>0.8'
|
15
|
+
t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
|
16
|
+
t.rcov_opts << '--exclude' << 'spec'
|
17
|
+
t.rcov_opts << '--text-summary'
|
18
|
+
t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
|
19
|
+
rescue LoadError
|
20
|
+
# rcov not installed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
# rspec not installed
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: irjudson-dm-ldap-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ivan R. Judson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dm-core~
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.10
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.11.0
|
34
|
+
version:
|
35
|
+
description: A DataMapper Adapter for LDAP, as simply as possible.
|
36
|
+
email:
|
37
|
+
- ivan.judson [a] montana [d] edu
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README.txt
|
44
|
+
- LICENSE
|
45
|
+
- TODO
|
46
|
+
- History.txt
|
47
|
+
files:
|
48
|
+
- History.txt
|
49
|
+
- LICENSE
|
50
|
+
- Manifest.txt
|
51
|
+
- README.txt
|
52
|
+
- Rakefile
|
53
|
+
- TODO
|
54
|
+
- lib/ldap_adapter.rb
|
55
|
+
- lib/ldap_adapter/version.rb
|
56
|
+
- spec/integration/ldap_adapter_spec.rb
|
57
|
+
- spec/spec.opts
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
- tasks/install.rb
|
60
|
+
- tasks/spec.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/irjudson/dm-ldap-adapter
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --main
|
66
|
+
- README.txt
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project: dm-ldap-adapter
|
84
|
+
rubygems_version: 1.2.0
|
85
|
+
signing_key:
|
86
|
+
specification_version: 2
|
87
|
+
summary: A DataMapper Adapter for LDAP
|
88
|
+
test_files: []
|
89
|
+
|