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,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'dry/core/extensions'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
extend Dry::Core::Extensions
|
|
8
|
+
|
|
9
|
+
# Make entry attributes suitable method names.
|
|
10
|
+
#
|
|
11
|
+
register_extension(:compatibility) do
|
|
12
|
+
require 'rom/ldap/extensions/compatibility'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#=======================================
|
|
16
|
+
# Exporters
|
|
17
|
+
#=======================================
|
|
18
|
+
|
|
19
|
+
# Add #to_dsml method to relation instance.
|
|
20
|
+
#
|
|
21
|
+
register_extension(:dsml_export) do
|
|
22
|
+
require 'rom/ldap/extensions/dsml'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Add #to_msgpack method to relation instance.
|
|
26
|
+
#
|
|
27
|
+
register_extension(:msgpack_export) do
|
|
28
|
+
require 'rom/ldap/extensions/msgpack'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Patch #to_json method in relation instance.
|
|
32
|
+
#
|
|
33
|
+
register_extension(:oj_export) do
|
|
34
|
+
require 'rom/ldap/extensions/optimised_json'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#=======================================
|
|
39
|
+
# Autoloaded for Rails
|
|
40
|
+
#=======================================
|
|
41
|
+
|
|
42
|
+
register_extension(:active_support_notifications) do
|
|
43
|
+
require 'rom/ldap/extensions/active_support_notifications'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
register_extension(:rails_log_subscriber) do
|
|
47
|
+
require 'rom/ldap/extensions/rails_log_subscriber'
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/notifications'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
module ActiveSupportInstrumentation
|
|
8
|
+
def call(filter)
|
|
9
|
+
ActiveSupport::Notifications.instrument(
|
|
10
|
+
'ldap.rom',
|
|
11
|
+
ldap: 'foobar',
|
|
12
|
+
name: instrumentation_name,
|
|
13
|
+
binds: filter
|
|
14
|
+
) { super }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def instrumentation_name
|
|
20
|
+
"ROM[#{directory.type}]"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Dataset.prepend ActiveSupportInstrumentation
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rom/initializer'
|
|
4
|
+
require 'libxml'
|
|
5
|
+
|
|
6
|
+
module ROM
|
|
7
|
+
module LDAP
|
|
8
|
+
#
|
|
9
|
+
# Directory Service Markup Language (DSML)
|
|
10
|
+
#
|
|
11
|
+
# Refines Array and Hash with #to_dsml method.
|
|
12
|
+
#
|
|
13
|
+
# @see https://publib.boulder.ibm.com/tividd/td/ITIM/SC32-1149-01/en_US/HTML/Policy_Org_Admin395.htm
|
|
14
|
+
# @see Directory::Entry
|
|
15
|
+
# @see Relation::Exporting
|
|
16
|
+
#
|
|
17
|
+
module DSML
|
|
18
|
+
# Export Entry objects as DSML files.
|
|
19
|
+
#
|
|
20
|
+
# @param tuple [Entry]
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
class Exporter
|
|
24
|
+
|
|
25
|
+
extend Initializer
|
|
26
|
+
|
|
27
|
+
include LibXML
|
|
28
|
+
|
|
29
|
+
# Dataset
|
|
30
|
+
#
|
|
31
|
+
param :tuples, type: Types::Strict::Array.of(Types::Strict::Hash)
|
|
32
|
+
|
|
33
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
|
34
|
+
# <dsml>
|
|
35
|
+
# <directory-entries>
|
|
36
|
+
# <entry dn="dn">
|
|
37
|
+
#
|
|
38
|
+
# @return [String]
|
|
39
|
+
#
|
|
40
|
+
# @api private
|
|
41
|
+
def to_dsml
|
|
42
|
+
doc = XML::Document.new
|
|
43
|
+
doc.encoding = XML::Encoding::UTF_8
|
|
44
|
+
doc.root = root = create_node('dsml')
|
|
45
|
+
root << (entries = create_node('directory-entries'))
|
|
46
|
+
map_tuples { |entry| entries << entry }
|
|
47
|
+
doc.to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# <entry dn="dn">
|
|
53
|
+
#
|
|
54
|
+
# @yield [LibXML::XML::Node]
|
|
55
|
+
#
|
|
56
|
+
def map_tuples
|
|
57
|
+
tuples.each do |tuple|
|
|
58
|
+
next if tuple.empty?
|
|
59
|
+
|
|
60
|
+
dn = tuple.delete('dn')
|
|
61
|
+
objc = tuple.delete('objectClass')
|
|
62
|
+
|
|
63
|
+
entry_node = create_node('entry', dn: dn&.first)
|
|
64
|
+
|
|
65
|
+
classes(objc) { |c| entry_node << c }
|
|
66
|
+
|
|
67
|
+
attributes(tuple) { |a| entry_node << a }
|
|
68
|
+
|
|
69
|
+
yield(entry_node)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns "<objectclass/>" if param is nil
|
|
74
|
+
#
|
|
75
|
+
# <oc-value>inetOrgPerson</oc-value>
|
|
76
|
+
#
|
|
77
|
+
# @param [Array, Nil] values
|
|
78
|
+
#
|
|
79
|
+
# @yield [LibXML::XML::Node]
|
|
80
|
+
#
|
|
81
|
+
def classes(values)
|
|
82
|
+
class_node = create_node('objectclass')
|
|
83
|
+
values.to_a.each do |value|
|
|
84
|
+
value_node = create_node('oc-value')
|
|
85
|
+
value_node.content = value
|
|
86
|
+
class_node << value_node
|
|
87
|
+
end
|
|
88
|
+
yield(class_node)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @example
|
|
92
|
+
#
|
|
93
|
+
# {'cn'=>['Peter']}
|
|
94
|
+
# => <attr name="cn"><value>Peter</value></attr>
|
|
95
|
+
#
|
|
96
|
+
# @yield [LibXML::XML::Node]
|
|
97
|
+
#
|
|
98
|
+
def attributes(attrs)
|
|
99
|
+
attrs.each do |attr_name, attr_values|
|
|
100
|
+
attr_node = create_node('attr', name: attr_name)
|
|
101
|
+
attr_values.each do |value|
|
|
102
|
+
value_node = create_node('value')
|
|
103
|
+
value_node.content = value
|
|
104
|
+
attr_node << value_node
|
|
105
|
+
end
|
|
106
|
+
yield(attr_node)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# @return [LibXML::XML::Node]
|
|
112
|
+
#
|
|
113
|
+
def create_node(type, params = EMPTY_OPTS)
|
|
114
|
+
node = XML::Node.new(type)
|
|
115
|
+
unless params.empty?
|
|
116
|
+
params.each do |key, value|
|
|
117
|
+
XML::Attr.new(node, key.to_s, value.to_s)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
node
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Extend functionality of Hash class.
|
|
126
|
+
#
|
|
127
|
+
refine ::Hash do
|
|
128
|
+
# Convert hash to DSML format
|
|
129
|
+
#
|
|
130
|
+
# @return [String]
|
|
131
|
+
#
|
|
132
|
+
# @api public
|
|
133
|
+
def to_dsml
|
|
134
|
+
Exporter.new([self]).to_dsml
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Extend functionality of Array class.
|
|
139
|
+
#
|
|
140
|
+
refine ::Array do
|
|
141
|
+
# Convert array to DSML format
|
|
142
|
+
#
|
|
143
|
+
# @return [String]
|
|
144
|
+
#
|
|
145
|
+
# @api public
|
|
146
|
+
def to_dsml
|
|
147
|
+
Exporter.new(self).to_dsml
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
module DSMLExport
|
|
153
|
+
using DSML
|
|
154
|
+
#
|
|
155
|
+
# @return [String]
|
|
156
|
+
#
|
|
157
|
+
# @api public
|
|
158
|
+
def to_dsml
|
|
159
|
+
export.to_dsml
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
Relation.include DSMLExport
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'msgpack'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
module MsgPackExport
|
|
8
|
+
# Export the relation as MessagePack Binary
|
|
9
|
+
#
|
|
10
|
+
# @return [String]
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# relation.to_msgpack
|
|
14
|
+
#
|
|
15
|
+
# @api public
|
|
16
|
+
def to_msgpack
|
|
17
|
+
export.to_msgpack
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Relation.include MsgPackExport
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'oj'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
module OptimisedJSON
|
|
8
|
+
# Replace #to_json
|
|
9
|
+
#
|
|
10
|
+
# @param _opts [Mixed] compatibility with JSON.generate
|
|
11
|
+
#
|
|
12
|
+
# @return [String]
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# relation.to_json
|
|
16
|
+
#
|
|
17
|
+
# @api public
|
|
18
|
+
def to_json(_opts = nil)
|
|
19
|
+
Oj.generate(export)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Relation.include OptimisedJSON
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/log_subscriber'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module LDAP
|
|
7
|
+
class RailsLogSubscriber < ActiveSupport::LogSubscriber
|
|
8
|
+
|
|
9
|
+
def ldap(event)
|
|
10
|
+
return unless logger.debug?
|
|
11
|
+
|
|
12
|
+
payload = event.payload
|
|
13
|
+
|
|
14
|
+
name = format('%s (%.1fms)', payload[:name], event.duration)
|
|
15
|
+
ldap = payload[:ldap].squeeze(' ')
|
|
16
|
+
binds = payload[:binds].to_a.inspect if payload[:binds]
|
|
17
|
+
|
|
18
|
+
if odd?
|
|
19
|
+
name = color(name, :cyan, true)
|
|
20
|
+
ldap = color(ldap, nil, true)
|
|
21
|
+
else
|
|
22
|
+
name = color(name, :magenta, true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
debug " #{name} #{ldap} #{binds}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :odd_or_even
|
|
29
|
+
private :odd_or_even
|
|
30
|
+
def odd?
|
|
31
|
+
@odd_or_even = !odd_or_even
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
RailsLogSubscriber.attach_to(:rom)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module LDAP
|
|
5
|
+
# Proc that returns input value.
|
|
6
|
+
#
|
|
7
|
+
DEFAULT_FORMATTER = ->(v) { v }
|
|
8
|
+
|
|
9
|
+
# Set/Reset the formatting proc
|
|
10
|
+
#
|
|
11
|
+
# @param func [Proc] Callable object
|
|
12
|
+
#
|
|
13
|
+
def self.use_formatter(func = nil)
|
|
14
|
+
@formatter = func
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @see 'rom/ldap/extensions/compatibility'
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# ROM::LDAP.load_extensions :compatibility
|
|
21
|
+
#
|
|
22
|
+
def self.formatter
|
|
23
|
+
@formatter || DEFAULT_FORMATTER
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'dry/transformer/all'
|
|
4
|
+
require 'base64'
|
|
5
|
+
require 'rom/support/inflector'
|
|
6
|
+
|
|
7
|
+
module ROM
|
|
8
|
+
module LDAP
|
|
9
|
+
# @api private
|
|
10
|
+
module Functions
|
|
11
|
+
extend Dry::Transformer::Registry
|
|
12
|
+
|
|
13
|
+
import Dry::Transformer::Coercions
|
|
14
|
+
import Dry::Transformer::ArrayTransformations
|
|
15
|
+
import Dry::Transformer::HashTransformations
|
|
16
|
+
|
|
17
|
+
# Build tuple from arguments.
|
|
18
|
+
# Translates keys into original schema names and stringify values.
|
|
19
|
+
#
|
|
20
|
+
# @param tuple [Hash] input arguments for directory #add and #modify
|
|
21
|
+
#
|
|
22
|
+
# @return [Hash]
|
|
23
|
+
#
|
|
24
|
+
# @note Directory#add will receive a hash with key :dn
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
def self.tuplify(tuple, matrix)
|
|
28
|
+
fn = t(:rename_keys, matrix) >>
|
|
29
|
+
t(:map_values, t(:identify_value)) >>
|
|
30
|
+
t(:map_values, t(:stringify)) >> t(:reject_blank)
|
|
31
|
+
|
|
32
|
+
fn.call(tuple)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# remove keys with blank values
|
|
36
|
+
# nil values allow attribute to be deleted
|
|
37
|
+
#
|
|
38
|
+
def self.reject_blank(tuple)
|
|
39
|
+
tuple.reject { |_k, v| v&.empty? }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Map from
|
|
43
|
+
#
|
|
44
|
+
# @todo Finish documentation
|
|
45
|
+
#
|
|
46
|
+
# @param val [Symbol,String]
|
|
47
|
+
#
|
|
48
|
+
# @example
|
|
49
|
+
# id_value(true) => 'TRUE'
|
|
50
|
+
# id_value('TRUE') => true
|
|
51
|
+
# id_value('peter hamilton') => 'peter hamilton'
|
|
52
|
+
#
|
|
53
|
+
# @return [Mixed]
|
|
54
|
+
#
|
|
55
|
+
# @api private
|
|
56
|
+
def self.identify_value(val)
|
|
57
|
+
case val
|
|
58
|
+
when ::Symbol, ::TrueClass, ::FalseClass, ::NilClass
|
|
59
|
+
VALUES_MAP.fetch(val, val)
|
|
60
|
+
else
|
|
61
|
+
VALUES_MAP.invert.fetch(val, val)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Ensure tuple values are strings or nil
|
|
66
|
+
#
|
|
67
|
+
# @param value [Mixed]
|
|
68
|
+
#
|
|
69
|
+
# @return [String, NilClass]
|
|
70
|
+
#
|
|
71
|
+
# @api private
|
|
72
|
+
def self.stringify(value)
|
|
73
|
+
case value
|
|
74
|
+
when ::Numeric then value.to_s
|
|
75
|
+
when ::Enumerable then value.map(&:to_s)
|
|
76
|
+
when ::Hash then value.to_json
|
|
77
|
+
when ::String then value
|
|
78
|
+
else
|
|
79
|
+
value
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Compare Magic Bytes
|
|
84
|
+
#
|
|
85
|
+
# @see https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
86
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types
|
|
87
|
+
# @see https://github.com/sdsykes/fastimage/blob/master/lib/fastimage.rb
|
|
88
|
+
#
|
|
89
|
+
# @param value [String] UTF-8 encoded
|
|
90
|
+
#
|
|
91
|
+
def self.mime_type(value)
|
|
92
|
+
mime =
|
|
93
|
+
case value[0, 2]
|
|
94
|
+
when "\xFF\xD8".b
|
|
95
|
+
'image/jpeg'
|
|
96
|
+
when "\x89P".b
|
|
97
|
+
'image/png'
|
|
98
|
+
when 'BM'
|
|
99
|
+
'image/bitmap'
|
|
100
|
+
when 'II', 'MM'
|
|
101
|
+
'image/tiff'
|
|
102
|
+
when "\xFF\xFBID".b
|
|
103
|
+
'audio/mpeg'
|
|
104
|
+
when 'WA'
|
|
105
|
+
'audio/x-wav'
|
|
106
|
+
else
|
|
107
|
+
'application/octet-stream'
|
|
108
|
+
end
|
|
109
|
+
to_base64(value).prepend("data:#{mime};base64,")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Base64 encoded string, with optional new line characters.
|
|
113
|
+
#
|
|
114
|
+
# @return [String]
|
|
115
|
+
#
|
|
116
|
+
def self.to_base64(value, strict: true)
|
|
117
|
+
if strict
|
|
118
|
+
Base64.strict_encode64(value).chomp
|
|
119
|
+
else
|
|
120
|
+
# [value].pack('m').chomp
|
|
121
|
+
Base64.encode64(value).chomp
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
#
|
|
126
|
+
#
|
|
127
|
+
# @return [Boolean]
|
|
128
|
+
#
|
|
129
|
+
def self.to_boolean(value)
|
|
130
|
+
Dry::Transformer::Coercions::BOOLEAN_MAP.fetch(value.to_s.downcase)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# The 18-digit Active Directory timestamps, also named
|
|
134
|
+
# 'Windows NT time format','Win32 FILETIME or SYSTEMTIME' or 'NTFS file time'.
|
|
135
|
+
#
|
|
136
|
+
# These are used in Microsoft Active Directory for
|
|
137
|
+
# pwdLastSet, accountExpires, LastLogon, LastLogonTimestamp and LastPwdSet.
|
|
138
|
+
#
|
|
139
|
+
# The number of 100-nanoseconds intervals since 12:00 A.M. January 1st, 1601 (UTC).
|
|
140
|
+
# NB:
|
|
141
|
+
# 1 nanosecond = a billionth of a second
|
|
142
|
+
# Accurate to the nearest millisecond (7 digits)
|
|
143
|
+
#
|
|
144
|
+
# @see ROM::LDAP::Types::Time
|
|
145
|
+
# @see https://ldapwiki.com/wiki/Microsoft%20TIME
|
|
146
|
+
#
|
|
147
|
+
# @param value [String] time or integer
|
|
148
|
+
#
|
|
149
|
+
# @return [Time] UTC formatted
|
|
150
|
+
#
|
|
151
|
+
def self.to_time(value)
|
|
152
|
+
unix_epoch_time = (Integer(value) / TEN_MILLION) - SINCE_1601
|
|
153
|
+
::Time.at(unix_epoch_time).utc
|
|
154
|
+
rescue ArgumentError
|
|
155
|
+
::Time.parse(value).utc
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# @return [Array<String>]
|
|
159
|
+
#
|
|
160
|
+
def self.map_to_base64(values)
|
|
161
|
+
t(:map_array, t(:to_base64)).call(values)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @return [Array<Integer>]
|
|
165
|
+
#
|
|
166
|
+
def self.map_to_integers(tuples)
|
|
167
|
+
t(:map_array, t(:to_integer)).call(tuples)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# @return [Array<Symbol>]
|
|
171
|
+
#
|
|
172
|
+
def self.map_to_symbols(tuples)
|
|
173
|
+
t(:map_array, t(:to_symbol)).call(tuples)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# @return [Array<TrueClass, FalseClass>]
|
|
177
|
+
#
|
|
178
|
+
def self.map_to_booleans(values)
|
|
179
|
+
t(:map_array, t(:to_boolean)).call(values)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# @return [Array<Time>]
|
|
183
|
+
#
|
|
184
|
+
def self.map_to_times(values)
|
|
185
|
+
t(:map_array, t(:to_time)).call(values)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Convert string to snake case.
|
|
189
|
+
#
|
|
190
|
+
# @param value [String]
|
|
191
|
+
#
|
|
192
|
+
# @return [String]
|
|
193
|
+
#
|
|
194
|
+
def self.to_underscore(value)
|
|
195
|
+
Inflector.underscore(value.delete('= '))
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Function applied to Directory::Entry to format incoming attribute names.
|
|
199
|
+
#
|
|
200
|
+
# @api public
|
|
201
|
+
def self.to_method_name(value)
|
|
202
|
+
fn = t(:to_string) >> t(:to_underscore) >> t(:to_symbol)
|
|
203
|
+
fn.call(value)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|