dm-ldap-adapter 0.3.5 → 0.4.0.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.project +11 -0
- data/.yardoc +0 -0
- data/Manifest.txt +5 -2
- data/README-example.markdown +0 -1
- data/README.txt +15 -15
- data/Rakefile +4 -3
- data/env.sh +2 -0
- data/example/identity_map.rb +10 -10
- data/example/posix.rb +9 -9
- data/ldap-commands.txt +3 -0
- data/lib/adapters/ldap_adapter.rb +155 -118
- data/lib/adapters/noop_transaction.rb +16 -0
- data/lib/dummy_ldap_resource.rb +6 -6
- data/lib/ldap/array.rb +96 -12
- data/lib/ldap/conditions_2_filter.rb +95 -0
- data/lib/ldap/digest.rb +3 -3
- data/lib/ldap/net_ldap_facade.rb +28 -110
- data/lib/ldap/ruby_ldap_facade.rb +31 -116
- data/lib/ldap/version.rb +1 -1
- data/lib/ldap_resource.rb +113 -26
- data/spec/assiociations_ldap_adapter_spec.rb +129 -130
- data/spec/authentication_ldap_adapter_spec.rb +1 -6
- data/spec/ldap_adapter_spec.rb +164 -177
- data/spec/multi_repository_spec.rb +41 -5
- data/spec/multi_value_attributes_spec.rb +64 -31
- data/spec/sorting_spec.rb +16 -15
- data/spec/spec_helper.rb +34 -20
- metadata +67 -27
- data/lib/adapters/memory_adapter.rb +0 -79
- data/lib/adapters/simple_adapter.rb +0 -198
data/lib/ldap_resource.rb
CHANGED
@@ -3,11 +3,105 @@ require 'dm-core'
|
|
3
3
|
require 'ldap/array'
|
4
4
|
|
5
5
|
module DataMapper
|
6
|
-
module
|
7
|
-
|
8
|
-
|
6
|
+
module Model
|
7
|
+
|
8
|
+
def load(records, query)
|
9
|
+
repository = query.repository
|
10
|
+
repository_name = repository.name
|
11
|
+
fields = query.fields
|
12
|
+
discriminator = properties(repository_name).discriminator
|
13
|
+
no_reload = !query.reload?
|
14
|
+
|
15
|
+
field_map = fields.map { |property| [ property, property.field ] }.to_hash
|
16
|
+
|
17
|
+
records.map do |record|
|
18
|
+
identity_map = nil
|
19
|
+
key_values = nil
|
20
|
+
resource = nil
|
21
|
+
|
22
|
+
case record
|
23
|
+
when Hash
|
24
|
+
# remap fields to use the Property object
|
25
|
+
record = record.dup
|
26
|
+
field_map.each { |property, field| record[property] = record.delete(field) if record.key?(field) }
|
27
|
+
|
28
|
+
model = discriminator && discriminator.load(record[discriminator]) || self
|
29
|
+
model_key = model.key(repository_name)
|
30
|
+
|
31
|
+
resource = if model_key.valid?(key_values = record.values_at(*model_key))
|
32
|
+
identity_map = repository.identity_map(model)
|
33
|
+
identity_map[key_values]
|
34
|
+
end
|
35
|
+
|
36
|
+
resource ||= model.allocate
|
37
|
+
|
38
|
+
fields.each do |property|
|
39
|
+
next if no_reload && property.loaded?(resource)
|
40
|
+
|
41
|
+
value = record[property]
|
42
|
+
|
43
|
+
# TODO: typecasting should happen inside the Adapter
|
44
|
+
# and all values should come back as expected objects
|
45
|
+
if property.respond_to?(:load_with_resource)
|
46
|
+
# hack to allow mutable types which are able to reset
|
47
|
+
# the attribute to make them dirty
|
48
|
+
value = property.load_with_resource(value, resource)
|
49
|
+
else
|
50
|
+
value = property.load(value)
|
51
|
+
end
|
52
|
+
|
53
|
+
property.set!(resource, value)
|
54
|
+
end
|
55
|
+
|
56
|
+
when Resource
|
57
|
+
model = record.model
|
58
|
+
model_key = model.key(repository_name)
|
59
|
+
|
60
|
+
resource = if model_key.valid?(key_values = record.key)
|
61
|
+
identity_map = repository.identity_map(model)
|
62
|
+
identity_map[key_values]
|
63
|
+
end
|
64
|
+
|
65
|
+
resource ||= model.allocate
|
66
|
+
|
67
|
+
fields.each do |property|
|
68
|
+
next if no_reload && property.loaded?(resource)
|
69
|
+
|
70
|
+
property.set!(resource, property.get!(record))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
resource.instance_variable_set(:@_repository, repository)
|
75
|
+
|
76
|
+
if identity_map
|
77
|
+
resource.persisted_state = Resource::State::Clean.new(resource) unless resource.persisted_state?
|
78
|
+
|
79
|
+
# defer setting the IdentityMap so second level caches can
|
80
|
+
# record the state of the resource after loaded
|
81
|
+
identity_map[key_values] = resource
|
82
|
+
else
|
83
|
+
resource.persisted_state = Resource::State::Immutable.new(resource)
|
84
|
+
end
|
85
|
+
|
86
|
+
resource
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
module LdapResource
|
91
|
+
|
92
|
+
Model.append_inclusions self
|
93
|
+
|
94
|
+
# authenticate the current resource against the stored password
|
95
|
+
# @param [String] password to authenticate
|
96
|
+
# @return [TrueClass, FalseClass] whether password was right or wrong
|
97
|
+
def authenticate(password)
|
98
|
+
ldap.authenticate(ldap.dn(self.class.dn_prefix(self),
|
99
|
+
self.class.treebase),
|
100
|
+
password)
|
101
|
+
end
|
102
|
+
|
9
103
|
# if called without parameter or block the given properties get returned.
|
10
|
-
# if called with a block then the block gets stored. if called with new
|
104
|
+
# if called with a block then the block gets stored. if called with new
|
11
105
|
# properties they get stored. if called with a Resource then either the
|
12
106
|
# stored block gets called with that Resource or the stored properties get
|
13
107
|
# returned.
|
@@ -27,9 +121,9 @@ module DataMapper
|
|
27
121
|
@ldap_properties = block
|
28
122
|
end
|
29
123
|
end
|
30
|
-
|
124
|
+
|
31
125
|
# if called without parameter or block the given treebase gets returned.
|
32
|
-
# if called with a block then the block gets stored. if called with a
|
126
|
+
# if called with a block then the block gets stored. if called with a
|
33
127
|
# String then it gets stored. if called with a Resource then either the
|
34
128
|
# stored block gets called with that Resource or the stored String gets
|
35
129
|
# returned.
|
@@ -53,9 +147,9 @@ module DataMapper
|
|
53
147
|
end
|
54
148
|
end
|
55
149
|
end
|
56
|
-
|
150
|
+
|
57
151
|
# if called without parameter or block the given dn_prefix gets returned.
|
58
|
-
# if called with a block then the block gets stored. if called with a
|
152
|
+
# if called with a block then the block gets stored. if called with a
|
59
153
|
# String then it gets stored. if called with a Resource then either the
|
60
154
|
# stored block gets called with that Resource or the stored String gets
|
61
155
|
# returned.
|
@@ -75,8 +169,8 @@ module DataMapper
|
|
75
169
|
@ldap_dn = block
|
76
170
|
end
|
77
171
|
end
|
78
|
-
|
79
|
-
# if called without parameter then the stored field gets returned
|
172
|
+
|
173
|
+
# if called without parameter then the stored field gets returned
|
80
174
|
# otherwise the given parameters gets stored
|
81
175
|
# @param [Symbol, String] field a new multivalue_field
|
82
176
|
# @return [Symbol] the multivalue_field
|
@@ -87,23 +181,16 @@ module DataMapper
|
|
87
181
|
@ldap_multivalue_field = field.to_sym
|
88
182
|
end
|
89
183
|
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# authenticate the current resource against the stored password
|
93
|
-
# @param [String] password to authenticate
|
94
|
-
# @return [TrueClass, FalseClass] whether password was right or wrong
|
95
|
-
def authenticate(password)
|
96
|
-
ldap.authenticate(ldap.dn(self.class.dn_prefix(self),
|
97
|
-
self.class.treebase),
|
98
|
-
password)
|
99
|
-
end
|
100
184
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
185
|
+
private
|
186
|
+
# short cut to the ldap facade
|
187
|
+
# @return [Ldap::LdapFacade]
|
188
|
+
def ldap
|
189
|
+
raise "not an ldap adapter #{repository.adapter.name}" unless repository.adapter.respond_to? :ldap
|
190
|
+
repository.adapter.ldap
|
191
|
+
end
|
107
192
|
end
|
193
|
+
|
194
|
+
include LdapResource
|
108
195
|
end
|
109
196
|
end
|
@@ -1,164 +1,163 @@
|
|
1
1
|
$LOAD_PATH << File.dirname(__FILE__)
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
|
5
|
-
:default,
|
6
|
-
:ldap,
|
7
|
-
:memory
|
8
|
-
].each do |adapter|
|
9
|
-
|
10
|
-
describe "A #{DataMapper.repository(adapter).adapter.class.name}" do
|
11
|
-
|
12
|
-
puts "#{DataMapper.repository(adapter).adapter.class.name}"
|
13
|
-
|
14
|
-
before do
|
4
|
+
describe DataMapper::Adapters::LdapAdapter do
|
15
5
|
|
16
|
-
|
17
|
-
User.all(:login.like => "b%").destroy!
|
18
|
-
Group.all(:name.like => "test_%").destroy!
|
19
|
-
@user1 = User.create(:login => "black", :name => 'Black', :age => 0)
|
20
|
-
@user2 = User.create(:login => "brown", :name => 'Brown', :age => 25)
|
21
|
-
@user3 = User.create(:login => "blue", :name => 'Blue', :age => nil)
|
22
|
-
|
23
|
-
@group1 = Group.create(:name => "test_root_group")
|
24
|
-
@group2 = Group.create(:name => "test_admin_group")
|
25
|
-
end
|
26
|
-
end
|
6
|
+
before do
|
27
7
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
8
|
+
DataMapper.repository(:ldap) do
|
9
|
+
User.all(:login.like => "b%").destroy!
|
10
|
+
Group.all(:name.like => "test_%").destroy!
|
11
|
+
@user1 = User.create(:login => "black", :name => 'Black', :age => 0)
|
12
|
+
@user2 = User.create(:login => "brown", :name => 'Brown', :age => 25)
|
13
|
+
@user3 = User.create(:login => "blue", :name => 'Blue', :age => nil)
|
33
14
|
|
34
|
-
|
35
|
-
|
36
|
-
end
|
15
|
+
@group1 = Group.create(:name => "test_root_group")
|
16
|
+
@group2 = Group.create(:name => "test_admin_group")
|
37
17
|
end
|
18
|
+
end
|
38
19
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
20
|
+
it 'should successfully save an object' do
|
21
|
+
DataMapper.repository(:ldap) do
|
22
|
+
@group1.new?.should be_false
|
43
23
|
end
|
24
|
+
end
|
44
25
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
26
|
+
it 'should be able to get the object' do
|
27
|
+
DataMapper.repository(:ldap) do
|
28
|
+
Group.get(@group1.id).should == @group1
|
49
29
|
end
|
30
|
+
end
|
50
31
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
32
|
+
it 'should be able to get all the objects' do
|
33
|
+
DataMapper.repository(:ldap) do
|
34
|
+
Group.all(:name.like => "test_%").should == [@group1, @group2]
|
55
35
|
end
|
36
|
+
end
|
56
37
|
|
57
|
-
|
58
|
-
|
38
|
+
it 'should be able to have a user' do
|
39
|
+
DataMapper.repository(:ldap) do
|
40
|
+
begin
|
41
|
+
gu = GroupUser.new(:user_id => @user1.id, :group_id => @group1.id)
|
59
42
|
# the next load prevent strange errors
|
60
43
|
@user1 = User.get!(@user1.id)
|
61
44
|
@user1.groups << @group1
|
62
45
|
@user1.save
|
63
46
|
User.get(@user1.id).groups.should == [@group1]
|
47
|
+
rescue => e
|
48
|
+
puts e
|
49
|
+
puts e.backtrace.join "\n\t"
|
50
|
+
raise e
|
64
51
|
end
|
65
52
|
end
|
53
|
+
end
|
66
54
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
55
|
+
it 'should be able to delete a user' do
|
56
|
+
DataMapper.repository(:ldap) do
|
57
|
+
# the next load prevent strange errors
|
58
|
+
@user1 = User.get!(@user1.id)
|
59
|
+
@user1.groups << @group1
|
60
|
+
@user1.save
|
61
|
+
@user1.groups.delete(@group1)
|
62
|
+
@user1.save
|
63
|
+
User.get(@user1.id).groups.should == []
|
64
|
+
@user1.groups << @group1
|
65
|
+
@user1.groups << @group2
|
66
|
+
@user1.save
|
67
|
+
@user1.groups.delete(@group1)
|
68
|
+
@user1.save
|
69
|
+
User.get(@user1.id).groups.should == [@group2]
|
83
70
|
end
|
71
|
+
end
|
84
72
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
73
|
+
it 'should be able to have users and remove them again' do
|
74
|
+
DataMapper.repository(:ldap) do
|
75
|
+
# the next load prevent strange errors
|
76
|
+
@user1 = User.get!(@user1.id)
|
77
|
+
@user1.groups << @group1
|
78
|
+
@user1.save
|
79
|
+
User.get(@user1.id).groups.should == [@group1]
|
80
|
+
@user1.groups << @group2
|
81
|
+
@user1.save
|
82
|
+
User.get(@user1.id)
|
83
|
+
@user1.groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
84
|
+
@user1.groups.delete(@group1)
|
85
|
+
@user1.save
|
86
|
+
User.get(@user1.id).groups.should == [@group2]
|
87
|
+
@user1.groups.delete(@group2)
|
88
|
+
@user1.save
|
89
|
+
User.get(@user1.id).groups.should == []
|
103
90
|
end
|
91
|
+
end
|
104
92
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
DataMapper.repository(adapter) do
|
117
|
-
User.get(@user2.id).groups.should == [@group1]
|
118
|
-
User.get(@user1.id).groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
119
|
-
end
|
93
|
+
it 'should be able to have two users' do
|
94
|
+
DataMapper.repository(:ldap) do
|
95
|
+
# the next load prevent strange errors
|
96
|
+
@user1 = User.get!(@user1.id)
|
97
|
+
@user1.groups << @group1
|
98
|
+
@user1.groups << @group2
|
99
|
+
@user1.save
|
100
|
+
User.get(@user1.id).groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
101
|
+
@user2.groups << @group1
|
102
|
+
@user2.save
|
120
103
|
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
User.get!(4711)
|
125
|
-
end.should raise_error(DataMapper::ObjectNotFoundError)
|
104
|
+
DataMapper.repository(:ldap) do
|
105
|
+
User.get(@user2.id).groups.should == [@group1]
|
106
|
+
User.get(@user1.id).groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
126
107
|
end
|
108
|
+
end
|
127
109
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
110
|
+
it 'should raise an not found error' do
|
111
|
+
lambda do
|
112
|
+
User.get!(4711)
|
113
|
+
end.should raise_error(DataMapper::ObjectNotFoundError)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should be able to have two users in one group' do
|
117
|
+
DataMapper.repository(:ldap) do
|
118
|
+
@user1 = User.get!(@user1.id)
|
119
|
+
@user1.groups << @group1
|
120
|
+
@user1.groups << @group2
|
121
|
+
@user1.groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
122
|
+
@user2.groups << @group1
|
140
123
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
size = GroupUser.all.size
|
145
|
-
@user1 = User.get!(@user1.id)
|
146
|
-
@user1.groups << @group1
|
147
|
-
@user1.groups << @group2
|
148
|
-
@user2.groups << @group1
|
149
|
-
GroupUser.all.size.should == size + 3
|
150
|
-
end
|
151
|
-
DataMapper.repository(adapter) do
|
152
|
-
@user1 = User.get!(@user1.id)
|
153
|
-
@user1.groups.delete(@group1)
|
154
|
-
User.get(@user1.id).groups.should == [@group2]
|
155
|
-
User.get(@user2.id).groups.should == [@group1]
|
156
|
-
@user2 = User.get!(@user2.id)
|
157
|
-
@user2.groups.delete(@group1)
|
158
|
-
User.get(@user1.id).groups.should == [@group2]
|
159
|
-
User.get(@user2.id).groups.should == []
|
160
|
-
end
|
124
|
+
DataMapper.repository(:ldap) do
|
125
|
+
User.get(@user1.id).groups.sort{|g1, g2| g1.id <=> g2.id}.should == [@group1, @group2]
|
126
|
+
User.get(@user2.id).groups.should == [@group1]
|
161
127
|
end
|
128
|
+
end
|
162
129
|
|
130
|
+
it 'should be able to delete a user from a group' do
|
131
|
+
DataMapper.repository(:ldap) do
|
132
|
+
size = GroupUser.all.size
|
133
|
+
@user1 = User.get!(@user1.id)
|
134
|
+
@user1.groups << @group1
|
135
|
+
@user1.groups << @group2
|
136
|
+
@user2.groups << @group1
|
137
|
+
GroupUser.all.size.should == size + 3
|
138
|
+
end
|
139
|
+
DataMapper.repository(:ldap) do
|
140
|
+
puts
|
141
|
+
puts "--------------"
|
142
|
+
p User.get(@user1.id).groups
|
143
|
+
puts "--------------"
|
144
|
+
p User.get(@user2.id).groups
|
145
|
+
puts
|
146
|
+
@user1 = User.get!(@user1.id)
|
147
|
+
@user1.groups.delete(@group1)
|
148
|
+
puts
|
149
|
+
puts "--------------"
|
150
|
+
p User.get(@user1.id).groups
|
151
|
+
puts "--------------"
|
152
|
+
p User.get(@user2.id).groups
|
153
|
+
puts
|
154
|
+
User.get(@user1.id).groups.should == [@group2]
|
155
|
+
User.get(@user2.id).groups.should == [@group1]
|
156
|
+
@user2 = User.get!(@user2.id)
|
157
|
+
@user2.groups.delete(@group1)
|
158
|
+
User.get(@user1.id).groups.should == [@group2]
|
159
|
+
User.get(@user2.id).groups.should == []
|
160
|
+
end
|
163
161
|
end
|
162
|
+
|
164
163
|
end
|
@@ -7,18 +7,13 @@ describe DataMapper.repository(:ldap).adapter do
|
|
7
7
|
|
8
8
|
before do
|
9
9
|
DataMapper.repository(:ldap) do
|
10
|
+
User.all.destroy!
|
10
11
|
@user = User.new(:login => "beige", :name => 'Beige')
|
11
12
|
@user.password = "asd123"
|
12
13
|
@user.save
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
after do
|
17
|
-
DataMapper.repository(:ldap) do
|
18
|
-
@user.destroy
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
17
|
it 'should successfully authenticate' do
|
23
18
|
DataMapper.repository(:ldap) do
|
24
19
|
@user.authenticate("asd123").should be_true
|