rom-ldap 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +251 -0
  3. data/CONTRIBUTING.md +18 -0
  4. data/README.md +172 -0
  5. data/TODO.md +33 -0
  6. data/config/responses.yml +328 -0
  7. data/lib/dry/monitor/ldap/colorizers/default.rb +17 -0
  8. data/lib/dry/monitor/ldap/colorizers/rouge.rb +31 -0
  9. data/lib/dry/monitor/ldap/logger.rb +58 -0
  10. data/lib/rom-ldap.rb +1 -0
  11. data/lib/rom/ldap.rb +22 -0
  12. data/lib/rom/ldap/alias.rb +30 -0
  13. data/lib/rom/ldap/associations.rb +6 -0
  14. data/lib/rom/ldap/associations/core.rb +23 -0
  15. data/lib/rom/ldap/associations/many_to_many.rb +18 -0
  16. data/lib/rom/ldap/associations/many_to_one.rb +22 -0
  17. data/lib/rom/ldap/associations/one_to_many.rb +32 -0
  18. data/lib/rom/ldap/associations/one_to_one.rb +19 -0
  19. data/lib/rom/ldap/associations/self_ref.rb +35 -0
  20. data/lib/rom/ldap/attribute.rb +327 -0
  21. data/lib/rom/ldap/client.rb +185 -0
  22. data/lib/rom/ldap/client/authentication.rb +118 -0
  23. data/lib/rom/ldap/client/operations.rb +233 -0
  24. data/lib/rom/ldap/commands.rb +6 -0
  25. data/lib/rom/ldap/commands/create.rb +41 -0
  26. data/lib/rom/ldap/commands/delete.rb +17 -0
  27. data/lib/rom/ldap/commands/update.rb +35 -0
  28. data/lib/rom/ldap/constants.rb +193 -0
  29. data/lib/rom/ldap/dataset.rb +286 -0
  30. data/lib/rom/ldap/dataset/conversion.rb +62 -0
  31. data/lib/rom/ldap/dataset/dsl.rb +299 -0
  32. data/lib/rom/ldap/dataset/persistence.rb +44 -0
  33. data/lib/rom/ldap/directory.rb +126 -0
  34. data/lib/rom/ldap/directory/capabilities.rb +71 -0
  35. data/lib/rom/ldap/directory/entry.rb +200 -0
  36. data/lib/rom/ldap/directory/env.rb +155 -0
  37. data/lib/rom/ldap/directory/operations.rb +282 -0
  38. data/lib/rom/ldap/directory/password.rb +122 -0
  39. data/lib/rom/ldap/directory/root.rb +187 -0
  40. data/lib/rom/ldap/directory/tokenization.rb +66 -0
  41. data/lib/rom/ldap/directory/transactions.rb +31 -0
  42. data/lib/rom/ldap/directory/vendors/active_directory.rb +129 -0
  43. data/lib/rom/ldap/directory/vendors/apache_ds.rb +27 -0
  44. data/lib/rom/ldap/directory/vendors/e_directory.rb +16 -0
  45. data/lib/rom/ldap/directory/vendors/open_directory.rb +12 -0
  46. data/lib/rom/ldap/directory/vendors/open_dj.rb +25 -0
  47. data/lib/rom/ldap/directory/vendors/open_ldap.rb +35 -0
  48. data/lib/rom/ldap/directory/vendors/three_eight_nine.rb +16 -0
  49. data/lib/rom/ldap/directory/vendors/unknown.rb +22 -0
  50. data/lib/rom/ldap/dsl.rb +76 -0
  51. data/lib/rom/ldap/errors.rb +47 -0
  52. data/lib/rom/ldap/expression.rb +77 -0
  53. data/lib/rom/ldap/expression_encoder.rb +174 -0
  54. data/lib/rom/ldap/extensions.rb +50 -0
  55. data/lib/rom/ldap/extensions/active_support_notifications.rb +26 -0
  56. data/lib/rom/ldap/extensions/compatibility.rb +11 -0
  57. data/lib/rom/ldap/extensions/dsml.rb +165 -0
  58. data/lib/rom/ldap/extensions/msgpack.rb +23 -0
  59. data/lib/rom/ldap/extensions/optimised_json.rb +25 -0
  60. data/lib/rom/ldap/extensions/rails_log_subscriber.rb +38 -0
  61. data/lib/rom/ldap/formatter.rb +26 -0
  62. data/lib/rom/ldap/functions.rb +207 -0
  63. data/lib/rom/ldap/gateway.rb +145 -0
  64. data/lib/rom/ldap/ldif.rb +74 -0
  65. data/lib/rom/ldap/ldif/exporter.rb +77 -0
  66. data/lib/rom/ldap/ldif/importer.rb +95 -0
  67. data/lib/rom/ldap/mapper_compiler.rb +19 -0
  68. data/lib/rom/ldap/matchers.rb +69 -0
  69. data/lib/rom/ldap/message_queue.rb +7 -0
  70. data/lib/rom/ldap/oid.rb +101 -0
  71. data/lib/rom/ldap/parsers/abstract_syntax.rb +91 -0
  72. data/lib/rom/ldap/parsers/attribute.rb +290 -0
  73. data/lib/rom/ldap/parsers/filter_syntax.rb +133 -0
  74. data/lib/rom/ldap/pdu.rb +285 -0
  75. data/lib/rom/ldap/plugin/pagination.rb +145 -0
  76. data/lib/rom/ldap/plugins.rb +7 -0
  77. data/lib/rom/ldap/projection_dsl.rb +38 -0
  78. data/lib/rom/ldap/relation.rb +135 -0
  79. data/lib/rom/ldap/relation/exporting.rb +72 -0
  80. data/lib/rom/ldap/relation/reading.rb +461 -0
  81. data/lib/rom/ldap/relation/writing.rb +64 -0
  82. data/lib/rom/ldap/responses.rb +17 -0
  83. data/lib/rom/ldap/restriction_dsl.rb +45 -0
  84. data/lib/rom/ldap/schema.rb +123 -0
  85. data/lib/rom/ldap/schema/attributes_inferrer.rb +59 -0
  86. data/lib/rom/ldap/schema/dsl.rb +13 -0
  87. data/lib/rom/ldap/schema/inferrer.rb +50 -0
  88. data/lib/rom/ldap/schema/type_builder.rb +133 -0
  89. data/lib/rom/ldap/scope.rb +19 -0
  90. data/lib/rom/ldap/search_request.rb +249 -0
  91. data/lib/rom/ldap/socket.rb +210 -0
  92. data/lib/rom/ldap/tasks/ldap.rake +103 -0
  93. data/lib/rom/ldap/tasks/ldif.rake +80 -0
  94. data/lib/rom/ldap/transaction.rb +29 -0
  95. data/lib/rom/ldap/type_map.rb +88 -0
  96. data/lib/rom/ldap/types.rb +158 -0
  97. data/lib/rom/ldap/version.rb +17 -0
  98. data/lib/rom/plugins/relation/ldap/active_directory.rb +182 -0
  99. data/lib/rom/plugins/relation/ldap/auto_restrictions.rb +69 -0
  100. data/lib/rom/plugins/relation/ldap/e_directory.rb +27 -0
  101. data/lib/rom/plugins/relation/ldap/instrumentation.rb +35 -0
  102. data/lib/rouge/lexers/ldap.rb +72 -0
  103. data/lib/rouge/themes/ldap.rb +49 -0
  104. metadata +231 -0
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/commands'
4
+ require 'rom/ldap/commands/create'
5
+ require 'rom/ldap/commands/update'
6
+ require 'rom/ldap/commands/delete'
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ROM
4
+ module LDAP
5
+ module Commands
6
+ class Create < ROM::Commands::Create
7
+
8
+ adapter :ldap
9
+
10
+ use :schema
11
+
12
+ after :finalize
13
+
14
+ # Pass tuple(s) to relation for insertion.
15
+ #
16
+ # @param tuples [Hash, Array<Hash>]
17
+ #
18
+ # @return [Array<Entry>]
19
+ #
20
+ # @api public
21
+ def execute(tuples)
22
+ Array([tuples]).flatten(1).map do |tuple|
23
+ relation.insert(tuple)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Output through relation output_schema
30
+ #
31
+ # @param entries [Array<Entry, FalseClass>]
32
+ #
33
+ # @api private
34
+ def finalize(entries, *)
35
+ entries.map { |t| relation.output_schema[t] }
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ROM
4
+ module LDAP
5
+ module Commands
6
+ class Delete < ROM::Commands::Delete
7
+
8
+ adapter :ldap
9
+
10
+ def execute
11
+ relation.delete
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ROM
4
+ module LDAP
5
+ module Commands
6
+ class Update < ROM::Commands::Update
7
+
8
+ adapter :ldap
9
+
10
+ use :schema
11
+
12
+ after :finalize
13
+
14
+ def execute(tuple)
15
+ update(input[tuple].to_h)
16
+ end
17
+
18
+ private
19
+
20
+ #
21
+ # @param entries [Array<Directory::Entry>]
22
+ #
23
+ # @api private
24
+ def finalize(entries, *)
25
+ entries.map { |t| relation.output_schema[t] }
26
+ end
27
+
28
+ def update(*args)
29
+ relation.update(*args)
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Layout/HashAlignment
4
+
5
+ require 'rom/ldap/oid'
6
+ require 'rom/ldap/scope'
7
+ require 'rom/ldap/alias'
8
+ require 'rom/ldap/matchers'
9
+ require 'rom/ldap/type_map'
10
+ require 'rom/ldap/responses'
11
+
12
+ require 'uri'
13
+
14
+ module ROM
15
+ module LDAP
16
+ # Matches an ldap(s) url
17
+ #
18
+ # @return [Regexp]
19
+ LDAPURI_REGEX = Regexp.union(
20
+ ::URI::DEFAULT_PARSER.make_regexp('ldap'),
21
+ ::URI::DEFAULT_PARSER.make_regexp('ldaps')
22
+ ).freeze
23
+
24
+ # Any word character or hyphen, equals
25
+ #
26
+ # @return [Regexp]
27
+ DN_REGEX = /(([-\w]+=[-\w]+)*,?)/.freeze
28
+
29
+ # Something in parentheses
30
+ #
31
+ # @return [Regexp]
32
+ FILTER_REGEX = /^\s*\(.*\)\s*$/.freeze
33
+
34
+ # @return [String]
35
+ NEW_LINE = "\n"
36
+
37
+ # @return [String]
38
+ WILDCARD = '*'
39
+
40
+ # @return [String]
41
+ PERCENT_SPACE = '%20'
42
+
43
+ # @return [String]
44
+ SPACE = ' '
45
+
46
+ # @return [Array<String>]
47
+ OP_ATTRS = %w[+].freeze
48
+
49
+ # @return [Array<String>]
50
+ ALL_ATTRS = [WILDCARD, *OP_ATTRS].freeze
51
+
52
+ # @return [String]
53
+ DEFAULT_PK = 'entrydn'
54
+
55
+ # @return [Array<String>]
56
+ #
57
+ # @example [Schema]
58
+ # use :timestamps,
59
+ # attributes: %i(create_timestamp modify_timestamp),
60
+ # type: ROM::LDAP::Types::Time
61
+ #
62
+ #
63
+ # @see Relation#operational
64
+ #
65
+ TIMESTAMPS = %w[createTimestamp modifyTimestamp].freeze
66
+
67
+ # @return [String]
68
+ #
69
+ DEFAULT_FILTER = '(objectClass=*)'
70
+
71
+ # Time conversion
72
+ #
73
+ # @return [Integer]
74
+ #
75
+ # @see Functions.to_time
76
+ TEN_MILLION = 10_000_000
77
+
78
+ # @return [Integer]
79
+ #
80
+ # @see Functions.to_time
81
+ SINCE_1601 = 11_644_473_600
82
+
83
+ # Internal abstraction of LDAP string search filter constructors.
84
+ #
85
+ # @see https://www.rfc-editor.org/rfc/rfc4515.txt String Search Filter Definition
86
+ #
87
+ # @return [Hash]
88
+ #
89
+ CONSTRUCTORS = {
90
+ con_and: '&', # AND / AMPERSAND / %x26
91
+ con_or: '|', # OR / VERTBAR / %x7C
92
+ con_not: '!' # NOT / EXCLAMATION / %x21
93
+ }.freeze
94
+
95
+ CONSTRUCTOR_REGEX = Regexp.union(/\s*\|\s*/, /\s*\&\s*/).freeze
96
+
97
+ # Internal abstraction of LDAP string search filter operators.
98
+ #
99
+ # @return [Hash]
100
+ #
101
+ # @see https://www.rfc-editor.org/rfc/rfc4515.txt String Search Filter Definition
102
+ #
103
+ # equal = EQUALS
104
+ # approx = TILDE EQUALS
105
+ # greaterorequal = RANGLE EQUALS
106
+ # lessorequal = LANGLE EQUALS
107
+ # extensible = ( attr [dnattrs]
108
+ # [matchingrule] COLON EQUALS assertionvalue )
109
+ # / ( [dnattrs]
110
+ # matchingrule COLON EQUALS assertionvalue )
111
+ #
112
+ OPERATORS = {
113
+ op_bineq: '=', # Binary comparison
114
+ op_eql: '=', # Equal to
115
+ op_prx: '~=', # Approximately equal to
116
+ op_gte: '>=', # Lexicographically greater than or equal to
117
+ op_lte: '<=', # Lexicographically less than or equal to
118
+ op_ext: ':=' # Bitwise comparison of numeric values
119
+ }.freeze
120
+
121
+ OPERATOR_REGEX = Regexp.union(*OPERATORS.values).freeze
122
+
123
+ # @return [Array]
124
+ #
125
+ ABSTRACTS = [*OPERATORS.keys, *CONSTRUCTORS.keys].freeze
126
+
127
+ # Symbolic abstraction of LDIF booleans and wildcard matcher
128
+ #
129
+ # @return [Hash]
130
+ #
131
+ VALUES_MAP = {
132
+ :wildcard => WILDCARD, # ANY / ASTERISK / %x2A
133
+ true => 'TRUE',
134
+ false => 'FALSE'
135
+ }.freeze
136
+
137
+ #
138
+ # DSL dataset methods
139
+ #
140
+ # @see RFC4515 value encoding rule.
141
+ #
142
+ # @return [Hash]
143
+ #
144
+ ESCAPES = {
145
+ "\0" => '00', # NUL / %x00
146
+ '*' => '2A', # ASTERISK / %x2A
147
+ '(' => '28', # LPARENS / %x28
148
+ ')' => '29', # RPARENS / %x29
149
+ '\\' => '5C' # ESC / %x5C
150
+ }.freeze
151
+
152
+ #
153
+ # Expression Encoder
154
+ # (1)type (2)dn (4)rule
155
+ #
156
+ # <attribute name>:<matching rule OID>:=<value>
157
+ # (&(objectCategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648))
158
+ #
159
+ # @return [Regexp]
160
+ #
161
+ EXTENSIBLE_REGEX = /^([-;\w]*)(:dn)?(:(\w+|[.\w]+))?$/.freeze
162
+
163
+ # ESC and HEX values
164
+ #
165
+ # The value encoding rule ensures that the entire filter string is a valid
166
+ # UTF-8 string and provides that the octets that represent theses ESCAPES
167
+ # are represented as a backslash followed by the two hexadecimal digits
168
+ # representing the value of the encoded octet.
169
+ #
170
+ UNESCAPE_REGEX = /\\([a-f\d]{2})/i.freeze
171
+
172
+ # @return [Regexp]
173
+ #
174
+ ESCAPE_REGEX = Regexp.new('[' + ESCAPES.keys.map { |e| Regexp.escape(e) }.join + ']').freeze
175
+
176
+ # @return [Regexp]
177
+ #
178
+ VAL_REGEX = %r"(?:[-\[\]{}\w*.+/:@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\x5C(?:[\x20-\x23]|[\x2B\x2C]|[\x3B-\x3E]|\x5C)|\\[a-fA-F\d]{2})+"u.freeze
179
+
180
+ # Local file path
181
+ #
182
+ # @return [Regexp]
183
+ #
184
+ BIN_FILE_REGEX = %r{^file://(.*)}.freeze
185
+
186
+ # $1 = attribute
187
+ # $3 = value
188
+ #
189
+ LDIF_LINE_REGEX = /^([^:]+):([\:]?)[\s]*<?(.*)$/.freeze
190
+ end
191
+ end
192
+
193
+ # rubocop:enable Layout/HashAlignment
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/initializer'
4
+ require 'rom/ldap/functions'
5
+
6
+ require 'rom/ldap/dataset/conversion'
7
+ require 'rom/ldap/dataset/persistence'
8
+ require 'rom/ldap/dataset/dsl'
9
+
10
+ module ROM
11
+ module LDAP
12
+ #
13
+ # @api private
14
+ class Dataset
15
+
16
+ extend Initializer
17
+ include Enumerable
18
+
19
+ # Directory instance
20
+ #
21
+ # @!attribute [r] directory
22
+ # @return [Directory]
23
+ option :directory
24
+
25
+ # LDAP filter defined in relation schema.
26
+ #
27
+ # @!attribute [r] name
28
+ # @return [String] Valid LDAP filter filter string.
29
+ option :name, type: Types::Filter, reader: :private
30
+
31
+ # Valid Distinguished Name. A relation class value or the gateway default.
32
+ #
33
+ # @!attribute [r] base
34
+ # @return [String] Set when initializing a relation
35
+ option :base, type: Types::DN, reader: :private, default: proc { directory.base }
36
+
37
+ #
38
+ # @!attribute [r] criteria
39
+ # @return [Array] Query AST
40
+ option :criteria, type: Types::Strict::Array, reader: :private, default: proc { EMPTY_ARRAY }
41
+
42
+ #
43
+ # @!attribute [r] direction
44
+ # @return [Symbol]
45
+ option :direction, type: Types::Direction, reader: :private, default: proc { :asc }
46
+
47
+ #
48
+ # @!attribute [r] offset
49
+ # @return [Integer] Pagination per_page(20).
50
+ option :offset, type: Types::Strict::Integer, reader: :private, optional: true
51
+
52
+ # @option :limit [Integer] Pagination page(1).
53
+ #
54
+ option :limit, type: Types::Strict::Integer, reader: :private, optional: true
55
+
56
+ # @option :random [TrueClass] Switch for randomisation
57
+ #
58
+ option :random, type: Types::Strict::Bool, reader: :private, default: proc { false }
59
+
60
+ # Attributes to return. Needs to be set to the projected schema.
61
+ #
62
+ option :attrs, type: Types::Strict::Array, reader: :private, optional: true
63
+
64
+ # @option :aliases [Array]
65
+ #
66
+ option :aliases, type: Types::Strict::Array, reader: :private, default: proc { EMPTY_ARRAY }
67
+
68
+ # @option :sort_attrs [String,Symbol] Attribute name(s) to sort by.
69
+ #
70
+ option :sort_attrs, type: Types::Strict::Array, reader: :private, optional: true
71
+
72
+ include DSL
73
+ include Persistence
74
+ include Conversion
75
+
76
+ # Collection of Dataset::DSL module methods.
77
+ # Used by Relation to forward methods to Dataset.
78
+ #
79
+ # @return [Array<Symbol>]
80
+ #
81
+ # @example
82
+ # # => %i{equal has lt begins excludes present}
83
+ #
84
+ def self.dsl
85
+ DSL.public_instance_methods(false)
86
+ end
87
+
88
+ # Dataset#where
89
+ alias_method :where, :equal
90
+
91
+ # Initialise a new class overriding options.
92
+ #
93
+ # @return [ROM::LDAP::Dataset]
94
+ #
95
+ # @param overrides [Hash] Alternative options
96
+ #
97
+ # @api public
98
+ def with(overrides)
99
+ self.class.new(options.merge(overrides))
100
+ end
101
+
102
+ # @return [Hash] internal options
103
+ #
104
+ # @api public
105
+ def opts
106
+ options.merge(ast: to_ast, filter: to_filter).freeze
107
+ end
108
+
109
+ # Iterate over the entries return from the server.
110
+ #
111
+ # @return [Array <Directory::Entry>]
112
+ # @return [Enumerator <Directory::Entry>]
113
+ #
114
+ # @api public
115
+ def each(*args, &block)
116
+ results = paginated? ? entries[page_range] : entries
117
+ results = results.sort_by { rand } if random
118
+ results = results.reverse_each if reversed?
119
+ results = results.map { |e| apply_aliases(e) } if aliases.any?
120
+
121
+ block_given? ? results.each(*args, &block) : results.to_enum
122
+ end
123
+
124
+ # Iterate over each entry or one attribute of each entry.
125
+ #
126
+ # @return [Mixed]
127
+ #
128
+ # @api public
129
+ def map(attr = nil, &block)
130
+ each.map { |entry| attr ? entry[attr] : entry }.map(&block)
131
+ end
132
+
133
+ # Inspect dataset revealing current ast and base.
134
+ #
135
+ # @return [String]
136
+ #
137
+ # @api public
138
+ def inspect
139
+ %(#<#{self.class}: base="#{base}" #{to_ast} />)
140
+ end
141
+
142
+ # This method is present in Sequel and ensures rom-sql/rom-ldap plugin interoperability.
143
+ #
144
+ # @return [Dataset]
145
+ #
146
+ # @api public
147
+ def unfiltered
148
+ with(criteria: EMPTY_ARRAY)
149
+ end
150
+
151
+ # Wildcard search on multiple attributes.
152
+ #
153
+ # @example
154
+ # dataset.grep([:givenname, :sn], 'foo').opts[:criteria] =>
155
+ # [:con_or, [[:op_eql, :givenname, "*foo*"], [:op_eql, :sn, "*foo*"]]]
156
+ #
157
+ #
158
+ # @see Relation::Reading#grep
159
+ #
160
+ # @param attrs [Array<Symbol>] schema attribute names
161
+ #
162
+ # @param value [String] search parameter
163
+ #
164
+ # @return [Relation]
165
+ #
166
+ # @api public
167
+ def grep(attrs, value)
168
+ new_criteria = attrs.map do |attr|
169
+ match_dsl([[attr, value]], left: WILDCARD, right: WILDCARD)
170
+ end
171
+ join(new_criteria, :con_or)
172
+ end
173
+
174
+ # @see Relation#where
175
+ #
176
+ # Combine AST criteria - use AND by default
177
+ #
178
+ # @param new_criteria [Array]
179
+ # @param constructor [Symbol]
180
+ #
181
+ # @return [Relation]
182
+ #
183
+ # @api public
184
+ def join(new_criteria, constructor = :con_and)
185
+ new_chain = join_dsl(constructor, new_criteria)
186
+
187
+ # check because RestrictionDSL sometimes offers empty criteria
188
+ if new_chain.empty?
189
+ self
190
+ else
191
+ chain(*new_chain)
192
+ end
193
+ end
194
+
195
+ # Validate the password against the filtered user.
196
+ #
197
+ # @param password [String]
198
+ #
199
+ # @return [Boolean]
200
+ #
201
+ # @api public
202
+ def bind(password)
203
+ directory.bind_as(filter: to_ast, password: password)
204
+ end
205
+
206
+ # Handle different string output formats
207
+ # i.e. DSML, LDIF, JSON, YAML, MessagePack.
208
+ #
209
+ # @return [Hash, Array<Hash>]
210
+ #
211
+ def export
212
+ results = map(&:canonical)
213
+ results.one? ? results.first : results
214
+ end
215
+
216
+ # Unrestricted count of every entry under the search base
217
+ # with the domain entry discounted.
218
+ #
219
+ # @return [Integer]
220
+ #
221
+ # @api public
222
+ def total
223
+ directory.base_total - 1
224
+ end
225
+
226
+ private
227
+
228
+ # Communicate with LDAP servers.
229
+ # @see Connection::SearchRequest for #query keywords defintion.
230
+ #
231
+ # @return [Array<Hash>] Populate with a directory search.
232
+ #
233
+ # @api private
234
+ def entries
235
+ results =
236
+ directory.query(
237
+ filter: to_ast,
238
+ base: base,
239
+ attributes: renamed_select,
240
+ sorted: renamed_sort,
241
+ max: limit,
242
+ reverse: reversed?
243
+ )
244
+
245
+ options[:criteria] = []
246
+ results
247
+ end
248
+
249
+ # @api private
250
+ def renamed_select
251
+ directory.canonical_attributes(attrs) if attrs
252
+ end
253
+
254
+ # @api private
255
+ def renamed_sort
256
+ directory.canonical_attributes(sort_attrs) if sort_attrs
257
+ end
258
+
259
+ # @return [Range]
260
+ #
261
+ # @api private
262
+ def page_range
263
+ offset..(offset + limit - 1)
264
+ end
265
+
266
+ # @api private
267
+ def paginated?
268
+ limit && offset
269
+ end
270
+
271
+ # @api private
272
+ def reversed?
273
+ direction.eql?(:desc)
274
+ end
275
+
276
+ def apply_aliases(entry)
277
+ Functions[:rename_keys][alias_map, entry].invert
278
+ end
279
+
280
+ def alias_map
281
+ { dn: :dn }.merge(attrs.zip(aliases).to_h)
282
+ end
283
+
284
+ end
285
+ end
286
+ end