dm-ldap-adapter 0.4.3-java
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/History.txt +75 -0
- data/MIT-LICENSE +20 -0
- data/README.md +247 -0
- data/ldap-commands.txt +17 -0
- data/lib/adapters/ldap_adapter.rb +370 -0
- data/lib/adapters/noop_transaction.rb +35 -0
- data/lib/dm-ldap-adapter.rb +1 -0
- data/lib/dummy_ldap_resource.rb +60 -0
- data/lib/ldap/array.rb +122 -0
- data/lib/ldap/conditions_2_filter.rb +95 -0
- data/lib/ldap/digest.rb +30 -0
- data/lib/ldap/net_ldap_facade.rb +161 -0
- data/lib/ldap/ruby_ldap_facade.rb +201 -0
- data/lib/ldap/transactions.rb +2 -0
- data/lib/ldap/unboundid_ldap_facade.rb +188 -0
- data/lib/ldap/version.rb +3 -0
- data/lib/ldap_resource.rb +189 -0
- data/spec/assiociations_ldap_adapter_spec.rb +179 -0
- data/spec/authentication_ldap_adapter_spec.rb +32 -0
- data/spec/contact.rb +58 -0
- data/spec/ldap_adapter_spec.rb +239 -0
- data/spec/ldap_array_spec.rb +119 -0
- data/spec/multi_repository_spec.rb +79 -0
- data/spec/multi_value_attributes_spec.rb +161 -0
- data/spec/performance_spec.rb.omit +67 -0
- data/spec/sorting_spec.rb +61 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +163 -0
- metadata +354 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'ldap'
|
2
|
+
require 'slf4r'
|
3
|
+
require 'ldap/conditions_2_filter'
|
4
|
+
|
5
|
+
module Ldap
|
6
|
+
class Connection < LDAP::Conn
|
7
|
+
|
8
|
+
attr_reader :base, :host, :port
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
super(config[:host], config[:port])
|
12
|
+
@base = config[:base]
|
13
|
+
@port = config[:port]
|
14
|
+
@host = config[:host]
|
15
|
+
set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class RubyLdapFacade
|
21
|
+
|
22
|
+
# @param config Hash for the ldap connection
|
23
|
+
def self.open(config)
|
24
|
+
ldap2 = Connection.new(config)
|
25
|
+
ldap2.bind(config[:auth][:username], config[:auth][:password]) do |ldap|
|
26
|
+
yield ldap
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
include ::Slf4r::Logger
|
31
|
+
|
32
|
+
# @param config Hash for the ldap connection
|
33
|
+
def initialize(config)
|
34
|
+
if config.is_a? Hash
|
35
|
+
@ldap2 = Connection.new(config)
|
36
|
+
@ldap2.bind(config[:auth][:username], config[:auth][:password])
|
37
|
+
else
|
38
|
+
@ldap2 = config
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def retrieve_next_id(treebase, key_field)
|
43
|
+
max = 0
|
44
|
+
@ldap2.search("#{treebase},#{@ldap2.base}",
|
45
|
+
LDAP::LDAP_SCOPE_SUBTREE,
|
46
|
+
"(objectclass=*)",
|
47
|
+
[key_field]) do |entry|
|
48
|
+
n = (entry.vals(key_field) || [0]).first.to_i
|
49
|
+
max = n if max < n
|
50
|
+
end
|
51
|
+
max + 1
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param dn_prefix String the prefix of the dn
|
55
|
+
# @param treebase the treebase of the dn or any search
|
56
|
+
# @param key_field field which carries the integer unique id of the entity
|
57
|
+
# @param props Hash of the ldap attributes of the new ldap object
|
58
|
+
# @return nil in case of an error or the new id of the created object
|
59
|
+
def create_object(dn_prefix, treebase, key_field, props, silence = false)
|
60
|
+
base = "#{treebase},#{@ldap2.base}"
|
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] )
|
63
|
+
end
|
64
|
+
if @ldap2.add( dn(dn_prefix, treebase), mods)
|
65
|
+
props[key_field.to_sym]
|
66
|
+
else
|
67
|
+
unless silence
|
68
|
+
msg = ldap_error("create",
|
69
|
+
dn(dn_prefix, treebase)) + "\n\t#{props.inspect}"
|
70
|
+
# TODO maybe raise always an error
|
71
|
+
if @ldap2.get_operation_result.code.to_s == "68"
|
72
|
+
raise ::DataMapper::PersistenceError.new(msg)
|
73
|
+
else
|
74
|
+
logger.warn(msg)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param treebase the treebase of the search
|
82
|
+
# @param key_fields Array of fields which carries the integer unique id(s) of the entity
|
83
|
+
# @param Array of conditions for the search
|
84
|
+
# @return Array of Hashes with a name/values pair for each attribute
|
85
|
+
def read_objects(treebase, key_fields, conditions, field_names, order_field = '')
|
86
|
+
|
87
|
+
if !conditions.nil? and conditions.size > 0
|
88
|
+
filter = Conditions2Filter.convert(conditions).to_s
|
89
|
+
else
|
90
|
+
filter = "(objectclass=*)"
|
91
|
+
end
|
92
|
+
|
93
|
+
result = []
|
94
|
+
begin
|
95
|
+
@ldap2.search("#{treebase},#{@ldap2.base}",
|
96
|
+
LDAP::LDAP_SCOPE_SUBTREE,
|
97
|
+
filter,
|
98
|
+
field_names, false, 0, 0, order_field) do |res|
|
99
|
+
mapp = to_map(field_names, res)
|
100
|
+
# TODO maybe make filter which removes this unless
|
101
|
+
# TODO move this into the ldap_Adapter to make it more general, so that
|
102
|
+
# all field with Integer gets converted, etc
|
103
|
+
# NOTE: somehow the fields are downcase coming from query.model
|
104
|
+
result << mapp if key_fields.detect do |key_field|
|
105
|
+
mapp.keys.detect {|k| k.to_s.downcase == key_field.downcase }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
result
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# @param dn_prefix String the prefix of the dn
|
114
|
+
# @param treebase the treebase of the dn or any search
|
115
|
+
# @param actions the add/replace/delete actions on the attributes
|
116
|
+
# @return nil in case of an error or true
|
117
|
+
def update_object(dn_prefix, treebase, actions)
|
118
|
+
mods = actions.collect do |act|
|
119
|
+
mod_op = case act[0]
|
120
|
+
when :add
|
121
|
+
LDAP::LDAP_MOD_ADD
|
122
|
+
when :replace
|
123
|
+
LDAP::LDAP_MOD_REPLACE
|
124
|
+
when :delete
|
125
|
+
LDAP::LDAP_MOD_DELETE
|
126
|
+
end
|
127
|
+
LDAP.mod(mod_op, act[1].to_s, act[2] == [] ? [] : [act[2].to_s])
|
128
|
+
end
|
129
|
+
if @ldap2.modify( dn(dn_prefix, treebase),
|
130
|
+
mods )
|
131
|
+
true
|
132
|
+
else
|
133
|
+
logger.warn(ldap_error("update",
|
134
|
+
dn(dn_prefix, treebase) + "\n\t#{actions.inspect}"))
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# @param dn_prefix String the prefix of the dn
|
140
|
+
# @param treebase the treebase of the dn or any search
|
141
|
+
# @return nil in case of an error or true
|
142
|
+
def delete_object(dn_prefix, treebase)
|
143
|
+
if @ldap2.delete( dn(dn_prefix, treebase) )
|
144
|
+
true
|
145
|
+
else
|
146
|
+
logger.warn(ldap_error("delete",
|
147
|
+
dn(dn_prefix, treebase)))
|
148
|
+
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# @param dn String for identifying the ldap object
|
155
|
+
# @param password String to be used for authenticate to the dn
|
156
|
+
def authenticate(dn, password)
|
157
|
+
bound = false
|
158
|
+
ldap_con = LDAP::Conn.new(@ldap2.host, @ldap2.port)
|
159
|
+
ldap_con.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )
|
160
|
+
begin
|
161
|
+
ldap_con.bind(dn, password, LDAP::LDAP_AUTH_SIMPLE) do
|
162
|
+
bound = true
|
163
|
+
end
|
164
|
+
rescue LDAP::ResultError => msg
|
165
|
+
if msg.to_s =~ /Invalid\ credentials/i
|
166
|
+
logger.info("Invalid Credentials: #{dn}")
|
167
|
+
else
|
168
|
+
logger.warn "Authentication Error: #{msg.to_s}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
bound
|
172
|
+
end
|
173
|
+
|
174
|
+
# helper to concat the dn from the various parts
|
175
|
+
# @param dn_prefix String the prefix of the dn
|
176
|
+
# @param treebase the treebase of the dn or any search
|
177
|
+
# @return the complete dn String
|
178
|
+
def dn(dn_prefix, treebase)
|
179
|
+
"#{dn_prefix},#{treebase},#{@ldap2.base}"
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# helper to extract the Hash from the ldap search result
|
185
|
+
# @param Entry from the ldap_search
|
186
|
+
# @return Hash with name/value pairs of the entry
|
187
|
+
def to_map(field_names, entry)
|
188
|
+
fields = {:dn => :dn}
|
189
|
+
field_names.each { |f| fields[f.downcase.to_sym] = f.to_sym }
|
190
|
+
map = {}
|
191
|
+
LDAP::entry2hash(entry).each do |k,v|
|
192
|
+
map[fields[k.downcase.to_sym]] = v
|
193
|
+
end
|
194
|
+
map
|
195
|
+
end
|
196
|
+
|
197
|
+
def ldap_error(method, dn)
|
198
|
+
"#{method} error: (#{@ldap2.get_operation_result.code}) #{@ldap2.get_operation_result.message}\n\tDN: #{dn}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'ldap'
|
2
|
+
require 'slf4r'
|
3
|
+
require 'ldap/conditions_2_filter'
|
4
|
+
|
5
|
+
module Ldap
|
6
|
+
# class Connection < LDAP::Conn
|
7
|
+
|
8
|
+
# attr_reader :base, :host, :port
|
9
|
+
|
10
|
+
# def initialize(config)
|
11
|
+
# super(config[:host], config[:port])
|
12
|
+
# @base = config[:base]
|
13
|
+
# @port = config[:port]
|
14
|
+
# @host = config[:host]
|
15
|
+
# set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
|
16
|
+
# end
|
17
|
+
|
18
|
+
# end
|
19
|
+
|
20
|
+
class RubyLdapFacade
|
21
|
+
|
22
|
+
# @param config Hash for the ldap connection
|
23
|
+
def self.open(config)
|
24
|
+
ldap3 = com.unboundid.ldap.sdk.LDAPConnection.new(config[:host], config[:port], config[:base] + "." + config[:auth][:username], config[:auth][:password])
|
25
|
+
|
26
|
+
yield ldap
|
27
|
+
end
|
28
|
+
|
29
|
+
include ::Slf4r::Logger
|
30
|
+
|
31
|
+
# @param config Hash for the ldap connection
|
32
|
+
def initialize(config)
|
33
|
+
if config.is_a? Hash
|
34
|
+
@ldap2 = Connection.new(config)
|
35
|
+
@ldap2.bind(config[:auth][:username], config[:auth][:password])
|
36
|
+
else
|
37
|
+
@ldap2 = config
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def retrieve_next_id(treebase, key_field)
|
42
|
+
max = 0
|
43
|
+
@ldap2.search("#{treebase},#{@ldap2.base}",
|
44
|
+
LDAP::LDAP_SCOPE_SUBTREE,
|
45
|
+
"(objectclass=*)",
|
46
|
+
[key_field]) do |entry|
|
47
|
+
n = (entry.vals(key_field) || [0]).first.to_i
|
48
|
+
max = n if max < n
|
49
|
+
end
|
50
|
+
max + 1
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param dn_prefix String the prefix of the dn
|
54
|
+
# @param treebase the treebase of the dn or any search
|
55
|
+
# @param key_field field which carries the integer unique id of the entity
|
56
|
+
# @param props Hash of the ldap attributes of the new ldap object
|
57
|
+
# @return nil in case of an error or the new id of the created object
|
58
|
+
def create_object(dn_prefix, treebase, key_field, props, silence = false)
|
59
|
+
base = "#{treebase},#{@ldap2.base}"
|
60
|
+
mods = props.collect do |k,v|
|
61
|
+
LDAP.mod(LDAP::LDAP_MOD_ADD, k.to_s, v.is_a?(::Array) ? v : [v.to_s] )
|
62
|
+
end
|
63
|
+
if @ldap2.add( dn(dn_prefix, treebase), mods)
|
64
|
+
# :attributes => props) and @ldap.get_operation_result.code.to_s == "0"
|
65
|
+
props[key_field.downcase.to_sym]
|
66
|
+
else
|
67
|
+
unless silence
|
68
|
+
msg = ldap_error("create",
|
69
|
+
dn(dn_prefix, treebase)) + "\n\t#{props.inspect}"
|
70
|
+
# TODO maybe raise always an error
|
71
|
+
if @ldap2.get_operation_result.code.to_s == "68"
|
72
|
+
raise ::DataMapper::PersistenceError.new(msg)
|
73
|
+
else
|
74
|
+
logger.warn(msg)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param treebase the treebase of the search
|
82
|
+
# @param key_fields Array of fields which carries the integer unique id(s) of the entity
|
83
|
+
# @param Array of conditions for the search
|
84
|
+
# @return Array of Hashes with a name/values pair for each attribute
|
85
|
+
def read_objects(treebase, key_fields, conditions, field_names, order_field = '')
|
86
|
+
filter = Conditions2Filter.convert(conditions)
|
87
|
+
result = []
|
88
|
+
begin
|
89
|
+
@ldap2.search("#{treebase},#{@ldap2.base}",
|
90
|
+
LDAP::LDAP_SCOPE_SUBTREE,
|
91
|
+
filter.to_s == "" ? "(objectclass=*)" : filter.to_s.gsub(/\(\(/, "(").gsub(/\)\)/, ")"),
|
92
|
+
field_names, false, 0, 0, order_field) do |res|
|
93
|
+
|
94
|
+
map = to_map(res)
|
95
|
+
#puts map[key_field.to_sym]
|
96
|
+
# TODO maybe make filter which removes this unless
|
97
|
+
# TODO move this into the ldap_Adapter to make it more general, so that
|
98
|
+
# all field with Integer gets converted, etc
|
99
|
+
result << map if key_fields.detect do |key_field|
|
100
|
+
map.member? key_field.to_sym
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
result
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
# @param dn_prefix String the prefix of the dn
|
109
|
+
# @param treebase the treebase of the dn or any search
|
110
|
+
# @param actions the add/replace/delete actions on the attributes
|
111
|
+
# @return nil in case of an error or true
|
112
|
+
def update_object(dn_prefix, treebase, actions)
|
113
|
+
mods = actions.collect do |act|
|
114
|
+
mod_op = case act[0]
|
115
|
+
when :add
|
116
|
+
LDAP::LDAP_MOD_ADD
|
117
|
+
when :replace
|
118
|
+
LDAP::LDAP_MOD_REPLACE
|
119
|
+
when :delete
|
120
|
+
LDAP::LDAP_MOD_DELETE
|
121
|
+
end
|
122
|
+
LDAP.mod(mod_op, act[1].to_s, act[2] == [] ? [] : [act[2].to_s])
|
123
|
+
end
|
124
|
+
if @ldap2.modify( dn(dn_prefix, treebase),
|
125
|
+
mods )
|
126
|
+
true
|
127
|
+
else
|
128
|
+
logger.warn(ldap_error("update",
|
129
|
+
dn(dn_prefix, treebase) + "\n\t#{actions.inspect}"))
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param dn_prefix String the prefix of the dn
|
135
|
+
# @param treebase the treebase of the dn or any search
|
136
|
+
# @return nil in case of an error or true
|
137
|
+
def delete_object(dn_prefix, treebase)
|
138
|
+
if @ldap2.delete( dn(dn_prefix, treebase) )
|
139
|
+
true
|
140
|
+
else
|
141
|
+
logger.warn(ldap_error("delete",
|
142
|
+
dn(dn_prefix, treebase)))
|
143
|
+
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# @param dn String for identifying the ldap object
|
150
|
+
# @param password String to be used for authenticate to the dn
|
151
|
+
def authenticate(dn, password)
|
152
|
+
Net::LDAP.new( { :host => @ldap2.host,
|
153
|
+
:port => @ldap2.port,
|
154
|
+
:auth => {
|
155
|
+
:method => :simple,
|
156
|
+
:username => dn,
|
157
|
+
:password => password
|
158
|
+
},
|
159
|
+
:base => @ldap2.base
|
160
|
+
} ).bind
|
161
|
+
end
|
162
|
+
|
163
|
+
# helper to concat the dn from the various parts
|
164
|
+
# @param dn_prefix String the prefix of the dn
|
165
|
+
# @param treebase the treebase of the dn or any search
|
166
|
+
# @return the complete dn String
|
167
|
+
def dn(dn_prefix, treebase)
|
168
|
+
"#{dn_prefix},#{treebase},#{@ldap2.base}"
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# helper to extract the Hash from the ldap search result
|
174
|
+
# @param Entry from the ldap_search
|
175
|
+
# @return Hash with name/value pairs of the entry
|
176
|
+
def to_map(entry)
|
177
|
+
map = {}
|
178
|
+
LDAP::entry2hash(entry).each do |k,v|
|
179
|
+
map[k.downcase.to_sym] = v
|
180
|
+
end
|
181
|
+
map
|
182
|
+
end
|
183
|
+
|
184
|
+
def ldap_error(method, dn)
|
185
|
+
"#{method} error: (#{@ldap2.get_operation_result.code}) #{@ldap2.get_operation_result.message}\n\tDN: #{dn}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
data/lib/ldap/version.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'ldap/digest'
|
2
|
+
require 'dm-core'
|
3
|
+
require 'ldap/array'
|
4
|
+
|
5
|
+
module DataMapper
|
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 = {}
|
16
|
+
fields.each { |property| field_map[property] = property.field }
|
17
|
+
|
18
|
+
records.map do |record|
|
19
|
+
identity_map = nil
|
20
|
+
key_values = nil
|
21
|
+
resource = nil
|
22
|
+
|
23
|
+
case record
|
24
|
+
when Hash
|
25
|
+
# remap fields to use the Property object
|
26
|
+
record = record.dup
|
27
|
+
field_map.each { |property, field| record[property] = record.delete(field) if record.key?(field) }
|
28
|
+
|
29
|
+
model = discriminator && discriminator.load(record[discriminator]) || self
|
30
|
+
model_key = model.key(repository_name)
|
31
|
+
|
32
|
+
resource = if model_key.valid?(key_values = record.values_at(*model_key))
|
33
|
+
identity_map = repository.identity_map(model)
|
34
|
+
identity_map[key_values]
|
35
|
+
end
|
36
|
+
|
37
|
+
resource ||= model.allocate
|
38
|
+
|
39
|
+
fields.each do |property|
|
40
|
+
next if no_reload && property.loaded?(resource)
|
41
|
+
|
42
|
+
value = record[property]
|
43
|
+
|
44
|
+
value = property.load(value)
|
45
|
+
|
46
|
+
property.set!(resource, value)
|
47
|
+
end
|
48
|
+
|
49
|
+
when Resource
|
50
|
+
model = record.model
|
51
|
+
model_key = model.key(repository_name)
|
52
|
+
|
53
|
+
resource = if model_key.valid?(key_values = record.key)
|
54
|
+
identity_map = repository.identity_map(model)
|
55
|
+
identity_map[key_values]
|
56
|
+
end
|
57
|
+
|
58
|
+
resource ||= model.allocate
|
59
|
+
|
60
|
+
fields.each do |property|
|
61
|
+
next if no_reload && property.loaded?(resource)
|
62
|
+
|
63
|
+
property.set!(resource, property.get!(record))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
resource.instance_variable_set(:@_repository, repository)
|
68
|
+
|
69
|
+
if identity_map
|
70
|
+
resource.persisted_state = Resource::State::Clean.new(resource) unless resource.persisted_state?
|
71
|
+
|
72
|
+
# defer setting the IdentityMap so second level caches can
|
73
|
+
# record the state of the resource after loaded
|
74
|
+
identity_map[key_values] = resource
|
75
|
+
else
|
76
|
+
resource.persisted_state = Resource::State::Immutable.new(resource)
|
77
|
+
end
|
78
|
+
|
79
|
+
resource
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module LdapResource
|
84
|
+
|
85
|
+
Model.append_inclusions self
|
86
|
+
|
87
|
+
# authenticate the current resource against the stored password
|
88
|
+
# @param [String] password to authenticate
|
89
|
+
# @return [TrueClass, FalseClass] whether password was right or wrong
|
90
|
+
def authenticate(password)
|
91
|
+
ldap.authenticate(ldap.dn(self.class.dn_prefix(self),
|
92
|
+
self.class.treebase),
|
93
|
+
password)
|
94
|
+
end
|
95
|
+
|
96
|
+
# if called without parameter or block the given properties get returned.
|
97
|
+
# if called with a block then the block gets stored. if called with new
|
98
|
+
# properties they get stored. if called with a Resource then either the
|
99
|
+
# stored block gets called with that Resource or the stored properties get
|
100
|
+
# returned.
|
101
|
+
# @param [Hash,DataMapper::Resource] properties_or_resource either a Hash with properties, a Resource or nil
|
102
|
+
# @param [block] &block to be stored for later calls when properties_or_resource is nil
|
103
|
+
# @return [Hash] when called with a Resource
|
104
|
+
def ldap_properties(properties_or_resource = nil, &block)
|
105
|
+
if properties_or_resource
|
106
|
+
if properties_or_resource.instance_of? Hash
|
107
|
+
@ldap_properties = properties_or_resource
|
108
|
+
elsif @ldap_properties.instance_of? Hash
|
109
|
+
@ldap_properties
|
110
|
+
else
|
111
|
+
@ldap_properties.call(properties_or_resource)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
@ldap_properties = block
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# if called without parameter or block the given treebase gets returned.
|
119
|
+
# if called with a block then the block gets stored. if called with a
|
120
|
+
# String then it gets stored. if called with a Resource then either the
|
121
|
+
# stored block gets called with that Resource or the stored String gets
|
122
|
+
# returned.
|
123
|
+
# @param [String,DataMapper::Resource] treebase_or_resource either a String, a Resource or nil
|
124
|
+
# @param [block] &block to be stored for later calls when base_or_resource is nil
|
125
|
+
# @return [String] when called with a Resource
|
126
|
+
def treebase(base_or_resource = nil, &block)
|
127
|
+
if base_or_resource
|
128
|
+
if base_or_resource.instance_of? String
|
129
|
+
@treebase = base_or_resource
|
130
|
+
elsif @treebase.instance_of? String
|
131
|
+
@treebase
|
132
|
+
else
|
133
|
+
@treebase.call(base_or_resource)
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if block
|
137
|
+
@treebase = block
|
138
|
+
else # backwards compatibility
|
139
|
+
@treebase
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# if called without parameter or block the given dn_prefix gets returned.
|
145
|
+
# if called with a block then the block gets stored. if called with a
|
146
|
+
# String then it gets stored. if called with a Resource then either the
|
147
|
+
# stored block gets called with that Resource or the stored String gets
|
148
|
+
# returned.
|
149
|
+
# @param [String,DataMapper::Resource] prefix_or_resource either a String, a Resource or nil
|
150
|
+
# @param [&block] block to be stored for later calls
|
151
|
+
# @return [String, nil] when called with a Resource
|
152
|
+
def dn_prefix(prefix_or_resource = nil, &block)
|
153
|
+
if prefix_or_resource
|
154
|
+
if prefix_or_resource.instance_of? String
|
155
|
+
@ldap_dn = prefix_or_resource
|
156
|
+
elsif @ldap_dn.instance_of? String
|
157
|
+
@ldap_dn
|
158
|
+
else
|
159
|
+
@ldap_dn.call(prefix_or_resource)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
@ldap_dn = block
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# if called without parameter then the stored field gets returned
|
167
|
+
# otherwise the given parameters gets stored
|
168
|
+
# @param [Symbol, String] field a new multivalue_field
|
169
|
+
# @return [Symbol] the multivalue_field
|
170
|
+
def multivalue_field(field = nil)
|
171
|
+
if field.nil?
|
172
|
+
@ldap_multivalue_field
|
173
|
+
else
|
174
|
+
@ldap_multivalue_field = field.to_sym
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
# short cut to the ldap facade
|
180
|
+
# @return [Ldap::LdapFacade]
|
181
|
+
def ldap
|
182
|
+
raise "not an ldap adapter #{repository.adapter.name}" unless repository.adapter.respond_to? :ldap
|
183
|
+
repository.adapter.ldap
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
include LdapResource
|
188
|
+
end
|
189
|
+
end
|