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,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module LDAP
|
|
5
|
+
class Relation < ROM::Relation
|
|
6
|
+
|
|
7
|
+
module Writing
|
|
8
|
+
# @example
|
|
9
|
+
# relation.insert(
|
|
10
|
+
# dn: 'uid=batman,ou=comic,dc=rom,dc=ldap',
|
|
11
|
+
# cn: 'The Dark Knight',
|
|
12
|
+
# uid: 'batman',
|
|
13
|
+
# given_name: 'Bruce',
|
|
14
|
+
# sn: 'Wayne',
|
|
15
|
+
# apple_imhandle: 'bruce-wayne',
|
|
16
|
+
# object_class: %w[extensibleObject inetOrgPerson]
|
|
17
|
+
# )
|
|
18
|
+
# #=>
|
|
19
|
+
# {
|
|
20
|
+
# dn: 'uid=batman,ou=comic,dc=rom,dc=ldap',
|
|
21
|
+
# cn: 'The Dark Knight',
|
|
22
|
+
# uid: 'batman',
|
|
23
|
+
# given_name: 'Bruce',
|
|
24
|
+
# sn: 'Wayne',
|
|
25
|
+
# apple_imhandle: 'bruce-wayne',
|
|
26
|
+
# object_class: %w[top extensibleObject inetOrgPerson]
|
|
27
|
+
# }
|
|
28
|
+
#
|
|
29
|
+
# @param tuple [Hash]
|
|
30
|
+
#
|
|
31
|
+
# @return [Array<Directory::Entry, FalseClass>]
|
|
32
|
+
#
|
|
33
|
+
# @api public
|
|
34
|
+
def insert(tuple)
|
|
35
|
+
dataset.add(tuple)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @example
|
|
39
|
+
# relation.update(mail: 'fear_the_bat@gotham.com')
|
|
40
|
+
# #=> {}
|
|
41
|
+
#
|
|
42
|
+
# @param tuple [Hash]
|
|
43
|
+
#
|
|
44
|
+
# @return [Array<Directory::Entry, FalseClass>]
|
|
45
|
+
#
|
|
46
|
+
# @api public
|
|
47
|
+
def update(tuple)
|
|
48
|
+
dataset.modify(tuple)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @example
|
|
52
|
+
# relation.delete #=> { uid: 'batman'}
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<Directory::Entry, FalseClass>]
|
|
55
|
+
#
|
|
56
|
+
# @api public
|
|
57
|
+
def delete
|
|
58
|
+
dataset.delete
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
|
|
6
|
+
module ROM
|
|
7
|
+
module LDAP
|
|
8
|
+
#
|
|
9
|
+
# Loaded by PDU
|
|
10
|
+
#
|
|
11
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.1.9
|
|
12
|
+
#
|
|
13
|
+
RESPONSES_PATH = Pathname(__dir__).join('../../../config/responses.yml').realpath.freeze
|
|
14
|
+
|
|
15
|
+
RESPONSES = ::YAML.load_file(RESPONSES_PATH).freeze
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/ldap/dsl'
|
|
4
|
+
require 'rom/ldap/parsers/filter_syntax'
|
|
5
|
+
|
|
6
|
+
module ROM
|
|
7
|
+
module LDAP
|
|
8
|
+
# @api private
|
|
9
|
+
class RestrictionDSL < DSL
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def call(&block)
|
|
13
|
+
instance_exec(select_relations(block.parameters), &block)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Parse a raw query to AST.
|
|
17
|
+
#
|
|
18
|
+
# @param [String] value
|
|
19
|
+
#
|
|
20
|
+
# @return [AST]
|
|
21
|
+
#
|
|
22
|
+
# @example
|
|
23
|
+
# animals.where { `(cn=dodo)` }.count
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
def `(value)
|
|
27
|
+
Parsers::FilterSyntax.new(value, EMPTY_ARRAY).call
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# @return [Attribute, Type]
|
|
33
|
+
#
|
|
34
|
+
# @api private
|
|
35
|
+
def method_missing(meth, *args, &block)
|
|
36
|
+
if schema.key?(meth)
|
|
37
|
+
schema[meth]
|
|
38
|
+
else
|
|
39
|
+
type(meth)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/schema'
|
|
4
|
+
require 'rom/ldap/schema/dsl'
|
|
5
|
+
require 'rom/ldap/restriction_dsl'
|
|
6
|
+
require 'rom/ldap/projection_dsl'
|
|
7
|
+
require 'rom/ldap/schema/inferrer'
|
|
8
|
+
|
|
9
|
+
module ROM
|
|
10
|
+
module LDAP
|
|
11
|
+
class Schema < ROM::Schema
|
|
12
|
+
|
|
13
|
+
# Open restriction DSL for defining query conditions using schema attributes
|
|
14
|
+
#
|
|
15
|
+
# @see Relation#where
|
|
16
|
+
#
|
|
17
|
+
# @return [Mixed] Result of the block call
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
20
|
+
def restriction(&block)
|
|
21
|
+
RestrictionDSL.new(self).call(&block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Create a new relation based on the schema definition
|
|
25
|
+
#
|
|
26
|
+
# @param relation [Relation] The source relation
|
|
27
|
+
#
|
|
28
|
+
# @return [Relation]
|
|
29
|
+
#
|
|
30
|
+
# @api public
|
|
31
|
+
def call(relation)
|
|
32
|
+
dataset = relation.dataset.with(attrs: map(&:name), aliases: map(&:alias))
|
|
33
|
+
relation.new(dataset, schema: self)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Rename schema attributes
|
|
37
|
+
#
|
|
38
|
+
# @see Relation#rename
|
|
39
|
+
#
|
|
40
|
+
# @return [Schema] A new schema with renamed attributes
|
|
41
|
+
#
|
|
42
|
+
# @api public
|
|
43
|
+
def rename(mapping)
|
|
44
|
+
super map(&:name).map { |k| { k => k } }.reduce(&:merge).merge(mapping)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Project a schema
|
|
48
|
+
#
|
|
49
|
+
# @see ROM::Schema#project
|
|
50
|
+
# @see Relation#select
|
|
51
|
+
#
|
|
52
|
+
# @return [Schema] A new schema with projected attributes
|
|
53
|
+
#
|
|
54
|
+
# @api public
|
|
55
|
+
def project(*names, &block)
|
|
56
|
+
if block
|
|
57
|
+
super(*(names + ProjectionDSL.new(self).call(&block)))
|
|
58
|
+
else
|
|
59
|
+
super
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Project schema so that it only contains primary key
|
|
64
|
+
#
|
|
65
|
+
# @return [Schema]
|
|
66
|
+
#
|
|
67
|
+
# @api private
|
|
68
|
+
def project_pk
|
|
69
|
+
project(*primary_key_names)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Project schema so that it only contains renamed foreign key
|
|
73
|
+
#
|
|
74
|
+
# @return [Schema]
|
|
75
|
+
#
|
|
76
|
+
# @api private
|
|
77
|
+
def project_fk(mapping)
|
|
78
|
+
new(rename(mapping).map(&:foreign_key))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Join with another schema
|
|
82
|
+
#
|
|
83
|
+
# @param [Schema] other The other schema to join with
|
|
84
|
+
#
|
|
85
|
+
# @return [Schema]
|
|
86
|
+
#
|
|
87
|
+
# @api public
|
|
88
|
+
def join(other)
|
|
89
|
+
merge(other.joined)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Return a new schema with all attributes marked as joined
|
|
93
|
+
#
|
|
94
|
+
# @return [Schema]
|
|
95
|
+
#
|
|
96
|
+
# @api public
|
|
97
|
+
def joined
|
|
98
|
+
new(map(&:joined))
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Return an empty schema
|
|
102
|
+
#
|
|
103
|
+
# @return [Schema]
|
|
104
|
+
#
|
|
105
|
+
# @api public
|
|
106
|
+
def empty
|
|
107
|
+
new(EMPTY_ARRAY)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @api private
|
|
111
|
+
def finalize_associations!(relations:)
|
|
112
|
+
super do
|
|
113
|
+
associations.map do |definition|
|
|
114
|
+
LDAP::Associations.const_get(definition.type).new(definition, relations)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
memoize :project_pk, :canonical, :joined
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/initializer'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
class Schema < ROM::Schema
|
|
8
|
+
|
|
9
|
+
# @api private
|
|
10
|
+
class AttributesInferrer
|
|
11
|
+
|
|
12
|
+
extend Initializer
|
|
13
|
+
|
|
14
|
+
option :type_builder
|
|
15
|
+
option :attr_class, optional: true
|
|
16
|
+
|
|
17
|
+
# @api private
|
|
18
|
+
def call(schema, gateway)
|
|
19
|
+
dataset = schema.name.dataset
|
|
20
|
+
columns = dataset_attributes(gateway, dataset)
|
|
21
|
+
|
|
22
|
+
inferred = columns.map do |name|
|
|
23
|
+
type = type_builder.call(name, schema.name)
|
|
24
|
+
attr_class.new(type, name: name.to_sym)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
missing = columns - inferred.map { |attr| attr.meta[:name] }
|
|
28
|
+
|
|
29
|
+
[inferred, missing]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def with(new_options)
|
|
34
|
+
self.class.new(options.merge(new_options))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# All possible formatted Entry attribute names.
|
|
40
|
+
#
|
|
41
|
+
# @see Directory#query_attributes
|
|
42
|
+
#
|
|
43
|
+
# @param dataset [String] LDAP filter string / dataset name
|
|
44
|
+
# @param gateway [ROM::LDAP::Gateway]
|
|
45
|
+
#
|
|
46
|
+
# @return [Array<Symbol, String>]
|
|
47
|
+
#
|
|
48
|
+
# @example => [:cn, :dn, :given_name, :mail, :object_class, :sn]
|
|
49
|
+
#
|
|
50
|
+
# @api private
|
|
51
|
+
def dataset_attributes(gateway, dataset)
|
|
52
|
+
gateway[dataset].flat_map(&:keys).uniq.sort
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/ldap/schema/type_builder'
|
|
4
|
+
require 'rom/ldap/schema/attributes_inferrer'
|
|
5
|
+
require 'rom/ldap/attribute'
|
|
6
|
+
|
|
7
|
+
module ROM
|
|
8
|
+
module LDAP
|
|
9
|
+
class Schema < ROM::Schema
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
class Inferrer < ROM::Schema::Inferrer
|
|
13
|
+
|
|
14
|
+
attributes_inferrer ->(schema, gateway, options) do
|
|
15
|
+
builder = TypeBuilder.new(gateway.attribute_types)
|
|
16
|
+
inferrer = AttributesInferrer.new(type_builder: builder, **options)
|
|
17
|
+
inferrer.call(schema, gateway)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_class LDAP::Attribute
|
|
21
|
+
|
|
22
|
+
option :silent, default: -> { false }
|
|
23
|
+
|
|
24
|
+
option :raise_on_error, default: -> { true }
|
|
25
|
+
|
|
26
|
+
FALLBACK_SCHEMA = {
|
|
27
|
+
attributes: EMPTY_ARRAY,
|
|
28
|
+
indexes: EMPTY_SET
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
# @api private
|
|
32
|
+
def call(schema, gateway)
|
|
33
|
+
inferred = super
|
|
34
|
+
|
|
35
|
+
{ **inferred }
|
|
36
|
+
rescue *CONNECTION_FAILURES => e
|
|
37
|
+
raise ConnectionError, e
|
|
38
|
+
ensure
|
|
39
|
+
FALLBACK_SCHEMA
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def suppress_errors
|
|
43
|
+
with(raise_on_error: false, silent: true)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/ldap/types'
|
|
4
|
+
require 'rom/initializer'
|
|
5
|
+
|
|
6
|
+
module ROM
|
|
7
|
+
module LDAP
|
|
8
|
+
class Schema
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# ATTRIBUTE TYPE
|
|
12
|
+
#
|
|
13
|
+
# An attribute type is a schema element that correlates an OID and a set of
|
|
14
|
+
# names with an attribute syntax and a set of matching rules.
|
|
15
|
+
#
|
|
16
|
+
# The components of an attribute type definition include:
|
|
17
|
+
#
|
|
18
|
+
# - An OID used to uniquely identify the attribute type.
|
|
19
|
+
# - A set of zero or more names that can be used to more easily reference the attribute type.
|
|
20
|
+
# - An optional equality matching rule that specifies how equality matching
|
|
21
|
+
# should be performed on values of that attribute.
|
|
22
|
+
# If no equality matching rule is specified, then the default equality rule
|
|
23
|
+
# for the associated attribute syntax will be used.
|
|
24
|
+
# If the associated syntax doesn't have a default equality matching rule,
|
|
25
|
+
# then equality operations will not be allowed for that attribute.
|
|
26
|
+
# - An optional ordering matching rule that specifies how ordering operations
|
|
27
|
+
# should be performed on values of that attribute.
|
|
28
|
+
# If no ordering matching rule is specified, then the default ordering rule
|
|
29
|
+
# for the associated attribute syntax will be used.
|
|
30
|
+
# If the associated syntax doesn't have a default ordering matching rule,
|
|
31
|
+
# then ordering operations will not be allowed for that attribute.
|
|
32
|
+
# - An optional substring matching rule that specifies how substring matching
|
|
33
|
+
# should be performed on values of that attribute.
|
|
34
|
+
# If no substring matching rule is specified, then the default substring rule
|
|
35
|
+
# for the associated attribute syntax will be used.
|
|
36
|
+
# If the associated syntax doesn't have a default substring matching rule,
|
|
37
|
+
# then substring operations will not be allowed for that attribute.
|
|
38
|
+
# - An optional syntax OID that specifies the syntax for values of the attribute.
|
|
39
|
+
# If no syntax is specified, then it will default to the directory string syntax.
|
|
40
|
+
# - A flag that indicates whether the attribute is allowed to have multiple values.
|
|
41
|
+
# - An optional attribute usage string indicating the context in which the attribute is to be used.
|
|
42
|
+
# - An optional flag that indicates whether the attribute can be modified by external clients.
|
|
43
|
+
#
|
|
44
|
+
# @see Directory.attributes
|
|
45
|
+
#
|
|
46
|
+
# @see <https://docs.oracle.com/cd/E19450-01/820-6173/def-attribute-type.html>
|
|
47
|
+
#
|
|
48
|
+
# @param attributes [Array<Hash>]
|
|
49
|
+
#
|
|
50
|
+
# @api private
|
|
51
|
+
class TypeBuilder
|
|
52
|
+
|
|
53
|
+
extend Initializer
|
|
54
|
+
|
|
55
|
+
param :attributes
|
|
56
|
+
|
|
57
|
+
# @param attribute_name [String, Symbol]
|
|
58
|
+
#
|
|
59
|
+
# @param schema [Schema] Relation schema object.
|
|
60
|
+
#
|
|
61
|
+
# @api public
|
|
62
|
+
def call(attribute_name, schema)
|
|
63
|
+
attribute = find_attribute(attribute_name)
|
|
64
|
+
primitive = map_type(attribute)
|
|
65
|
+
ruby_type = Types.const_get(primitive)
|
|
66
|
+
read_type = !attribute[:single] ? Types.const_get(Inflector.pluralize(primitive)) : ruby_type
|
|
67
|
+
|
|
68
|
+
ruby_type.meta(
|
|
69
|
+
**attribute,
|
|
70
|
+
source: schema,
|
|
71
|
+
name: attribute_name,
|
|
72
|
+
read: read_type.meta(oid: attribute[:oid])
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
# Attribute whose formatted name matches the attribute name.
|
|
79
|
+
#
|
|
80
|
+
# @param name [Symbol, String]
|
|
81
|
+
#
|
|
82
|
+
# @return [Hash]
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
def find_attribute(name)
|
|
86
|
+
attributes.find { |a| a[:name].eql?(name) } || EMPTY_HASH
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Map attribute to Type using known syntax or by inferring from the matchers.
|
|
90
|
+
#
|
|
91
|
+
# @option :syntax [String] attribute syntax
|
|
92
|
+
# @option :matcher [String] attribute matcher
|
|
93
|
+
#
|
|
94
|
+
# @return [String]
|
|
95
|
+
#
|
|
96
|
+
# @api private
|
|
97
|
+
def map_type(syntax: nil, matcher: nil, **)
|
|
98
|
+
by_syntax(syntax) or by_matcher(matcher)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @param oid [String] LDAP Object Identifier
|
|
102
|
+
#
|
|
103
|
+
# @example
|
|
104
|
+
# by_syntax('1.3.6.1.4.1.1466.115.121.1.24') => Time
|
|
105
|
+
#
|
|
106
|
+
# @return [String]
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
def by_syntax(oid)
|
|
110
|
+
OID_TYPE_MAP[oid]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @param matcher [String]
|
|
114
|
+
#
|
|
115
|
+
# @return [String]
|
|
116
|
+
#
|
|
117
|
+
# @api private
|
|
118
|
+
def by_matcher(matcher)
|
|
119
|
+
case matcher
|
|
120
|
+
when *STRING_MATCHERS then 'String'
|
|
121
|
+
when *BOOLEAN_MATCHERS then 'Bool'
|
|
122
|
+
when *INTEGER_MATCHERS then 'Integer'
|
|
123
|
+
when *TIME_MATCHERS then 'Time'
|
|
124
|
+
else
|
|
125
|
+
'String'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|