bbk-utils 1.0.1.72694 → 1.0.1.84207
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 +4 -4
- data/Gemfile +3 -0
- data/Gemfile.lock +23 -3
- data/README.md +6 -1
- data/bin/console +2 -0
- data/lib/bbk/utils/config.rb +197 -180
- data/lib/bbk/utils/crypt.rb +31 -23
- data/lib/bbk/utils/env_helper.rb +87 -69
- data/lib/bbk/utils/log_formatter.rb +15 -8
- data/lib/bbk/utils/logger.rb +33 -30
- data/lib/bbk/utils/proxy_logger.rb +29 -24
- data/lib/bbk/utils/version.rb +6 -1
- data/lib/bbk/utils/xml.rb +31 -20
- data/lib/bbk/utils.rb +7 -1
- data/sig/bbk/config.rbs +55 -0
- data/sig/bbk/crypt.rbs +9 -0
- data/sig/bbk/env_helper.rbs +14 -0
- data/sig/bbk/log_formatter.rbs +10 -0
- data/sig/bbk/logger.rbs +15 -0
- data/sig/bbk/proxy_logger.rbs +16 -0
- data/sig/bbk/proxy_object.rbs +7 -0
- data/sig/bbk/utils.rbs +5 -0
- data/sig/bbk/xml.rbs +10 -0
- data/sig/env.rbs +4 -0
- data/sig/logger.rbs +37 -0
- metadata +45 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4c885cb45d09a4268faf157c86945257ffff5e9581a12379c8ef01576df1137
|
4
|
+
data.tar.gz: 139acd30f3c496710ad5d07bf1760833d7069b5dc23ea364c90d739c3eec022b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e6e5899f32ceca3fb0422f568a0696667ed6ee2da0e6ede474fbf9e71fc4a37eadb12b08a8e64524a8ef366e84d351b9ae48f0652f43602a5a76d847e272027
|
7
|
+
data.tar.gz: ec65ba53e4026ee33242883dd2f42058214b3f0bd8d384ba833c952fd0b0391c24e349ad6b3b89b33914d14d9dbed259773c2a5dea24e01a200f956f05365595
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bbk-utils (1.0.1.
|
5
|
-
activesupport
|
4
|
+
bbk-utils (1.0.1.84207)
|
5
|
+
activesupport (~> 6.0)
|
6
6
|
russian
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (
|
11
|
+
activesupport (6.1.6)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
13
|
i18n (>= 1.6, < 2)
|
14
14
|
minitest (>= 5.1)
|
15
15
|
tzinfo (~> 2.0)
|
16
|
+
zeitwerk (~> 2.3)
|
16
17
|
addressable (2.8.0)
|
17
18
|
public_suffix (>= 2.0.2, < 5.0)
|
18
19
|
ansi (1.5.0)
|
@@ -49,6 +50,7 @@ GEM
|
|
49
50
|
launchy (2.5.0)
|
50
51
|
addressable (~> 2.7)
|
51
52
|
minitest (5.15.0)
|
53
|
+
parallel (1.21.0)
|
52
54
|
parser (3.0.3.1)
|
53
55
|
ast (~> 2.4.1)
|
54
56
|
path_expander (1.1.0)
|
@@ -59,6 +61,7 @@ GEM
|
|
59
61
|
kwalify (~> 0.7.0)
|
60
62
|
parser (~> 3.0.0)
|
61
63
|
rainbow (>= 2.0, < 4.0)
|
64
|
+
regexp_parser (2.2.0)
|
62
65
|
rexml (3.2.5)
|
63
66
|
rspec (3.10.0)
|
64
67
|
rspec-core (~> 3.10.0)
|
@@ -75,6 +78,20 @@ GEM
|
|
75
78
|
rspec-support (3.10.3)
|
76
79
|
rspec_junit_formatter (0.4.1)
|
77
80
|
rspec-core (>= 2, < 4, != 2.12.0)
|
81
|
+
rubocop (1.22.3)
|
82
|
+
parallel (~> 1.10)
|
83
|
+
parser (>= 3.0.0.0)
|
84
|
+
rainbow (>= 2.2.2, < 4.0)
|
85
|
+
regexp_parser (>= 1.8, < 3.0)
|
86
|
+
rexml
|
87
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
88
|
+
ruby-progressbar (~> 1.7)
|
89
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
90
|
+
rubocop-ast (1.13.0)
|
91
|
+
parser (>= 3.0.1.1)
|
92
|
+
rubocop-rspec (2.6.0)
|
93
|
+
rubocop (~> 1.19)
|
94
|
+
ruby-progressbar (1.11.0)
|
78
95
|
ruby_parser (3.18.1)
|
79
96
|
sexp_processor (~> 4.16)
|
80
97
|
rubycritic (4.6.1)
|
@@ -116,6 +133,7 @@ GEM
|
|
116
133
|
coercible (~> 1.0)
|
117
134
|
descendants_tracker (~> 0.0, >= 0.0.3)
|
118
135
|
equalizer (~> 0.0, >= 0.0.9)
|
136
|
+
zeitwerk (2.5.4)
|
119
137
|
|
120
138
|
PLATFORMS
|
121
139
|
ruby
|
@@ -129,6 +147,8 @@ DEPENDENCIES
|
|
129
147
|
rake (~> 12.0)
|
130
148
|
rspec (~> 3.0)
|
131
149
|
rspec_junit_formatter
|
150
|
+
rubocop
|
151
|
+
rubocop-rspec
|
132
152
|
rubycritic
|
133
153
|
simplecov
|
134
154
|
simplecov-cobertura
|
data/README.md
CHANGED
@@ -42,6 +42,11 @@ gem "bbk-utils", "~> 1.0.0"
|
|
42
42
|
* Ruby (MRI) 2.5.x
|
43
43
|
* Ruby (MRI) 3.0.x
|
44
44
|
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
See the file [CONTRIBUTING.md](./CONTRIBUTING.md)
|
48
|
+
|
45
49
|
## License
|
46
50
|
|
47
|
-
|
51
|
+
See the file [LICENSE](./LICENSE)
|
52
|
+
|
data/bin/console
CHANGED
data/lib/bbk/utils/config.rb
CHANGED
@@ -1,223 +1,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BBK
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
4
|
+
module Utils
|
5
|
+
class Config
|
6
|
+
|
7
|
+
attr_accessor :store, :name
|
8
|
+
|
9
|
+
class BooleanCaster
|
10
|
+
|
11
|
+
FALSE_VALUES = [
|
12
|
+
false, 0,
|
13
|
+
'0', :"0",
|
14
|
+
'f', :f,
|
15
|
+
'F', :F,
|
16
|
+
'false', false,
|
17
|
+
'FALSE', :FALSE,
|
18
|
+
'off', :off,
|
19
|
+
'OFF', :OFF
|
20
|
+
].to_set.freeze
|
21
|
+
|
22
|
+
def self.cast(value)
|
23
|
+
if value.nil? || value == ''
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
!FALSE_VALUES.include?(value)
|
27
|
+
end
|
23
28
|
end
|
29
|
+
|
24
30
|
end
|
25
|
-
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
def self.instance
|
33
|
+
@instance ||= new
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
delegate :map, :require, :optional, :run!, :[], :[]=, :content, :to_s, :to_json, :as_json, :to_yaml, :fetch, to: :instance
|
33
|
-
end
|
36
|
+
class << self
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
@store = {}
|
38
|
-
end
|
38
|
+
delegate :map, :require, :optional, :run!, :[], :[]=, :content, :to_s, :to_json, :as_json, :to_yaml, :fetch,
|
39
|
+
to: :instance
|
39
40
|
|
40
|
-
|
41
|
-
@store[env.to_s.upcase] = {
|
42
|
-
env: (key || env).to_s.upcase,
|
43
|
-
file: file,
|
44
|
-
required: required,
|
45
|
-
desc: desc,
|
46
|
-
bool: bool
|
47
|
-
}
|
48
|
-
end
|
41
|
+
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@store[env.to_s.upcase] = {
|
55
|
-
env: (key || env).to_s.upcase,
|
56
|
-
required: true,
|
57
|
-
desc: desc,
|
58
|
-
bool: bool,
|
59
|
-
type: type
|
60
|
-
}
|
61
|
-
end
|
43
|
+
def initialize(name = nil)
|
44
|
+
@name = name
|
45
|
+
@store = {}
|
46
|
+
end
|
62
47
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
}
|
74
|
-
end
|
48
|
+
def map(env, file, required: true, desc: nil, bool: false, key: nil)
|
49
|
+
@store[env.to_s.upcase] = {
|
50
|
+
env: (key || env).to_s.upcase,
|
51
|
+
file: file,
|
52
|
+
required: required,
|
53
|
+
desc: desc,
|
54
|
+
bool: bool,
|
55
|
+
type: nil
|
56
|
+
}
|
57
|
+
end
|
75
58
|
|
76
|
-
|
77
|
-
|
78
|
-
|
59
|
+
def require(env, desc: nil, bool: false, type: nil, key: nil)
|
60
|
+
raise ArgumentError.new('Specified type and bool') if bool && type.present?
|
61
|
+
|
62
|
+
type = BBK::Config::BooleanCaster.singleton_method(:cast) if bool
|
63
|
+
@store[env.to_s.upcase] = {
|
64
|
+
env: (key || env).to_s.upcase,
|
65
|
+
file: nil,
|
66
|
+
required: true,
|
67
|
+
desc: desc,
|
68
|
+
bool: bool,
|
69
|
+
type: type
|
70
|
+
}
|
79
71
|
end
|
80
|
-
end
|
81
72
|
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
def optional(env, default: nil, desc: nil, bool: false, type: nil, key: nil)
|
74
|
+
raise ArgumentError.new('Specified type and bool') if bool && type.present?
|
75
|
+
|
76
|
+
type = BBK::Utils::Config::BooleanCaster.singleton_method(:cast) if bool
|
77
|
+
@store[env.to_s.upcase] = {
|
78
|
+
env: (key || env).to_s.upcase,
|
79
|
+
file: nil,
|
80
|
+
required: false,
|
81
|
+
default: default,
|
82
|
+
desc: desc,
|
83
|
+
bool: true,
|
84
|
+
type: type
|
85
|
+
}
|
86
|
+
end
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
def run!(source = ENV)
|
89
|
+
@store.each_value do |item|
|
90
|
+
process(source, item)
|
91
|
+
end
|
92
|
+
end
|
89
93
|
|
90
|
-
|
91
|
-
|
92
|
-
if (file = item[:file])
|
93
|
-
File.read(file)
|
94
|
-
else
|
95
|
-
item[:value]
|
94
|
+
def [](key)
|
95
|
+
@store[normalize_key(key)][:value]
|
96
96
|
end
|
97
|
-
end
|
98
97
|
|
99
|
-
|
100
|
-
|
101
|
-
if (field = store[key.to_s.upcase]).present? && field.key?(:value)
|
102
|
-
field[:value]
|
103
|
-
else
|
104
|
-
default
|
98
|
+
def []=(key, value)
|
99
|
+
@store[normalize_key(key)][:value] = value
|
105
100
|
end
|
106
|
-
end
|
107
101
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
102
|
+
def content(key)
|
103
|
+
item = @store[normalize_key(key)]
|
104
|
+
if (file = item[:file])
|
105
|
+
File.read(file)
|
106
|
+
else
|
107
|
+
item[:value]
|
108
|
+
end
|
109
|
+
end
|
113
110
|
|
114
|
-
|
115
|
-
|
116
|
-
|
111
|
+
def fetch(key, default = nil)
|
112
|
+
# store.fetch(key.to_s.upcase, default)
|
113
|
+
if (field = store[key.to_s.upcase]).present? && field.key?(:value)
|
114
|
+
field[:value]
|
117
115
|
else
|
118
|
-
|
116
|
+
default
|
119
117
|
end
|
120
118
|
end
|
121
|
-
result.string
|
122
|
-
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
120
|
+
def to_s
|
121
|
+
result = StringIO.new
|
122
|
+
result.puts "Environment variables#{@name ? " for #{@name}" : ''}:"
|
123
|
+
padding = ' ' * 3
|
124
|
+
sorted = @store.values.sort_by do |item|
|
125
|
+
[item[:file].present? ? 0 : 1, item[:required] ? 0 : 1]
|
126
|
+
end
|
127
|
+
|
128
|
+
sorted.each do |item|
|
129
|
+
if item[:file]
|
130
|
+
result.puts print_file_item(item, padding)
|
131
|
+
else
|
132
|
+
result.puts print_item(item, padding)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
result.string
|
129
136
|
end
|
130
137
|
|
131
|
-
|
132
|
-
|
138
|
+
def as_json(*_args)
|
139
|
+
values = @store.values.sort_by do |item|
|
140
|
+
[item[:file].present? ? 0 : 1, item[:required] ? 0 : 1]
|
141
|
+
end.reduce({}) do |ret, item|
|
142
|
+
ret.merge(item[:env] => item)
|
143
|
+
end
|
133
144
|
|
134
|
-
|
135
|
-
|
136
|
-
end
|
145
|
+
@name ? { @name => values } : values
|
146
|
+
end
|
137
147
|
|
138
|
-
|
139
|
-
|
140
|
-
|
148
|
+
def to_json(*_args)
|
149
|
+
JSON.pretty_generate(as_json)
|
150
|
+
end
|
141
151
|
|
142
|
-
|
152
|
+
def to_yaml(*_args)
|
153
|
+
JSON.parse(to_json).to_yaml
|
154
|
+
end
|
143
155
|
|
144
|
-
|
145
|
-
k = key.to_s.upcase
|
146
|
-
raise "There is no such key: #{k} in config!" unless @store.key?(k)
|
156
|
+
private
|
147
157
|
|
148
|
-
|
149
|
-
|
158
|
+
def normalize_key(key)
|
159
|
+
k = key.to_s.upcase
|
160
|
+
raise "There is no such key: #{k} in config!" unless @store.key?(k)
|
150
161
|
|
151
|
-
|
152
|
-
|
162
|
+
k
|
163
|
+
end
|
153
164
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
165
|
+
def process(source, item)
|
166
|
+
content = source.fetch(item[:env], item[:default])
|
167
|
+
|
168
|
+
# Если данные есть, либо указан тип (нужно для того чтобы переменная была нужного типа)
|
169
|
+
if content.present? || item[:type].present?
|
170
|
+
if file = item[:file]
|
171
|
+
dirname = File.dirname(file)
|
172
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
173
|
+
File.write(file, content)
|
174
|
+
item[:value] = file
|
175
|
+
else
|
176
|
+
item[:value] = if (type = item[:type])
|
177
|
+
if type.respond_to? :call
|
178
|
+
type.call(content)
|
179
|
+
else
|
180
|
+
type.new(content)
|
181
|
+
end
|
182
|
+
else
|
183
|
+
content
|
184
|
+
end
|
185
|
+
end
|
186
|
+
elsif item[:required]
|
187
|
+
required!(item)
|
188
|
+
else
|
189
|
+
item[:value] = content
|
190
|
+
end
|
191
|
+
rescue StandardError => e
|
192
|
+
msg = "Failed processing #{item[:env]} parameter. #{e.inspect}"
|
193
|
+
if $logger
|
194
|
+
$logger.error msg
|
195
|
+
else
|
196
|
+
puts msg
|
197
|
+
end
|
198
|
+
raise
|
171
199
|
end
|
172
|
-
elsif item[:required]
|
173
|
-
required!(item)
|
174
|
-
else
|
175
|
-
item[:value] = content
|
176
|
-
end
|
177
|
-
rescue => e
|
178
|
-
msg = "Failed processing #{item[:env]} parameter. #{e.inspect}"
|
179
|
-
if $logger
|
180
|
-
$logger.error msg
|
181
|
-
else
|
182
|
-
puts msg
|
183
|
-
end
|
184
|
-
raise
|
185
|
-
end
|
186
200
|
|
187
|
-
|
188
|
-
|
189
|
-
|
201
|
+
def required!(item)
|
202
|
+
raise "ENV [#{item[:env]}] is required!"
|
203
|
+
end
|
190
204
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
205
|
+
def print_file_item(item, padding)
|
206
|
+
line = "#{padding}File #{wrap_required(item)}"
|
207
|
+
line = if item[:desc].present?
|
208
|
+
"#{line.ljust(50)} #{item[:desc]}"
|
209
|
+
else
|
210
|
+
line
|
211
|
+
end
|
198
212
|
|
199
|
-
|
200
|
-
|
213
|
+
"#{line}\n#{padding * 2}-> #{item[:file].inspect}"
|
214
|
+
end
|
201
215
|
|
202
|
-
|
203
|
-
|
204
|
-
|
216
|
+
def print_item(item, padding)
|
217
|
+
line = padding + wrap_required(item)
|
218
|
+
line += " (=#{item[:default]})" if item[:default].present?
|
205
219
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
220
|
+
line = if item[:desc].present?
|
221
|
+
"#{line.ljust(50)} #{item[:desc]}"
|
222
|
+
else
|
223
|
+
line
|
224
|
+
end
|
211
225
|
|
212
|
-
|
213
|
-
|
226
|
+
"#{line}\n#{padding * 2}-> #{item[:value].inspect}"
|
227
|
+
end
|
228
|
+
|
229
|
+
def wrap_required(item)
|
230
|
+
if item[:required]
|
231
|
+
"<#{item[:env]}>"
|
232
|
+
else
|
233
|
+
"[#{item[:env]}]"
|
234
|
+
end
|
235
|
+
end
|
214
236
|
|
215
|
-
def wrap_required(item)
|
216
|
-
if item[:required]
|
217
|
-
"<#{item[:env]}>"
|
218
|
-
else
|
219
|
-
"[#{item[:env]}]"
|
220
|
-
end
|
221
237
|
end
|
222
238
|
end
|
223
239
|
end
|
240
|
+
|
data/lib/bbk/utils/crypt.rb
CHANGED
@@ -1,34 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
|
3
5
|
module BBK
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
errors
|
6
|
+
module Utils
|
7
|
+
class Crypt
|
8
|
+
|
9
|
+
def self.full_check(key_path, cert_path, *cacert_chain)
|
10
|
+
errors = []
|
11
|
+
errors << 'Invalid key and cert pair' unless valid_key_cert?(key_path, cert_path)
|
12
|
+
errors << 'Invalid cert and cacert pair' unless valid_cert_sign?(cert_path,
|
13
|
+
*cacert_chain.compact)
|
14
|
+
if errors.empty?
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
errors
|
18
|
+
end
|
13
19
|
end
|
14
|
-
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
def self.valid_key_cert?(key_path, cert_path)
|
22
|
+
raise "Key file #{key_path} not exists" unless File.exist? key_path
|
23
|
+
raise "Cert file #{cert_path} not exists" unless File.exist? cert_path
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
key = OpenSSL::PKey::RSA.new(File.read(key_path))
|
26
|
+
cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
|
27
|
+
cert.check_private_key(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.valid_cert_sign?(cert_path, *ca_certs_paths)
|
31
|
+
raise "Cert file #{cert_path} not exists" unless File.exist? cert_path
|
32
|
+
raise "Not all files in ca chain #{ca_certs_paths} exists" unless ca_certs_paths.all? {|pth| File.exist? pth }
|
24
33
|
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
store = ca_certs_paths.reduce(OpenSSL::X509::Store.new) {|st, c| st.add_file(c) }
|
35
|
+
cert = OpenSSL::X509::Certificate.new File.read(cert_path)
|
36
|
+
store.verify(cert)
|
37
|
+
end
|
28
38
|
|
29
|
-
store = ca_certs_paths.reduce(OpenSSL::X509::Store.new) { |st, c| st.add_file(c) }
|
30
|
-
cert = OpenSSL::X509::Certificate.new File.read(cert_path)
|
31
|
-
store.verify(cert)
|
32
39
|
end
|
33
40
|
end
|
34
41
|
end
|
42
|
+
|