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.
@@ -0,0 +1,95 @@
1
+ require 'net/ldap'
2
+
3
+ module Ldap
4
+ class Conditions2Filter
5
+
6
+ @@logger = ::Slf4r::LoggerFacade.new(::Ldap::Conditions2Filter)
7
+
8
+ # @param Array of conditions for the search
9
+ # @return Array of Hashes with a name/values pair for each attribute
10
+ def self.convert(conditions)
11
+ @@logger.debug { "conditions #{conditions.inspect}" }
12
+ filters = []
13
+ conditions.each do |cond|
14
+ c = cond[2]
15
+ case cond[0]
16
+ when :or_operator
17
+ f = nil
18
+ cond[1].each do |cc|
19
+ ff = case cc[0]
20
+ when :eql
21
+ Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s )
22
+ when :gte
23
+ Net::LDAP::Filter.ge( cc[1].to_s, cc[2].to_s )
24
+ when :lte
25
+ Net::LDAP::Filter.le( cc[1].to_s, cc[2].to_s )
26
+ when :like
27
+ Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
28
+ else
29
+ logger.error(cc[0].to_s + " needs coding")
30
+ end
31
+ if f
32
+ f = f | ff
33
+ else
34
+ f = ff
35
+ end
36
+ end
37
+ when :eql
38
+ if c.nil?
39
+ f = ~ Net::LDAP::Filter.pres( cond[1].to_s )
40
+ elsif c.respond_to? :each
41
+ f = nil
42
+ c.each do |cc|
43
+ if f
44
+ f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
45
+ else
46
+ f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
47
+ end
48
+ end
49
+ #elsif c.class == Range
50
+ # p c
51
+ # f = Net::LDAP::Filter.ge( cond[1].to_s, c.begin.to_s ) & Net::LDAP::Filter.le( cond[1].to_s, c.end.to_s )
52
+ else
53
+ f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
54
+ end
55
+ when :gte
56
+ f = Net::LDAP::Filter.ge( cond[1].to_s, c.to_s )
57
+ when :lte
58
+ f = Net::LDAP::Filter.le( cond[1].to_s, c.to_s )
59
+ when :not
60
+ if c.nil?
61
+ f = Net::LDAP::Filter.pres( cond[1].to_s )
62
+ elsif c.respond_to? :each
63
+ f = nil
64
+ c.each do |cc|
65
+ if f
66
+ f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
67
+ else
68
+ f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
69
+ end
70
+ end
71
+ f = ~ f
72
+ else
73
+ f = ~ Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
74
+ end
75
+ when :like
76
+ f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
77
+ else
78
+ logger.error(cond[0].to_s + " needs coding")
79
+ end
80
+ filters << f if f
81
+ end
82
+
83
+ filter = nil
84
+ filters.each do |f|
85
+ if filter.nil?
86
+ filter = f
87
+ else
88
+ filter = filter & f
89
+ end
90
+ end
91
+ @@logger.debug { "search filter: (#{filter.to_s})" }
92
+ filter
93
+ end
94
+ end
95
+ end
data/lib/ldap/digest.rb CHANGED
@@ -6,9 +6,9 @@ module Ldap
6
6
  # @param salt String the salt for the password digester
7
7
  # @return the encoded password/salt
8
8
  def self.ssha(secret, salt)
9
- require 'sha1'
10
- require 'base64'
11
- (salt.empty? ? "{SHA}": "{SSHA}") +
9
+ require 'sha1'
10
+ require 'base64'
11
+ (salt.empty? ? "{SHA}": "{SSHA}") +
12
12
  Base64.encode64(::Digest::SHA1.digest(secret + salt) + salt).gsub(/\n/, '')
13
13
  end
14
14
 
@@ -1,15 +1,16 @@
1
1
  require 'net/ldap'
2
+ require 'ldap/conditions_2_filter'
2
3
 
3
4
  module Ldap
4
5
  class NetLdapFacade
5
-
6
+
6
7
  # @param config Hash for the ldap connection
7
8
  def self.open(config)
8
9
  Net::LDAP.open( config ) do |ldap|
9
10
  yield ldap
10
11
  end
11
12
  end
12
-
13
+
13
14
  include ::Slf4r::Logger
14
15
 
15
16
  # @param config Hash for the ldap connection
