rom-ldap 0.2.2
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +251 -0
- data/CONTRIBUTING.md +18 -0
- data/README.md +172 -0
- data/TODO.md +33 -0
- data/config/responses.yml +328 -0
- data/lib/dry/monitor/ldap/colorizers/default.rb +17 -0
- data/lib/dry/monitor/ldap/colorizers/rouge.rb +31 -0
- data/lib/dry/monitor/ldap/logger.rb +58 -0
- data/lib/rom-ldap.rb +1 -0
- data/lib/rom/ldap.rb +22 -0
- data/lib/rom/ldap/alias.rb +30 -0
- data/lib/rom/ldap/associations.rb +6 -0
- data/lib/rom/ldap/associations/core.rb +23 -0
- data/lib/rom/ldap/associations/many_to_many.rb +18 -0
- data/lib/rom/ldap/associations/many_to_one.rb +22 -0
- data/lib/rom/ldap/associations/one_to_many.rb +32 -0
- data/lib/rom/ldap/associations/one_to_one.rb +19 -0
- data/lib/rom/ldap/associations/self_ref.rb +35 -0
- data/lib/rom/ldap/attribute.rb +327 -0
- data/lib/rom/ldap/client.rb +185 -0
- data/lib/rom/ldap/client/authentication.rb +118 -0
- data/lib/rom/ldap/client/operations.rb +233 -0
- data/lib/rom/ldap/commands.rb +6 -0
- data/lib/rom/ldap/commands/create.rb +41 -0
- data/lib/rom/ldap/commands/delete.rb +17 -0
- data/lib/rom/ldap/commands/update.rb +35 -0
- data/lib/rom/ldap/constants.rb +193 -0
- data/lib/rom/ldap/dataset.rb +286 -0
- data/lib/rom/ldap/dataset/conversion.rb +62 -0
- data/lib/rom/ldap/dataset/dsl.rb +299 -0
- data/lib/rom/ldap/dataset/persistence.rb +44 -0
- data/lib/rom/ldap/directory.rb +126 -0
- data/lib/rom/ldap/directory/capabilities.rb +71 -0
- data/lib/rom/ldap/directory/entry.rb +200 -0
- data/lib/rom/ldap/directory/env.rb +155 -0
- data/lib/rom/ldap/directory/operations.rb +282 -0
- data/lib/rom/ldap/directory/password.rb +122 -0
- data/lib/rom/ldap/directory/root.rb +187 -0
- data/lib/rom/ldap/directory/tokenization.rb +66 -0
- data/lib/rom/ldap/directory/transactions.rb +31 -0
- data/lib/rom/ldap/directory/vendors/active_directory.rb +129 -0
- data/lib/rom/ldap/directory/vendors/apache_ds.rb +27 -0
- data/lib/rom/ldap/directory/vendors/e_directory.rb +16 -0
- data/lib/rom/ldap/directory/vendors/open_directory.rb +12 -0
- data/lib/rom/ldap/directory/vendors/open_dj.rb +25 -0
- data/lib/rom/ldap/directory/vendors/open_ldap.rb +35 -0
- data/lib/rom/ldap/directory/vendors/three_eight_nine.rb +16 -0
- data/lib/rom/ldap/directory/vendors/unknown.rb +22 -0
- data/lib/rom/ldap/dsl.rb +76 -0
- data/lib/rom/ldap/errors.rb +47 -0
- data/lib/rom/ldap/expression.rb +77 -0
- data/lib/rom/ldap/expression_encoder.rb +174 -0
- data/lib/rom/ldap/extensions.rb +50 -0
- data/lib/rom/ldap/extensions/active_support_notifications.rb +26 -0
- data/lib/rom/ldap/extensions/compatibility.rb +11 -0
- data/lib/rom/ldap/extensions/dsml.rb +165 -0
- data/lib/rom/ldap/extensions/msgpack.rb +23 -0
- data/lib/rom/ldap/extensions/optimised_json.rb +25 -0
- data/lib/rom/ldap/extensions/rails_log_subscriber.rb +38 -0
- data/lib/rom/ldap/formatter.rb +26 -0
- data/lib/rom/ldap/functions.rb +207 -0
- data/lib/rom/ldap/gateway.rb +145 -0
- data/lib/rom/ldap/ldif.rb +74 -0
- data/lib/rom/ldap/ldif/exporter.rb +77 -0
- data/lib/rom/ldap/ldif/importer.rb +95 -0
- data/lib/rom/ldap/mapper_compiler.rb +19 -0
- data/lib/rom/ldap/matchers.rb +69 -0
- data/lib/rom/ldap/message_queue.rb +7 -0
- data/lib/rom/ldap/oid.rb +101 -0
- data/lib/rom/ldap/parsers/abstract_syntax.rb +91 -0
- data/lib/rom/ldap/parsers/attribute.rb +290 -0
- data/lib/rom/ldap/parsers/filter_syntax.rb +133 -0
- data/lib/rom/ldap/pdu.rb +285 -0
- data/lib/rom/ldap/plugin/pagination.rb +145 -0
- data/lib/rom/ldap/plugins.rb +7 -0
- data/lib/rom/ldap/projection_dsl.rb +38 -0
- data/lib/rom/ldap/relation.rb +135 -0
- data/lib/rom/ldap/relation/exporting.rb +72 -0
- data/lib/rom/ldap/relation/reading.rb +461 -0
- data/lib/rom/ldap/relation/writing.rb +64 -0
- data/lib/rom/ldap/responses.rb +17 -0
- data/lib/rom/ldap/restriction_dsl.rb +45 -0
- data/lib/rom/ldap/schema.rb +123 -0
- data/lib/rom/ldap/schema/attributes_inferrer.rb +59 -0
- data/lib/rom/ldap/schema/dsl.rb +13 -0
- data/lib/rom/ldap/schema/inferrer.rb +50 -0
- data/lib/rom/ldap/schema/type_builder.rb +133 -0
- data/lib/rom/ldap/scope.rb +19 -0
- data/lib/rom/ldap/search_request.rb +249 -0
- data/lib/rom/ldap/socket.rb +210 -0
- data/lib/rom/ldap/tasks/ldap.rake +103 -0
- data/lib/rom/ldap/tasks/ldif.rake +80 -0
- data/lib/rom/ldap/transaction.rb +29 -0
- data/lib/rom/ldap/type_map.rb +88 -0
- data/lib/rom/ldap/types.rb +158 -0
- data/lib/rom/ldap/version.rb +17 -0
- data/lib/rom/plugins/relation/ldap/active_directory.rb +182 -0
- data/lib/rom/plugins/relation/ldap/auto_restrictions.rb +69 -0
- data/lib/rom/plugins/relation/ldap/e_directory.rb +27 -0
- data/lib/rom/plugins/relation/ldap/instrumentation.rb +35 -0
- data/lib/rouge/lexers/ldap.rb +72 -0
- data/lib/rouge/themes/ldap.rb +49 -0
- metadata +231 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/ldap/parsers/abstract_syntax'
|
|
4
|
+
require 'rom/ldap/parsers/filter_syntax'
|
|
5
|
+
|
|
6
|
+
module ROM
|
|
7
|
+
module LDAP
|
|
8
|
+
class Dataset
|
|
9
|
+
|
|
10
|
+
# Parsing Formats
|
|
11
|
+
#
|
|
12
|
+
# @api public
|
|
13
|
+
module Conversion
|
|
14
|
+
# Extends the class with filter abstraction behavior.
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
def self.included(klass)
|
|
18
|
+
klass.class_eval do
|
|
19
|
+
extend Dry::Core::ClassAttributes
|
|
20
|
+
|
|
21
|
+
defines :filter_class
|
|
22
|
+
filter_class Parsers::FilterSyntax
|
|
23
|
+
|
|
24
|
+
defines :ast_class
|
|
25
|
+
ast_class Parsers::AbstractSyntax
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert the full query to an LDAP filter string
|
|
30
|
+
#
|
|
31
|
+
# @return [String]
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
def to_filter
|
|
35
|
+
self.class.ast_class.new(to_ast, directory.attribute_types).call.to_filter
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Combine original relation dataset name (LDAP filter string)
|
|
39
|
+
# with search criteria (AST).
|
|
40
|
+
#
|
|
41
|
+
# @return [Array]
|
|
42
|
+
#
|
|
43
|
+
# @api private
|
|
44
|
+
def to_ast
|
|
45
|
+
criteria.empty? ? source_ast : [:con_and, [source_ast, criteria]]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# Convert the relation's source filter string to a query AST.
|
|
51
|
+
#
|
|
52
|
+
# @return [Array]
|
|
53
|
+
#
|
|
54
|
+
# @api private
|
|
55
|
+
def source_ast
|
|
56
|
+
self.class.filter_class.new(name, directory.attribute_types).call
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module LDAP
|
|
5
|
+
class Dataset
|
|
6
|
+
|
|
7
|
+
# AST Query Interface
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
module DSL
|
|
11
|
+
# Invert the whole query
|
|
12
|
+
#
|
|
13
|
+
# @return [Dataset]
|
|
14
|
+
def inverse
|
|
15
|
+
with(criteria: [:con_not, criteria])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Equality filter aliased as 'where'.
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# relation.where(uid: 'Pietro')
|
|
22
|
+
# relation.where(uid: %w[Pietro Wanda])
|
|
23
|
+
# relation.where(uid: 'Pietro', sn: 'Maximoff')
|
|
24
|
+
#
|
|
25
|
+
# @param args [Hash]
|
|
26
|
+
#
|
|
27
|
+
# @return [Dataset]
|
|
28
|
+
def equal(args)
|
|
29
|
+
chain(*array_dsl(args))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Antonym of 'equal'
|
|
33
|
+
#
|
|
34
|
+
# @example
|
|
35
|
+
# relation.unequal(uid: 'Pietro')
|
|
36
|
+
# relation.unequal(uid: %w[Pietro Wanda])
|
|
37
|
+
#
|
|
38
|
+
# @param args [Hash]
|
|
39
|
+
#
|
|
40
|
+
# @return [Dataset]
|
|
41
|
+
def unequal(args)
|
|
42
|
+
chain(:con_not, array_dsl(args))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Presence filter aliased as 'has'.
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# relation.present(:uid)
|
|
49
|
+
# relation.has(:mail)
|
|
50
|
+
#
|
|
51
|
+
# @param attribute [Symbol]
|
|
52
|
+
#
|
|
53
|
+
# @return [Dataset]
|
|
54
|
+
def present(attribute)
|
|
55
|
+
chain(:op_eql, attribute, :wildcard)
|
|
56
|
+
end
|
|
57
|
+
alias_method :has, :present
|
|
58
|
+
|
|
59
|
+
# Absence filter aliased as 'hasnt'. Inverse of 'present'.
|
|
60
|
+
#
|
|
61
|
+
# @example
|
|
62
|
+
# relation.missing(:uid)
|
|
63
|
+
# relation.hasnt(:mail)
|
|
64
|
+
#
|
|
65
|
+
# @param attribute [Symbol]
|
|
66
|
+
#
|
|
67
|
+
# @return [Dataset]
|
|
68
|
+
def missing(attribute)
|
|
69
|
+
chain(:con_not, [:op_eql, attribute, :wildcard])
|
|
70
|
+
end
|
|
71
|
+
alias_method :hasnt, :missing
|
|
72
|
+
|
|
73
|
+
# Greater than filter
|
|
74
|
+
#
|
|
75
|
+
# @param args [Hash]
|
|
76
|
+
#
|
|
77
|
+
# @return [Dataset]
|
|
78
|
+
def gt(args)
|
|
79
|
+
chain(:con_not, [:op_lte, *args.to_a[0]])
|
|
80
|
+
end
|
|
81
|
+
alias_method :above, :gt
|
|
82
|
+
|
|
83
|
+
# Less than filter
|
|
84
|
+
#
|
|
85
|
+
# @param args [Hash]
|
|
86
|
+
#
|
|
87
|
+
# @return [Dataset]
|
|
88
|
+
def lt(args)
|
|
89
|
+
chain(:con_not, [:op_gte, *args.to_a[0]])
|
|
90
|
+
end
|
|
91
|
+
alias_method :below, :lt
|
|
92
|
+
|
|
93
|
+
# Greater than or equal filter
|
|
94
|
+
#
|
|
95
|
+
# @param args [Hash]
|
|
96
|
+
#
|
|
97
|
+
# @return [Dataset]
|
|
98
|
+
def gte(args)
|
|
99
|
+
chain(:op_gte, *args.to_a[0])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Less than or equal filter
|
|
103
|
+
#
|
|
104
|
+
# @param args [Hash]
|
|
105
|
+
#
|
|
106
|
+
# @return [Dataset]
|
|
107
|
+
def lte(args)
|
|
108
|
+
chain(:op_lte, *args.to_a[0])
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Starts with filter
|
|
112
|
+
#
|
|
113
|
+
# @param args [Hash]
|
|
114
|
+
#
|
|
115
|
+
# @return [Dataset]
|
|
116
|
+
def begins(args)
|
|
117
|
+
chain(*match_dsl(args, right: WILDCARD))
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Ends with filter
|
|
121
|
+
#
|
|
122
|
+
# @param args [Hash]
|
|
123
|
+
#
|
|
124
|
+
# @return [Dataset]
|
|
125
|
+
def ends(args)
|
|
126
|
+
chain(*match_dsl(args, left: WILDCARD))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @param args [Hash]
|
|
130
|
+
#
|
|
131
|
+
# @return [Dataset]
|
|
132
|
+
def contains(args)
|
|
133
|
+
chain(*match_dsl(args, left: WILDCARD, right: WILDCARD))
|
|
134
|
+
end
|
|
135
|
+
alias_method :matches, :contains
|
|
136
|
+
|
|
137
|
+
# negate #contains
|
|
138
|
+
#
|
|
139
|
+
# @param args [Hash]
|
|
140
|
+
#
|
|
141
|
+
# @return [Dataset]
|
|
142
|
+
def excludes(args)
|
|
143
|
+
chain(:con_not, match_dsl(args, left: WILDCARD, right: WILDCARD))
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# @param args [Range]
|
|
147
|
+
#
|
|
148
|
+
# @return [Dataset]
|
|
149
|
+
def within(args)
|
|
150
|
+
chain(:con_and, cover_dsl(args))
|
|
151
|
+
end
|
|
152
|
+
alias_method :between, :within
|
|
153
|
+
|
|
154
|
+
# negate #outside
|
|
155
|
+
#
|
|
156
|
+
# @param args [Range]
|
|
157
|
+
#
|
|
158
|
+
# @return [Dataset]
|
|
159
|
+
def outside(args)
|
|
160
|
+
chain(:con_not, [:con_and, cover_dsl(args)])
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# @param args [Hash]
|
|
164
|
+
#
|
|
165
|
+
# @return [Dataset]
|
|
166
|
+
def binary_equal(args)
|
|
167
|
+
chain(:op_bineq, *args.to_a[0])
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @param args [Hash]
|
|
171
|
+
#
|
|
172
|
+
# @return [Dataset]
|
|
173
|
+
def approx(args)
|
|
174
|
+
chain(:op_prx, *args.to_a[0])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# @param args [Hash]
|
|
178
|
+
#
|
|
179
|
+
# @return [Dataset]
|
|
180
|
+
def bitwise(args)
|
|
181
|
+
chain(:op_ext, *args.to_a[0])
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
private
|
|
185
|
+
|
|
186
|
+
# Update the criteria.
|
|
187
|
+
# If criteria already exist join with AND.
|
|
188
|
+
#
|
|
189
|
+
# @example
|
|
190
|
+
# chain(:op_eql, :uid, "*foo*")
|
|
191
|
+
#
|
|
192
|
+
# @param exprs [Mixed] AST built by QueryDSL
|
|
193
|
+
#
|
|
194
|
+
# @return [Dataset]
|
|
195
|
+
def chain(*exprs)
|
|
196
|
+
if criteria.empty?
|
|
197
|
+
with(criteria: exprs)
|
|
198
|
+
else
|
|
199
|
+
with(criteria: [:con_and, [criteria, exprs]])
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Handle multiple criteria with an OR join.
|
|
204
|
+
# @see #chain for AND join.
|
|
205
|
+
#
|
|
206
|
+
# @param args [Hash]
|
|
207
|
+
#
|
|
208
|
+
# @return [Array] AST
|
|
209
|
+
#
|
|
210
|
+
# @example
|
|
211
|
+
# array_dsl(sn: 'Maximoff', gn: %w[Wanda Pietror])
|
|
212
|
+
# =>
|
|
213
|
+
# [ :con_or,
|
|
214
|
+
# [
|
|
215
|
+
# [ :op_eql, :sn, "Maximoff" ],
|
|
216
|
+
# [ :con_or,
|
|
217
|
+
# [
|
|
218
|
+
# [ :op_eql, :gn, "Wanda" ],
|
|
219
|
+
# [ :op_eql, :gn, "Pietror" ]
|
|
220
|
+
# ]
|
|
221
|
+
# ]
|
|
222
|
+
# ]
|
|
223
|
+
# ]
|
|
224
|
+
#
|
|
225
|
+
def array_dsl(args)
|
|
226
|
+
expressions = args.map do |left, right|
|
|
227
|
+
values = Array(right).map { |v| [:op_eql, left, escape(v)] }
|
|
228
|
+
join_dsl(:con_or, values)
|
|
229
|
+
end
|
|
230
|
+
join_dsl(:con_or, expressions)
|
|
231
|
+
|
|
232
|
+
# join_dsl(:con_or, [ match_dsl(args.map(&:to_a)) ])
|
|
233
|
+
# join_dsl(:con_or, args.map { |arg| match_dsl([arg]) })
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Wrap criteria with a join operator.
|
|
237
|
+
#
|
|
238
|
+
# @param operator [Symbol] :con_or, :con_and
|
|
239
|
+
#
|
|
240
|
+
# @param ary [Array] [[op, left, right],[op, left, right]]
|
|
241
|
+
def join_dsl(operator, ary)
|
|
242
|
+
ary.size >= 2 ? [operator, ary] : ary.first
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Wrap criteria value with extra characters, used for wildcard
|
|
246
|
+
#
|
|
247
|
+
# @param args [Array]
|
|
248
|
+
#
|
|
249
|
+
# @option :left [String] Prepended to value.
|
|
250
|
+
# @option :right [String] Appended to value.
|
|
251
|
+
#
|
|
252
|
+
# @return [Array]
|
|
253
|
+
#
|
|
254
|
+
# @example
|
|
255
|
+
# match_dsl(bar: 'foo', left: '*', right: '*')
|
|
256
|
+
# => [:op_eql, :bar, '*foo*']
|
|
257
|
+
#
|
|
258
|
+
def match_dsl(args, left: EMPTY_STRING, right: EMPTY_STRING)
|
|
259
|
+
expressions = args.map do |att, val|
|
|
260
|
+
values = Array(val).map do |v|
|
|
261
|
+
value = left.to_s + escape(v) + right.to_s
|
|
262
|
+
[:op_eql, att, value]
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
join_dsl(:con_or, values)
|
|
266
|
+
end
|
|
267
|
+
join_dsl(:con_or, expressions)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
#
|
|
271
|
+
# @param args [Range,Array]
|
|
272
|
+
#
|
|
273
|
+
# @return [Array]
|
|
274
|
+
def cover_dsl(args)
|
|
275
|
+
attribute, range = args.to_a[0]
|
|
276
|
+
lower, *_, upper = range.to_a
|
|
277
|
+
|
|
278
|
+
lower = [:op_gte, attribute, lower]
|
|
279
|
+
upper = [:op_lte, attribute, upper]
|
|
280
|
+
|
|
281
|
+
[lower, upper]
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# If any of the following special characters appear in the
|
|
285
|
+
# search filter as literals, they must be escaped with a backslash.
|
|
286
|
+
#
|
|
287
|
+
# "(", ")", "\", ,"/" "*", "null"
|
|
288
|
+
#
|
|
289
|
+
# @param value [String, Integer]
|
|
290
|
+
#
|
|
291
|
+
# @return [String]
|
|
292
|
+
def escape(value)
|
|
293
|
+
value.to_s.gsub(ESCAPE_REGEX) { |char| '\\' + ESCAPES[char] }
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module LDAP
|
|
5
|
+
class Dataset
|
|
6
|
+
|
|
7
|
+
module Persistence
|
|
8
|
+
# Interface to Directory#add
|
|
9
|
+
#
|
|
10
|
+
# @param tuple [Hash]
|
|
11
|
+
#
|
|
12
|
+
# @return [Boolean]
|
|
13
|
+
#
|
|
14
|
+
# @api public
|
|
15
|
+
def add(tuple)
|
|
16
|
+
directory.add(tuple)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Interface to Directory#modify
|
|
20
|
+
#
|
|
21
|
+
# @param tuple [Changeset, Hash] Modification params
|
|
22
|
+
#
|
|
23
|
+
# @return [Array<Directory::Entry, Boolean>]
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
def modify(tuple)
|
|
27
|
+
map { |e| directory.modify(e.dn, tuple) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Interface to Directory#delete
|
|
31
|
+
#
|
|
32
|
+
# @see Directory::Operations#delete
|
|
33
|
+
#
|
|
34
|
+
# @return [Array<Directory::Entry, Boolean>]
|
|
35
|
+
#
|
|
36
|
+
# @api public
|
|
37
|
+
def delete
|
|
38
|
+
map { |e| directory.delete(e.dn) }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/ldap/client'
|
|
4
|
+
|
|
5
|
+
require 'rom/ldap/directory/env'
|
|
6
|
+
require 'rom/ldap/directory/entry'
|
|
7
|
+
require 'rom/ldap/directory/root'
|
|
8
|
+
require 'rom/ldap/directory/capabilities'
|
|
9
|
+
require 'rom/ldap/directory/operations'
|
|
10
|
+
require 'rom/ldap/directory/transactions'
|
|
11
|
+
require 'rom/ldap/directory/tokenization'
|
|
12
|
+
|
|
13
|
+
module ROM
|
|
14
|
+
module LDAP
|
|
15
|
+
# @abstract
|
|
16
|
+
# Builds LDAP directory abstraction over TCP connection instance.
|
|
17
|
+
# Includes vendor specific modules once initialised.
|
|
18
|
+
#
|
|
19
|
+
class Directory
|
|
20
|
+
|
|
21
|
+
attr_accessor :logger
|
|
22
|
+
attr_reader :env
|
|
23
|
+
|
|
24
|
+
# Load vendor specific methods into the instance as singletons
|
|
25
|
+
#
|
|
26
|
+
# @see Gateway#directory
|
|
27
|
+
#
|
|
28
|
+
# @return [ROM::LDAP::Directory]
|
|
29
|
+
#
|
|
30
|
+
def initialize(uri, options)
|
|
31
|
+
@env = ENV.new(uri, options)
|
|
32
|
+
@logger = options.fetch(:logger, Logger.new($stdout))
|
|
33
|
+
|
|
34
|
+
require "rom/ldap/directory/vendors/#{type}"
|
|
35
|
+
extend LDAP.const_get(Inflector.camelize(type))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
include Root
|
|
39
|
+
include Capabilities
|
|
40
|
+
include Tokenization
|
|
41
|
+
include Operations
|
|
42
|
+
include Transactions
|
|
43
|
+
|
|
44
|
+
# Initial search base.
|
|
45
|
+
#
|
|
46
|
+
# @return [String] Defaults to empty string.
|
|
47
|
+
#
|
|
48
|
+
# @api public
|
|
49
|
+
def base
|
|
50
|
+
env.base
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Encapsulates encoding and binding using socket.
|
|
54
|
+
#
|
|
55
|
+
# @return [Client]
|
|
56
|
+
#
|
|
57
|
+
def client
|
|
58
|
+
@client ||= Client.new(env.to_h)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Expected method inside gateway.
|
|
62
|
+
#
|
|
63
|
+
# @return [TrueClass]
|
|
64
|
+
#
|
|
65
|
+
def disconnect
|
|
66
|
+
client.close
|
|
67
|
+
client.closed?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Parsed attributes.
|
|
71
|
+
# Output influenced by LDAP.formatter. Ordered alphabetically.
|
|
72
|
+
#
|
|
73
|
+
# @return [Array<Hash>]
|
|
74
|
+
#
|
|
75
|
+
def attribute_types
|
|
76
|
+
@attribute_types ||= schema_attribute_types.map(&method(:to_attribute)).flatten.freeze
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Look up canonical name for a formatted attribute.
|
|
80
|
+
#
|
|
81
|
+
# @see Dataset#order_by and Dataset#select
|
|
82
|
+
#
|
|
83
|
+
# @param attrs [Array<Symbol,String>] formatted attribute names.
|
|
84
|
+
#
|
|
85
|
+
# @return [Array<String>] camelCased canonical LDAP attributes.
|
|
86
|
+
#
|
|
87
|
+
def canonical_attributes(attrs)
|
|
88
|
+
attrs.map do |formatted|
|
|
89
|
+
attribute_by(:name, formatted).fetch(:canonical, formatted.to_s)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Query parsed attribute definition hashes by key.
|
|
94
|
+
#
|
|
95
|
+
# @example
|
|
96
|
+
# directory.attribute_by(:name, :jpeg_photo) => { name: :jpeg_photo, ...}
|
|
97
|
+
#
|
|
98
|
+
# @param key [Symbol]
|
|
99
|
+
# @param value [Mixed]
|
|
100
|
+
#
|
|
101
|
+
# @return [Hash]
|
|
102
|
+
#
|
|
103
|
+
def attribute_by(key, value)
|
|
104
|
+
attribute_types.find { |a| a[key].eql?(value) } || EMPTY_HASH
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Hash of attribute names converted => original
|
|
108
|
+
#
|
|
109
|
+
# @example { formatted_name: 'canonicalName' }
|
|
110
|
+
#
|
|
111
|
+
# @return [Hash]
|
|
112
|
+
#
|
|
113
|
+
def key_map
|
|
114
|
+
attribute_types.map { |a| a.values_at(:name, :canonical) }.sort.to_h
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @return [String]
|
|
118
|
+
#
|
|
119
|
+
# @api public
|
|
120
|
+
def inspect
|
|
121
|
+
"#<#{self.class} uri='#{env.connection}' vendor='#{vendor_name}' version='#{vendor_version}' />"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|