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,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,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
|