@@ -25,8 +26,8 @@ module Ldap
25
26
  base = "#{treebase},#{@ldap.base}"
26
27
  id_sym = key_field.downcase.to_sym
27
28
  max = 0
28
- @ldap.search( :base => base,
29
- :attributes => [key_field],
29
+ @ldap.search( :base => base,
30
+ :attributes => [key_field],
30
31
  :return_result => false ) do |entry|
31
32
  n = entry[id_sym].first.to_i
32
33
  max = n if max < n
@@ -41,12 +42,12 @@ module Ldap
41
42
  # @return nil in case of an error or the new id of the created object
42
43
  def create_object(dn_prefix, treebase, key_field, props, silence = false)
43
44
  base = "#{treebase},#{@ldap.base}"
44
- if @ldap.add( :dn => dn(dn_prefix, treebase),
45
- :attributes => props) and @ldap.get_operation_result.code.to_s == "0"
45
+ if @ldap.add( :dn => dn(dn_prefix, treebase),
46
+ :attributes => props) || @ldap.get_operation_result.code.to_s == "0"
46
47
  props[key_field.downcase.to_sym]
47
48
  else
48
49
  unless silence
49
- msg = ldap_error("create",
50
+ msg = ldap_error("create",
50
51
  dn(dn_prefix, treebase)) + "\n\t#{props.inspect}"
51
52
  # TODO maybe raise always an error
52
53
  if @ldap.get_operation_result.code.to_s == "68"
@@ -64,102 +65,19 @@ module Ldap
64
65
  # @param Array of conditions for the search
65
66
  # @return Array of Hashes with a name/values pair for each attribute
66
67
  def read_objects(treebase, key_fields, conditions, field_names, order_field = nil)
67
- filters = []
68
- conditions.each do |cond|
69
- c = cond[2]
70
- case cond[0]
71
- when :or_operator
72
- f = nil
73
- cond[1].each do |cc|
74
- ff = case cc[0]
75
- when :eql
76
- Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s )
77
- when :gte
78
- Net::LDAP::Filter.ge( cc[1].to_s, cc[2].to_s )
79
- when :lte
80
- Net::LDAP::Filter.le( cc[1].to_s, cc[2].to_s )
81
- when :like
82
- Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
83
- else
84
- logger.error(cc[0].to_s + " needs coding")
85
- end
86
- if f
87
- f = f | ff
88
- else
89
- f = ff
90
- end
91
- end
92
- when :eql
93
- if c.nil?
94
- f = ~ Net::LDAP::Filter.pres( cond[1].to_s )
95
- elsif c.class == Array
96
- f = nil
97
- c.each do |cc|
98
- if f
99
- f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
100
- else
101
- f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
102
- end
103
- end
104
- #elsif c.class == Range
105
- # p c
106
- # f = Net::LDAP::Filter.ge( cond[1].to_s, c.begin.to_s ) & Net::LDAP::Filter.le( cond[1].to_s, c.end.to_s )
107
- else
108
- f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
109
- end
110
- when :gte
111
- f = Net::LDAP::Filter.ge( cond[1].to_s, c.to_s )
112
- when :lte
113
- f = Net::LDAP::Filter.le( cond[1].to_s, c.to_s )
114
- when :not
115
- if c.nil?
116
- f = Net::LDAP::Filter.pres( cond[1].to_s )
117
- elsif c.class == Array
118
- f = nil
119
- c.each do |cc|
120
- if f
121
- f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
122
- else
123
- f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
124
- end
125
- end
126
- f = ~ f
127
- else
128
- f = ~ Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
129
- end
130
- when :like
131
- f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
132
- else
133
- logger.error(cond[0].to_s + " needs coding")
134
- end
135
- filters << f if f
136
- end
137
-
138
- filter = nil
139
- filters.each do |f|
140
- if filter.nil?
141
- filter = f
142
- else
143
- filter = filter & f
144
- end
145
- end
146
- logger.debug { "search filter: (#{filter.to_s})" }
147
68
  result = []
69
+ filter = Conditions2Filter.convert(conditions)
148
70
  @ldap.search( :base => "#{treebase},#{@ldap.base}",
149
71
  :attributes => field_names,
150
72
  :filter => filter ) do |res|
151
- map = to_map(res)
73
+ map = to_map(res)
152
74
  #puts map[key_field.to_sym]
153
75
  # TODO maybe make filter which removes this unless
154
76
  # TODO move this into the ldap_Adapter to make it more general, so that
155
77
  # all field with Integer gets converted, etc
156
- result << map if key_fields.select do |key_field|
157
- if map.member? key_field.to_sym
158
- # convert field to integer
159
- map[key_field.to_sym] = [map[key_field.to_sym].collect { |k| k.to_i != 0 ? k.to_s : k }].flatten
160
- true
161
- end
162
- end.size > 0 # i.e. there was at least one key_field in the map
78
+ result << map if key_fields.detect do |key_field|
79
+ map.member? key_field.to_sym
80
+ end
163
81
  end
164
82
  result
165
83
  end
@@ -170,11 +88,11 @@ module Ldap
170
88
  # @param actions the add/replace/delete actions on the attributes
171
89
  # @return nil in case of an error or true
172
90
  def update_object(dn_prefix, treebase, actions)
173
- if @ldap.modify( :dn => dn(dn_prefix, treebase),
174
- :operations => actions )
91
+ if @ldap.modify( :dn => dn(dn_prefix, treebase),
92
+ :operations => actions ) || @ldap.get_operation_result.code.to_s == "0"
175
93
  true
176
94
  else
177
- logger.warn(ldap_error("update",
95
+ logger.warn(ldap_error("update",
178
96
  dn(dn_prefix, treebase) + "\n\t#{actions.inspect}"))
179
97
  nil
180
98
  end
@@ -187,24 +105,24 @@ module Ldap
187
105
  if @ldap.delete( :dn => dn(dn_prefix, treebase) )
188
106
  true
189
107
  else
190
- logger.warn(ldap_error("delete",
108
+ logger.warn(ldap_error("delete",
191
109
  dn(dn_prefix, treebase)))
192
-
110
+
193
111
  nil
194
112
  end
195
113
  end
196
114
 
197
-
115
+
198
116
  # @param dn String for identifying the ldap object
199
117
  # @param password String to be used for authenticate to the dn
200
118
  def authenticate(dn, password)
201
- Net::LDAP.new( { :host => @ldap.host,
202
- :port => @ldap.port,
203
- :auth => {
204
- :method => :simple,
205
- :username => dn,
206
- :password => password
207
- },
119
+ Net::LDAP.new( { :host => @ldap.host,
120
+ :port => @ldap.port,
121
+ :auth => {
122
+ :method => :simple,
123
+ :username => dn,
124
+ :password => password
125
+ },
208
126
  :base => @ldap.base
209
127
  } ).bind
210
128
  end
@@ -218,7 +136,7 @@ module Ldap
218
136
  end
219
137
 
220
138
  private
221
-
139
+
222
140
  # helper to extract the Hash from the ldap search result
223
141
  # @param Entry from the ldap_search
224
142
  # @return Hash with name/value pairs of the entry
@@ -228,7 +146,7 @@ module Ldap
228
146
  end
229
147
  entry.map
230
148
  end
231
-
149
+
232
150
  def ldap_error(method, dn)
233
151
  "#{method} error: (#{@ldap.get_operation_result.code}) #{@ldap.get_operation_result.message}\n\tDN: #{dn}"
234
152
  end
@@ -1,6 +1,6 @@
1
1
  require 'ldap'
2
- require 'net/ldap'
3
2
  require 'slf4r'
3
+ require 'ldap/conditions_2_filter'
4
4
 
5
5
  module Ldap
6
6
  class Connection < LDAP::Conn
@@ -14,11 +14,11 @@ module Ldap
14
14
  @host = config[:host]
15
15
  set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
16
16
  end
17
-
17
+
18
18
  end
19
19
 
20
20
  class RubyLdapFacade
21
-
21
+
22
22
  # @param config Hash for the ldap connection
23
23
  def self.open(config)
24
24
  ldap2 = Connection.new(config)
@@ -26,7 +26,7 @@ module Ldap
26
26
  yield ldap
27
27
  end
28
28
  end
29
-
29
+
30
30
  include ::Slf4r::Logger
31
31
 
32
32
  # @param config Hash for the ldap connection
@@ -41,9 +41,9 @@ module Ldap
41
41
 
42
42
  def retrieve_next_id(treebase, key_field)
43
43
  max = 0
44
- @ldap2.search("#{treebase},#{@ldap2.base}",
45
- LDAP::LDAP_SCOPE_SUBTREE,
46
- "(objectclass=*)",
44
+ @ldap2.search("#{treebase},#{@ldap2.base}",
45
+ LDAP::LDAP_SCOPE_SUBTREE,
46
+ "(objectclass=*)",
47
47
  [key_field]) do |entry|
48
48
  n = (entry.vals(key_field) || [0]).first.to_i
49
49
  max = n if max < n
@@ -59,14 +59,14 @@ module Ldap
59
59
  def create_object(dn_prefix, treebase, key_field, props, silence = false)
60
60
  base = "#{treebase},#{@ldap2.base}"
61
61
  mods = props.collect do |k,v|
62
- LDAP.mod(LDAP::LDAP_MOD_ADD, k.to_s, v.is_a?(Array) ? v : [v.to_s] )
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
65
  # :attributes => props) and @ldap.get_operation_result.code.to_s == "0"
66
66
  props[key_field.downcase.to_sym]
67
67
  else
68
68
  unless silence
69
- msg = ldap_error("create",
69
+ msg = ldap_error("create",
70
70
  dn(dn_prefix, treebase)) + "\n\t#{props.inspect}"
71
71
  # TODO maybe raise always an error
72
72
  if @ldap2.get_operation_result.code.to_s == "68"
@@ -83,109 +83,24 @@ module Ldap
83
83
  # @param key_fields Array of fields which carries the integer unique id(s) of the entity
84
84
  # @param Array of conditions for the search
85
85
  # @return Array of Hashes with a name/values pair for each attribute
86
- def read_objects(treebase, key_fields, conditions, field_names, order_field = '')
87
- filters = []
88
- conditions.each do |cond|
89
- c = cond[2]
90
- case cond[0]
91
- when :or_operator
92
- f = nil
93
- cond[1].each do |cc|
94
- ff = case cc[0]
95
- when :eql
96
- Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s )
97
- when :gte
98
- Net::LDAP::Filter.ge( cc[1].to_s, cc[2].to_s )
99
- when :lte
100
- Net::LDAP::Filter.le( cc[1].to_s, cc[2].to_s )
101
- when :like
102
- Net::LDAP::Filter.eq( cc[1].to_s, cc[2].to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
103
- else
104
- logger.error(cc[0].to_s + " needs coding")
105
- end
106
- if f
107
- f = f | ff
108
- else
109
- f = ff
110
- end
111
- end
112
- when :eql
113
- if c.nil?
114
- f = ~ Net::LDAP::Filter.pres( cond[1].to_s )
115
- elsif c.class == Array
116
- f = nil
117
- c.each do |cc|
118
- if f
119
- f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
120
- else
121
- f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
122
- end
123
- end
124
- #elsif c.class == Range
125
- # p c
126
- # f = Net::LDAP::Filter.ge( cond[1].to_s, c.begin.to_s ) & Net::LDAP::Filter.le( cond[1].to_s, c.end.to_s )
127
- else
128
- f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
129
- end
130
- when :gte
131
- f = Net::LDAP::Filter.ge( cond[1].to_s, c.to_s )
132
- when :lte
133
- f = Net::LDAP::Filter.le( cond[1].to_s, c.to_s )
134
- when :not
135
- if c.nil?
136
- f = Net::LDAP::Filter.pres( cond[1].to_s )
137
- elsif c.class == Array
138
- f = nil
139
- c.each do |cc|
140
- if f
141
- f = f | Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
142
- else
143
- f = Net::LDAP::Filter.eq( cond[1].to_s, cc.to_s )
144
- end
145
- end
146
- f = ~ f
147
- else
148
- f = ~ Net::LDAP::Filter.eq( cond[1].to_s, c.to_s )
149
- end
150
- when :like
151
- f = Net::LDAP::Filter.eq( cond[1].to_s, c.to_s.gsub(/%/, "*").gsub(/_/, "*").gsub(/\*\*/, "*") )
152
- else
153
- logger.error(cond[0].to_s + " needs coding")
154
- end
155
- filters << f if f
156
- end
157
-
158
- filter = nil
159
- filters.each do |f|
160
- if filter.nil?
161
- filter = f
162
- else
163
- filter = filter & f
164
- end
165
- end
166
- logger.debug { "search filter: (#{filter.to_s})" }
86
+ def read_objects(treebase, key_fields, conditions, field_names, order_field = '')
87
+ filter = Conditions2Filter.convert(conditions)
167
88
  result = []
168
89
  begin
169
- @ldap2.search("#{treebase},#{@ldap2.base}",
170
- LDAP::LDAP_SCOPE_SUBTREE,
171
- filter.to_s == "" ? "(objectclass=*)" : filter.to_s.gsub(/\(\(/, "(").gsub(/\)\)/, ")"),
90
+ @ldap2.search("#{treebase},#{@ldap2.base}",
91
+ LDAP::LDAP_SCOPE_SUBTREE,
92
+ filter.to_s == "" ? "(objectclass=*)" : filter.to_s.gsub(/\(\(/, "(").gsub(/\)\)/, ")"),
172
93
  field_names, false, 0, 0, order_field) do |res|
173
94
 
174
- map = to_map(res)
95
+ map = to_map(res)
175
96
  #puts map[key_field.to_sym]
176
97
  # TODO maybe make filter which removes this unless
177
98
  # TODO move this into the ldap_Adapter to make it more general, so that
178
99
  # all field with Integer gets converted, etc
179
- result << map if key_fields.select do |key_field|
180
- if map.member? key_field.to_sym
181
- # convert field to integer
182
- map[key_field.to_sym] = [map[key_field.to_sym].collect { |k| k.to_i != 0 ? k.to_s : k }].flatten
183
- true
100
+ result << map if key_fields.detect do |key_field|
101
+ map.member? key_field.to_sym
184
102
  end
185
- end.size > 0 # i.e. there was at least one key_field in the map
186
103
  end
187
- rescue RuntimeError => e
188
- raise e unless e.message == "no result returned by search"
189
104
  end
190
105
  result
191
106
  end
@@ -207,11 +122,11 @@ module Ldap
207
122
  end
208
123
  LDAP.mod(mod_op, act[1].to_s, act[2] == [] ? [] : [act[2].to_s])
209
124
  end
210
- if @ldap2.modify( dn(dn_prefix, treebase),
125
+ if @ldap2.modify( dn(dn_prefix, treebase),
211
126
  mods )
212
127
  true
213
128
  else
214
- logger.warn(ldap_error("update",
129
+ logger.warn(ldap_error("update",
215
130
  dn(dn_prefix, treebase) + "\n\t#{actions.inspect}"))
216
131
  nil
217
132
  end
@@ -224,24 +139,24 @@ module Ldap
224
139
  if @ldap2.delete( dn(dn_prefix, treebase) )
225
140
  true
226
141
  else
227
- logger.warn(ldap_error("delete",
142
+ logger.warn(ldap_error("delete",
228
143
  dn(dn_prefix, treebase)))
229
-
144
+
230
145
  nil
231
146
  end
232
147
  end
233
148
 
234
-
149
+
235
150
  # @param dn String for identifying the ldap object
236
151
  # @param password String to be used for authenticate to the dn
237
152
  def authenticate(dn, password)
238
- Net::LDAP.new( { :host => @ldap2.host,
239
- :port => @ldap2.port,
240
- :auth => {
241
- :method => :simple,
242
- :username => dn,
243
- :password => password
244
- },
153
+ Net::LDAP.new( { :host => @ldap2.host,
154
+ :port => @ldap2.port,
155
+ :auth => {
156
+ :method => :simple,
157
+ :username => dn,
158
+ :password => password
159
+ },
245
160
  :base => @ldap2.base
246
161
  } ).bind
247
162
  end
@@ -255,7 +170,7 @@ module Ldap
255
170
  end
256
171
 
257
172
  private
258
-
173
+
259
174
  # helper to extract the Hash from the ldap search result
260
175
  # @param Entry from the ldap_search
261
176
  # @return Hash with name/value pairs of the entry
@@ -266,7 +181,7 @@ module Ldap
266
181
  end
267
182
  map
268
183
  end
269
-
184
+
270
185
  def ldap_error(method, dn)
271
186
  "#{method} error: (#{@ldap2.get_operation_result.code}) #{@ldap2.get_operation_result.message}\n\tDN: #{dn}"
272
187
  end
data/lib/ldap/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ldap
2
- VERSION = '0.3.5'.freeze
2
+ VERSION = '0.4.0.alpha1'.freeze
3
3
  end