dm-ldap-adapter 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/Manifest.txt +0 -1
- data/README.txt +6 -8
- data/Rakefile +1 -1
- data/example/posix.rb +14 -14
- data/lib/adapters/ldap_adapter.rb +1 -8
- data/lib/ldap/digest.rb +2 -2
- data/lib/ldap/net_ldap_facade.rb +14 -7
- data/lib/ldap/ruby_ldap_facade.rb +9 -9
- data/spec/multi_value_attributes_spec.rb +2 -2
- data/spec/spec_helper.rb +7 -7
- metadata +4 -5
- data/example/identity_map.rb +0 -75
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -46,8 +46,6 @@ or
|
|
46
46
|
|
47
47
|
see 'example/posix.rb' for user/group setup works with default installation of openldap on ubuntu (just change your password as needed in the code)
|
48
48
|
|
49
|
-
the 'example/identity_map.rb' shows the usage of identity maps, see also below.
|
50
|
-
|
51
49
|
== FEATURES/PROBLEMS:
|
52
50
|
|
53
51
|
* the net-ldap has some issues with not closing the connections when an exception/error got raised, with limit the search result to 126 entries which gets fixed by making consecutives searches and collect the result.
|
@@ -62,7 +60,7 @@ there are three parts which makes the DN of a model, the base from the ldap conn
|
|
62
60
|
|
63
61
|
class User
|
64
62
|
include DataMapper::Resource
|
65
|
-
property :id, Serial, :field => "
|
63
|
+
property :id, Serial, :field => "uidNumber"
|
66
64
|
dn_prefix { |user| "uid=#{user.login}"}
|
67
65
|
treebase "ou=people"
|
68
66
|
end
|
@@ -77,7 +75,7 @@ for example the ldap posixGroup has more attributes than the model class, it nee
|
|
77
75
|
|
78
76
|
class Group
|
79
77
|
include DataMapper::Resource
|
80
|
-
property :id, Serial, :field => "
|
78
|
+
property :id, Serial, :field => "gidNumber"
|
81
79
|
property :name, String, :field => "cn"
|
82
80
|
dn_prefix { |group| "cn=#{group.name}" }
|
83
81
|
treebase "ou=groups"
|
@@ -169,8 +167,8 @@ staying with posix example there the groups has a memberuid attribute BUT unlike
|
|
169
167
|
|
170
168
|
class GroupUser
|
171
169
|
include DataMapper::Resource
|
172
|
-
property :
|
173
|
-
property :
|
170
|
+
property :memberUid, String, :key => true
|
171
|
+
property :gidNumber, Integer, :key => true
|
174
172
|
dn_prefix { |group_user| "cn=#{group_user.group.name}" }
|
175
173
|
treebase "ou=groups"
|
176
174
|
ldap_properties do |group_user|
|
@@ -187,14 +185,14 @@ let's say your LDAP has multiple email values for a users then you can define yo
|
|
187
185
|
|
188
186
|
class User
|
189
187
|
include DataMapper::Resource
|
190
|
-
property :id, Serial, :field => "
|
188
|
+
property :id, Serial, :field => "uidNumber"
|
191
189
|
property :login, String, :field => "uid", :unique_index => true
|
192
190
|
property :mail, LdapArray
|
193
191
|
|
194
192
|
dn_prefix { |user| "uid=#{user.login}"}
|
195
193
|
treebase "ou=people"
|
196
194
|
ldap_properties do |user|
|
197
|
-
properties = { :objectclass => ["inetOrgPerson", "posixAccount", "shadowAccount"], :loginshell => "/bin/bash", :
|
195
|
+
properties = { :objectclass => ["inetOrgPerson", "posixAccount", "shadowAccount"], :loginshell => "/bin/bash", :gidNumber => "10000" }
|
198
196
|
properties
|
199
197
|
end
|
200
198
|
end
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ require 'spec/rake/spectask'
|
|
9
9
|
require 'pathname'
|
10
10
|
|
11
11
|
Hoe.spec('dm-ldap-adapter') do |p|
|
12
|
-
p.version = "0.4.
|
12
|
+
p.version = "0.4.2"
|
13
13
|
p.description = "ldap adapter for datamapper which uses either net-ldap or ruby-ldap"
|
14
14
|
p.developer('mkristian', 'm.kristian@web.de')
|
15
15
|
p.url = "http://dm-ldap-adapter.rubyforge.org"
|
data/example/posix.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'rubygems'
|
3
|
-
require 'slf4r/
|
4
|
-
|
3
|
+
require 'slf4r/logger'
|
4
|
+
require 'slf4r/ruby_logger'
|
5
5
|
require 'dm-core'
|
6
6
|
|
7
7
|
$LOAD_PATH << Pathname(__FILE__).dirname.parent.expand_path + 'lib'
|
8
8
|
|
9
|
-
Logging.init :debug, :info, :warn, :error
|
9
|
+
# Logging.init :debug, :info, :warn, :error
|
10
10
|
|
11
|
-
appender = Logging::Appender.stdout
|
12
|
-
appender.layout = Logging::Layouts::Pattern.new(:pattern => "%d [%-l] (%c) %m\n")
|
13
|
-
logger = Logging::Logger.new(:root)
|
14
|
-
logger.add_appenders(appender)
|
15
|
-
logger.level = :debug
|
16
|
-
logger.info "initialized logger . . ."
|
11
|
+
# appender = Logging::Appender.stdout
|
12
|
+
# appender.layout = Logging::Layouts::Pattern.new(:pattern => "%d [%-l] (%c) %m\n")
|
13
|
+
# logger = Logging::Logger.new(:root)
|
14
|
+
# logger.add_appenders(appender)
|
15
|
+
# logger.level = :debug
|
16
|
+
# logger.info "initialized logger . . ."
|
17
17
|
|
18
18
|
dummy = true #uncomment this to use dummy, i.e. a database instead of ldap
|
19
19
|
dummy = false # uncomment this to use ldap
|
@@ -49,9 +49,9 @@ end
|
|
49
49
|
class User
|
50
50
|
include DataMapper::Resource
|
51
51
|
|
52
|
-
property :id, Serial, :field => "
|
52
|
+
property :id, Serial, :field => "uidNumber"
|
53
53
|
property :login, String, :field => "uid"
|
54
|
-
property :hashed_password, String, :field => "
|
54
|
+
property :hashed_password, String, :field => "userPassword"
|
55
55
|
property :name, String, :field => "cn"
|
56
56
|
|
57
57
|
has n, :group_users, :child_key => [:memberuid]
|
@@ -99,7 +99,7 @@ end
|
|
99
99
|
class Group
|
100
100
|
include DataMapper::Resource
|
101
101
|
include Slf4r::Logger
|
102
|
-
property :id, Serial, :field => "
|
102
|
+
property :id, Serial, :field => "gidNumber"
|
103
103
|
property :name, String, :field => "cn"
|
104
104
|
|
105
105
|
dn_prefix { |group| "cn=#{group.name}" }
|
@@ -145,8 +145,8 @@ class GroupUser
|
|
145
145
|
ldap_properties do |group_user|
|
146
146
|
{:cn=>"#{group_user.group.name}", :objectclass => "posixGroup"}
|
147
147
|
end
|
148
|
-
property :memberuid, String, :key => true#, :field => "
|
149
|
-
property :gidnumber, Integer, :key => true#, :field => "
|
148
|
+
property :memberuid, String, :key => true#, :field => "memberUid"
|
149
|
+
property :gidnumber, Integer, :key => true#, :field => "gidNumber"
|
150
150
|
|
151
151
|
def group
|
152
152
|
Group.get!(gidnumber)
|
@@ -316,7 +316,7 @@ module DataMapper
|
|
316
316
|
end
|
317
317
|
|
318
318
|
#puts "read_many"
|
319
|
-
#p result
|
319
|
+
#p result
|
320
320
|
result = result.uniq if query.unique?
|
321
321
|
result = query.match_records(result) if query.model.multivalue_field
|
322
322
|
result = query.sort_records_case_insensitive(result)
|
@@ -332,11 +332,6 @@ module DataMapper
|
|
332
332
|
query.model.key.collect { |k| k.field },
|
333
333
|
to_ldap_conditions(query),
|
334
334
|
field_names, order_by)
|
335
|
-
#.sort! do |u1, u2|
|
336
|
-
# value1 = u1[order_by_sym].first.upcase rescue ""
|
337
|
-
# value2 = u2[order_by_sym].first.upcase rescue ""
|
338
|
-
# value1 <=> value2
|
339
|
-
# end
|
340
335
|
if query.model.multivalue_field
|
341
336
|
props_result = []
|
342
337
|
result.each do |props|
|
@@ -367,8 +362,6 @@ module DataMapper
|
|
367
362
|
end
|
368
363
|
end
|
369
364
|
end
|
370
|
-
|
371
|
-
# include ::DataMapper::Transaction::Adapter
|
372
365
|
end
|
373
366
|
end
|
374
367
|
end
|
data/lib/ldap/digest.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sha1'
|
2
|
+
require 'base64'
|
1
3
|
module Ldap
|
2
4
|
class Digest
|
3
5
|
# method from openldap faq which produces the userPassword attribute
|
@@ -6,8 +8,6 @@ module Ldap
|
|
6
8
|
# @param salt String the salt for the password digester
|
7
9
|
# @return the encoded password/salt
|
8
10
|
def self.ssha(secret, salt)
|
9
|
-
require 'sha1'
|
10
|
-
require 'base64'
|
11
11
|
(salt.empty? ? "{SHA}": "{SSHA}") +
|
12
12
|
Base64.encode64(::Digest::SHA1.digest(secret + salt) + salt).gsub(/\n/, '')
|
13
13
|
end
|
data/lib/ldap/net_ldap_facade.rb
CHANGED
@@ -44,7 +44,7 @@ module Ldap
|
|
44
44
|
base = "#{treebase},#{@ldap.base}"
|
45
45
|
if @ldap.add( :dn => dn(dn_prefix, treebase),
|
46
46
|
:attributes => props) || @ldap.get_operation_result.code.to_s == "0"
|
47
|
-
props[key_field.
|
47
|
+
props[key_field.to_sym]
|
48
48
|
else
|
49
49
|
unless silence
|
50
50
|
msg = ldap_error("create",
|
@@ -70,13 +70,14 @@ module Ldap
|
|
70
70
|
@ldap.search( :base => "#{treebase},#{@ldap.base}",
|
71
71
|
:attributes => field_names,
|
72
72
|
:filter => filter ) do |res|
|
73
|
-
|
73
|
+
mapp = to_map(field_names, res)
|
74
|
+
|
74
75
|
#puts map[key_field.to_sym]
|
75
76
|
# TODO maybe make filter which removes this unless
|
76
77
|
# TODO move this into the ldap_Adapter to make it more general, so that
|
77
78
|
# all field with Integer gets converted, etc
|
78
|
-
result <<
|
79
|
-
|
79
|
+
result << mapp if key_fields.detect do |key_field|
|
80
|
+
mapp.keys.detect {|k| k.to_s.downcase == key_field.downcase }
|
80
81
|
end
|
81
82
|
end
|
82
83
|
result
|
@@ -140,13 +141,19 @@ module Ldap
|
|
140
141
|
# helper to extract the Hash from the ldap search result
|
141
142
|
# @param Entry from the ldap_search
|
142
143
|
# @return Hash with name/value pairs of the entry
|
143
|
-
def to_map(entry)
|
144
|
+
def to_map(field_names, entry)
|
145
|
+
fields = {:dn => :dn}
|
146
|
+
field_names.each { |f| fields[f.downcase.to_sym] = f.to_sym }
|
144
147
|
def entry.map
|
145
148
|
@myhash
|
146
149
|
end
|
147
|
-
|
150
|
+
result = {}
|
151
|
+
entry.map.each do |k,v|
|
152
|
+
result[fields[k]] = v
|
153
|
+
end
|
154
|
+
result
|
148
155
|
end
|
149
|
-
|
156
|
+
|
150
157
|
def ldap_error(method, dn)
|
151
158
|
"#{method} error: (#{@ldap.get_operation_result.code}) #{@ldap.get_operation_result.message}\n\tDN: #{dn}"
|
152
159
|
end
|
@@ -62,8 +62,7 @@ module Ldap
|
|
62
62
|
LDAP.mod(LDAP::LDAP_MOD_ADD, k.to_s, v.is_a?(::Array) ? v : [v.to_s] )
|
63
63
|
end
|
64
64
|
if @ldap2.add( dn(dn_prefix, treebase), mods)
|
65
|
-
|
66
|
-
props[key_field.downcase.to_sym]
|
65
|
+
props[key_field.to_sym]
|
67
66
|
else
|
68
67
|
unless silence
|
69
68
|
msg = ldap_error("create",
|
@@ -91,14 +90,13 @@ module Ldap
|
|
91
90
|
LDAP::LDAP_SCOPE_SUBTREE,
|
92
91
|
filter.to_s == "" ? "(objectclass=*)" : filter.to_s.gsub(/\(\(/, "(").gsub(/\)\)/, ")"),
|
93
92
|
field_names, false, 0, 0, order_field) do |res|
|
94
|
-
|
95
|
-
map = to_map(res)
|
96
|
-
#puts map[key_field.to_sym]
|
93
|
+
mapp = to_map(field_names, res)
|
97
94
|
# TODO maybe make filter which removes this unless
|
98
95
|
# TODO move this into the ldap_Adapter to make it more general, so that
|
99
96
|
# all field with Integer gets converted, etc
|
100
|
-
|
101
|
-
|
97
|
+
# NOTE: somehow the fields are downcase coming from query.model
|
98
|
+
result << mapp if key_fields.detect do |key_field|
|
99
|
+
mapp.keys.detect {|k| k.to_s.downcase == key_field.downcase }
|
102
100
|
end
|
103
101
|
end
|
104
102
|
end
|
@@ -174,10 +172,12 @@ module Ldap
|
|
174
172
|
# helper to extract the Hash from the ldap search result
|
175
173
|
# @param Entry from the ldap_search
|
176
174
|
# @return Hash with name/value pairs of the entry
|
177
|
-
def to_map(entry)
|
175
|
+
def to_map(field_names, entry)
|
176
|
+
fields = {:dn => :dn}
|
177
|
+
field_names.each { |f| fields[f.downcase.to_sym] = f.to_sym }
|
178
178
|
map = {}
|
179
179
|
LDAP::entry2hash(entry).each do |k,v|
|
180
|
-
map[k.downcase.to_sym] = v
|
180
|
+
map[fields[k.downcase.to_sym]] = v
|
181
181
|
end
|
182
182
|
map
|
183
183
|
end
|
@@ -4,9 +4,9 @@ require 'spec_helper'
|
|
4
4
|
class TestContact
|
5
5
|
include DataMapper::Resource
|
6
6
|
|
7
|
-
property :id, Serial, :field => "
|
7
|
+
property :id, Serial, :field => "uidNumber"
|
8
8
|
property :login, String, :field => "uid", :unique_index => true
|
9
|
-
property :hashed_password, String, :field => "
|
9
|
+
property :hashed_password, String, :field => "userPassword", :lazy => true
|
10
10
|
property :name, String, :field => "cn"
|
11
11
|
property :mail, ::Ldap::LdapArray
|
12
12
|
|
data/spec/spec_helper.rb
CHANGED
@@ -44,10 +44,10 @@ class User
|
|
44
44
|
include DataMapper::Resource
|
45
45
|
property :id, Serial, :field => "uidnumber"
|
46
46
|
property :login, String, :field => "uid", :unique_index => true
|
47
|
-
property :hashed_password, String, :field => "
|
47
|
+
property :hashed_password, String, :field => "userPassword", :writer => :private
|
48
48
|
property :name, String, :field => "cn"
|
49
49
|
property :mail, String
|
50
|
-
property :age, Integer, :field => "
|
50
|
+
property :age, Integer, :field => "postalCode"
|
51
51
|
property :alive, Boolean, :field => "gecos"
|
52
52
|
|
53
53
|
has n, :roles
|
@@ -96,7 +96,7 @@ end
|
|
96
96
|
|
97
97
|
class Role
|
98
98
|
include DataMapper::Resource
|
99
|
-
property :id, Serial, :field => "
|
99
|
+
property :id, Serial, :field => "gidNumber"
|
100
100
|
property :name, String, :field => "cn"
|
101
101
|
|
102
102
|
dn_prefix { |role| "cn=#{role.name}" }
|
@@ -110,7 +110,7 @@ end
|
|
110
110
|
|
111
111
|
class Group
|
112
112
|
include DataMapper::Resource
|
113
|
-
property :id, Serial, :field => "
|
113
|
+
property :id, Serial, :field => "gidNumber"
|
114
114
|
property :name, String, :field => "cn"
|
115
115
|
|
116
116
|
dn_prefix { |group| "cn=#{group.name}" }
|
@@ -127,14 +127,14 @@ class GroupUser
|
|
127
127
|
|
128
128
|
treebase "ou=groups"
|
129
129
|
|
130
|
-
multivalue_field :
|
130
|
+
multivalue_field :memberUid
|
131
131
|
|
132
132
|
ldap_properties do |group_user|
|
133
133
|
{:cn=>"#{group_user.group.name}", :objectclass => "posixGroup"}
|
134
134
|
end
|
135
135
|
|
136
|
-
property :user_id, Integer, :key => true, :field => "
|
137
|
-
property :group_id, Integer, :key => true, :field => "
|
136
|
+
property :user_id, Integer, :key => true, :field => "memberUid"
|
137
|
+
property :group_id, Integer, :key => true, :field => "gidNumber"
|
138
138
|
|
139
139
|
def group
|
140
140
|
Group.get!(group_id)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-ldap-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 2
|
10
|
+
version: 0.4.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- mkristian
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-08 00:00:00 +05:30
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -101,7 +101,6 @@ files:
|
|
101
101
|
- README-example.markdown
|
102
102
|
- README.txt
|
103
103
|
- Rakefile
|
104
|
-
- example/identity_map.rb
|
105
104
|
- example/posix.rb
|
106
105
|
- ldap-commands.txt
|
107
106
|
- lib/adapters/ldap_adapter.rb
|
data/example/identity_map.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'example/posix.rb'
|
2
|
-
|
3
|
-
USER_REPO = :default
|
4
|
-
|
5
|
-
class User
|
6
|
-
|
7
|
-
def self.ddefault_repository_name
|
8
|
-
USER_REPO
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.repository_name
|
12
|
-
USER_REPO
|
13
|
-
end
|
14
|
-
|
15
|
-
def authenticate(pwd)
|
16
|
-
require 'base64'
|
17
|
-
Base64.encode64(Digest::SHA1.digest(pwd)).gsub(/\n/, '') == attribute_get(:hashed_password)[5,1000]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class GroupUser
|
22
|
-
|
23
|
-
def self.ddefault_repository_name
|
24
|
-
USER_REPO
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.repository_name
|
28
|
-
USER_REPO
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
class Group
|
34
|
-
|
35
|
-
def self.ddefault_repository_name
|
36
|
-
USER_REPO
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.repository_name
|
40
|
-
USER_REPO
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
require 'adapters/memory_adapter'
|
46
|
-
DATA_REPO=:store
|
47
|
-
DataMapper.setup(DATA_REPO, {:adapter => 'memory'})
|
48
|
-
|
49
|
-
class Item
|
50
|
-
include DataMapper::Resource
|
51
|
-
property :id, Serial
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
DataMapper.repository(USER_REPO) do |repository|
|
56
|
-
repository.adapter.open_ldap_connection do
|
57
|
-
DataMapper.repository(DATA_REPO) do
|
58
|
-
root = User.first(:login => 'root') || User.create(:id => 0, :login => :root, :name => 'root', :password => 'none') if root.nil?
|
59
|
-
admin = Group.first(:name => 'admin') || Group.create(:name => 'admin')
|
60
|
-
root.groups << admin
|
61
|
-
|
62
|
-
p DataMapper.repository(USER_REPO).identity_map(User)
|
63
|
-
|
64
|
-
p DataMapper.repository(USER_REPO).identity_map(Group)
|
65
|
-
|
66
|
-
p root.authenticate('none')
|
67
|
-
|
68
|
-
p root.groups
|
69
|
-
|
70
|
-
(1..10).each {Item.create}
|
71
|
-
|
72
|
-
p DataMapper.repository(DATA_REPO).identity_map(Item)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|