eco-helpers 2.4.8 → 2.5.1

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -1
  3. data/eco-helpers.gemspec +17 -17
  4. data/lib/eco/api/common/class_auto_loader.rb +8 -3
  5. data/lib/eco/api/common/loaders/base.rb +5 -1
  6. data/lib/eco/api/common/loaders/case_base.rb +2 -3
  7. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +97 -47
  8. data/lib/eco/api/common/people/default_parsers/select_parser.rb +2 -2
  9. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +0 -1
  10. data/lib/eco/api/common/people/entry_factory.rb +13 -8
  11. data/lib/eco/api/common/people/person_attribute_parser.rb +1 -1
  12. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +2 -2
  13. data/lib/eco/api/common/people/person_parser.rb +1 -1
  14. data/lib/eco/api/common/session/base_session.rb +1 -2
  15. data/lib/eco/api/common/session/environment.rb +6 -10
  16. data/lib/eco/api/common/session/helpers/prompt_user.rb +18 -18
  17. data/lib/eco/api/common/session/logger.rb +2 -2
  18. data/lib/eco/api/common/session/mailer.rb +1 -3
  19. data/lib/eco/api/common/session/s3_uploader.rb +1 -3
  20. data/lib/eco/api/common/session/sftp.rb +6 -4
  21. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +5 -4
  22. data/lib/eco/api/error.rb +5 -5
  23. data/lib/eco/api/session/config/api.rb +4 -2
  24. data/lib/eco/api/usecases/base_case.rb +0 -2
  25. data/lib/eco/api/usecases/base_io.rb +0 -3
  26. data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +1 -1
  27. data/lib/eco/api/usecases/ooze_samples/ooze_from_doc_case.rb +1 -2
  28. data/lib/eco/api/usecases/ooze_samples/ooze_run_base_case.rb +0 -1
  29. data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +0 -1
  30. data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +1 -1
  31. data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +0 -2
  32. data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +0 -1
  33. data/lib/eco/api/usecases/ooze_samples.rb +0 -1
  34. data/lib/eco/api/usecases/use_case.rb +30 -1
  35. data/lib/eco/api/usecases/use_case_chain.rb +1 -4
  36. data/lib/eco/api/usecases/use_case_io.rb +0 -2
  37. data/lib/eco/api/usecases.rb +4 -4
  38. data/lib/eco/api.rb +0 -2
  39. data/lib/eco/cli/config/default/options.rb +11 -1
  40. data/lib/eco/cli/scripting/arguments.rb +1 -1
  41. data/lib/eco/csv.rb +4 -7
  42. data/lib/eco/data/files/directory.rb +0 -3
  43. data/lib/eco/data/files/encoding.rb +75 -0
  44. data/lib/eco/data/files/helpers.rb +15 -37
  45. data/lib/eco/data/files.rb +1 -0
  46. data/lib/eco/data/fuzzy_match.rb +8 -4
  47. data/lib/eco/data.rb +0 -1
  48. data/lib/eco/version.rb +1 -1
  49. data/lib/eco-helpers.rb +1 -1
  50. metadata +23 -24
  51. data/lib/eco/data/crypto/encryption.rb +0 -321
  52. data/lib/eco/data/crypto.rb +0 -7
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.8
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 2.4.8
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.5'
22
+ version: '3'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 2.4.8
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.5'
32
+ version: '3'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rspec
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: 3.10.0
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '3.11'
42
+ version: '4'
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: 3.10.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '3.11'
52
+ version: '4'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: rake
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -59,7 +59,7 @@ dependencies:
59
59
  version: 13.0.3
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
- version: '13.1'
62
+ version: '14'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  version: 13.0.3
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: '13.1'
72
+ version: '14'
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: yard
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: 0.9.26
80
80
  - - "<"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.10'
82
+ version: '1'
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: 0.9.26
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: '0.10'
92
+ version: '1'
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: redcarpet
95
95
  requirement: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 3.5.1
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: '3.6'
102
+ version: '4'
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
@@ -109,14 +109,14 @@ dependencies:
109
109
  version: 3.5.1
110
110
  - - "<"
111
111
  - !ruby/object:Gem::Version
112
- version: '3.6'
112
+ version: '4'
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ecoportal-api
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: 0.9.3
119
+ version: 0.9.4
120
120
  - - "<"
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0.10'
@@ -126,7 +126,7 @@ dependencies:
126
126
  requirements:
127
127
  - - ">="
128
128
  - !ruby/object:Gem::Version
129
- version: 0.9.3
129
+ version: 0.9.4
130
130
  - - "<"
131
131
  - !ruby/object:Gem::Version
132
132
  version: '0.10'
@@ -136,7 +136,7 @@ dependencies:
136
136
  requirements:
137
137
  - - ">="
138
138
  - !ruby/object:Gem::Version
139
- version: 1.1.1
139
+ version: 1.1.2
140
140
  - - "<"
141
141
  - !ruby/object:Gem::Version
142
142
  version: '1.2'
@@ -146,7 +146,7 @@ dependencies:
146
146
  requirements:
147
147
  - - ">="
148
148
  - !ruby/object:Gem::Version
149
- version: 1.1.1
149
+ version: 1.1.2
150
150
  - - "<"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '1.2'
@@ -156,7 +156,7 @@ dependencies:
156
156
  requirements:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: 0.3.5
159
+ version: 0.3.7
160
160
  - - "<"
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0.4'
@@ -166,7 +166,7 @@ dependencies:
166
166
  requirements:
167
167
  - - ">="
168
168
  - !ruby/object:Gem::Version
169
- version: 0.3.5
169
+ version: 0.3.7
170
170
  - - "<"
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0.4'
@@ -219,7 +219,7 @@ dependencies:
219
219
  version: 2.7.6
220
220
  - - "<"
221
221
  - !ruby/object:Gem::Version
222
- version: '2.8'
222
+ version: '3'
223
223
  type: :runtime
224
224
  prerelease: false
225
225
  version_requirements: !ruby/object:Gem::Requirement
@@ -229,7 +229,7 @@ dependencies:
229
229
  version: 2.7.6
230
230
  - - "<"
231
231
  - !ruby/object:Gem::Version
232
- version: '2.8'
232
+ version: '3'
233
233
  - !ruby/object:Gem::Dependency
234
234
  name: net-sftp
235
235
  requirement: !ruby/object:Gem::Requirement
@@ -239,7 +239,7 @@ dependencies:
239
239
  version: 3.0.0
240
240
  - - "<"
241
241
  - !ruby/object:Gem::Version
242
- version: '3.1'
242
+ version: '4'
243
243
  type: :runtime
244
244
  prerelease: false
245
245
  version_requirements: !ruby/object:Gem::Requirement
@@ -249,7 +249,7 @@ dependencies:
249
249
  version: 3.0.0
250
250
  - - "<"
251
251
  - !ruby/object:Gem::Version
252
- version: '3.1'
252
+ version: '4'
253
253
  - !ruby/object:Gem::Dependency
254
254
  name: hashdiff
255
255
  requirement: !ruby/object:Gem::Requirement
@@ -644,10 +644,9 @@ files:
644
644
  - lib/eco/csv.rb
645
645
  - lib/eco/csv/table.rb
646
646
  - lib/eco/data.rb
647
- - lib/eco/data/crypto.rb
648
- - lib/eco/data/crypto/encryption.rb
649
647
  - lib/eco/data/files.rb
650
648
  - lib/eco/data/files/directory.rb
649
+ - lib/eco/data/files/encoding.rb
651
650
  - lib/eco/data/files/file_pattern.rb
652
651
  - lib/eco/data/files/helpers.rb
653
652
  - lib/eco/data/fuzzy_match.rb
@@ -698,7 +697,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
698
697
  - !ruby/object:Gem::Version
699
698
  version: '0'
700
699
  requirements: []
701
- rubygems_version: 3.1.4
700
+ rubygems_version: 3.4.12
702
701
  signing_key:
703
702
  specification_version: 4
704
703
  summary: eco-helpers to manage people api cases
@@ -1,321 +0,0 @@
1
- require 'openssl'
2
- # 'json'
3
- require 'base64'
4
- #require 'pp'
5
-
6
- require_relative '../../cli/scripting'
7
-
8
- # see some ramblings here: http://distributed-frostbite.blogspot.com/2010/06/file-encryption-in-ruby-with-openssl.html
9
-
10
-
11
- def run! # this will run only if called from command line (not when require'd nor load'd)
12
- include Eco::CLI::Scripting
13
- include Eco::Data::Crypto
14
- # script arguments
15
- keygen = get_arg("-keygen")
16
- filename = get_arg("-keygen", with_param: true)
17
- ssh = get_arg("-ssh")
18
- length = get_arg("-length", with_param: true)
19
- check_rsa_pairs = get_arg("-keypairs")
20
- key_filename = get_arg("-keypairs", with_param: true)
21
-
22
- # methods
23
- case true
24
- when keygen
25
- puts "++ keygen RSA ++"
26
- #pp ::OpenSSL.constants.sort
27
- cr = Eco::Data::Crypto::OpenSSL.new
28
- case true
29
- when ssh
30
- puts "think about installing this library: https://rubygems.org/gems/sshkey"
31
- puts "GitHub: https://github.com/bensie/sshkey"
32
- puts "or add this Ruby solution to convert to ssh-rsa: https://stackoverflow.com/a/3162593/4352306"
33
- exit(1)
34
- cr.rsa_keygen_ssh(filename: filename)
35
- else
36
- cr.rsa_keygen(filename: filename)
37
- end
38
- when check_rsa_pairs
39
- puts "++ checking file pairs ++"
40
- begin
41
- key_filename = "rsa" if !key_filename
42
- priv = File.read(key_filename + '.pem')
43
- pub = File.read(key_filename + '.pub')
44
- rescue
45
- puts "could not find files with basename: #{key_filename}"
46
- exit(1)
47
- end
48
- cr = Eco::Data::Crypto::OpenSSL.new
49
- equals = cr.rsa_keypairs?(priv, pub)
50
- if equals
51
- puts "the pair #{key_filename} seem to be for one to another!"
52
- else
53
- puts "those files with base name #{key_filename} are not a rsa pair"
54
- end
55
- end
56
- end
57
-
58
-
59
- module Eco
60
- module Data
61
- #TODO study how to encrypt uniquely the api key in the configuration file
62
- #TODO study how RSA could boost team-shared Drive folder (updates, and people files should be encrypted via public key)
63
- module Crypto
64
- # file conf definitions
65
- THIS_FILENAME = __FILE__
66
- MY_NAME = File.basename(THIS_FILENAME, File.extname(THIS_FILENAME)) # ".rb"
67
- PATH = File.dirname(THIS_FILENAME)
68
- WORKING_DIR = PATH + "/" + MY_NAME
69
- PARSER_FILE = WORKING_DIR + "/json_parser.json" # .dll
70
-
71
- class OpenSSL
72
- DEFAULT_KEY_LENGTH = 256
73
- DEFAULT_RSA_LENGTH = 2048
74
- SALT_LENGTH = 128
75
- SALT_SEED = "$%!@_halt9000"
76
- BLOCK_OCTETS = 512
77
- attr_accessor :salt_seed
78
- attr_reader :digest, :pkcs5, :kdf, :cipher, :rsa
79
- attr_reader :salt
80
- def initialize(init = {})
81
- @digest = ::OpenSSL::Digest
82
- @pkcs5 = ::OpenSSL::PKCS5
83
- #@kdf = ::OpenSSL::KDF
84
- @cipher = ::OpenSSL::Cipher
85
- self.salt_seed = SALT_SEED
86
- @rsa = ::OpenSSL::PKey::RSA
87
- end
88
- def salt_seed=(value)
89
- @salt_seed = value
90
- @salt = self.pbkdf2(@salt_seed, salt: @salt_seed, length: SALT_LENGTH)
91
- end
92
- def sha256 (str = nil)
93
- sha = @digest.SHA256.new
94
- digest = sha.digest(str) unless !str
95
- sha.reset
96
- digest
97
- end
98
- def sha512 (str = nil)
99
- sha = @digest.SHA512.new
100
- digest = sha.digest(str) unless !str
101
- sha.reset
102
- digest
103
- end
104
- # default hmac hash to "sha256" -> https://github.com/hueniverse/iron/issues/55
105
- def pbkdf2 (pass, salt: @salt || "salt", iterations: 1000, length: DEFAULT_KEY_LENGTH, hash: "sha256")
106
- octets = length.div(8)
107
- #puts "this has been called"
108
- #puts "pass: #{pass}"
109
- #puts "salt: #{salt}"
110
- #puts "iterations: #{iterations}"
111
- #puts "length: #{length}"
112
- #puts "hash: #{hash}"
113
- @pkcs5.pbkdf2_hmac(pass, salt, iterations, octets, hash)
114
- end
115
- def pbkdf2_sha1 (pass, salt: @salt, iterations: 1000, length: DEFAULT_KEY_LENGTH)
116
- #self.pbkdf2(pass, salt: salt, iterations: iternations, length: length, hash: "sha1")
117
- @pkcs5.pbkdf2_hmac(pass, salt, iterations, octets, "sha1")
118
- end
119
- =begin
120
- def scrypt (pass, salt: @salt, cost: 14, length: DEFAULT_KEY_LENGTH)
121
- block_size = 8
122
- parallelization = 1
123
- octets = length.div(8)
124
- @kdf.scrypt(pass, salt: salt, N: 2**cost, r: block_size, p: parallelization, length: octets)
125
- end
126
- =end
127
- def aes256_pass(pass)
128
- self.pbkdf2(pass, length: 256)
129
- end
130
- def aes256_encrypt(data, key: nil, iv: nil, block_octets: BLOCK_OCTETS)
131
- block_bits = block_bits * 8
132
- cipher = @cipher.new('aes-256-cbc')
133
- cipher.encrypt
134
-
135
- if key ; cipher.key = key
136
- else ; key = cipher.random_key
137
- end
138
- if iv ; cipher.iv = iv
139
- else ; iv = cipher.random_iv
140
- end
141
-
142
- str_c = ""
143
- while str.length > 0
144
- str_c += cipher.update(str.slice!(0, block_bits))
145
- end
146
- str_c += cipher.final
147
- return str_c
148
- #EncryptedData.new({content: str_c, key: key, iv: iv})
149
-
150
-
151
- end
152
- def aes256_decrypt(data, key: , iv: , block_octets: BLOCK_OCTETS)
153
- block_bits = block_bits * 8
154
- #validation = encrypted_data && encrypted_data.key && encrypted_data.iv
155
- # return nil unless validation
156
- cipher = @cipher.new('aes-256-cbc')
157
- cipher.decrypt
158
- cipher.key = key
159
- cipher.iv = iv
160
- #cipher.key = encrypted_data.key
161
- #cipher.iv = encrypted_data.iv
162
- #str_c = encrypted_data.content
163
- str_c = data
164
- str = ""
165
- while str_c.length > 0
166
- str += cipher.update(str_c.slice!(0, block_bits))
167
- #puts str[-50..-1] || str
168
- end
169
- str += cipher.final
170
- return str
171
- end
172
- def rsa_keygen(length = DEFAULT_RSA_LENGTH, filename: "rsa")
173
- filename = "rsa" if !filename
174
- key = @rsa.new(length)
175
- File.open('./' + filename + '.pem',"w") {|fd| fd << key.to_pem }
176
- File.open('./' + filename + '.pub',"w") {|fd| fd << key.public_key.to_pem }
177
- end
178
- def rsa_keygen_ssh(length = DEFAULT_RSA_LENGTH, filename: "rsa")
179
- # to do conersion pem to ssh-rsa: https://stackoverflow.com/a/3162593/4352306
180
- # conversion explained here: http://blog.oddbit.com/2011/05/08/converting-openssh-public-keys/
181
- # much simpler developed in php here: https://stackoverflow.com/a/5524323/4352306
182
- filename = "rsa" if !filename
183
- key = @rsa.new(length)
184
- File.open('./' + filename + '.der',"w") {|fd| fd << key.ssh_type }
185
- File.open('./' + filename + '.pub',"w") {|fd| fd << key.public_key.ssh_type }
186
- end
187
- def rsa_keypairs?(private_key, public_key)
188
- str_original = "See, my mule don’t like people laughing"
189
-
190
- pub_key = @rsa.new(public_key)
191
- str_original.force_encoding(Encoding::UTF_8)
192
- encrypted_data = Base64.encode64(pub_key.public_encrypt(str_original))
193
-
194
- priv_key = @rsa.new(private_key)
195
- begin # see here: https://stackoverflow.com/a/13251160/4352306 (padding error when false pub key)
196
- decrypted_data = priv_key.private_decrypt(Base64.decode64(encrypted_data))
197
- # OpenSSL core Ruby library is written in C which uses different encoding (ASCII-8BIT)
198
- # that's why we force UTF-8 encoding (before and after encryption)
199
- # see this answer: https://stackoverflow.com/a/27326915/4352306
200
- decrypted_data.force_encoding(Encoding::UTF_8)
201
- rescue
202
- return false
203
- end
204
-
205
- puts "encrypted string: #{str_original}"
206
- puts "decrypted string: #{decrypted_data}"
207
- return (decrypted_data == str_original)
208
- end
209
- end
210
-
211
-
212
- class EncryptedData
213
- attr_reader :key, :iv, :content
214
- def initialize(init = {})
215
- @key = init[:key]
216
- @iv = init[:iv]
217
- @content = init[:content]
218
- @sha = sha256(@content)
219
- load() if !@key || !@iv
220
- end
221
- def load (file = nil)
222
- parser = get_parser(file)
223
- sha64 = Base64.encode64(@sha) if @sha
224
- if parser.key?(sha64)
225
- #puts "found key!"
226
- meta = parser[sha64]
227
- key64, iv64 = meta.values_at("key", "iv")
228
- @key = Base64.decode64(key64) if key64
229
- @iv = Base64.decode64(iv64) if iv64
230
- else
231
- #puts "key not found! #{sha64}"
232
- end
233
- end
234
- def save (file = nil)
235
- parser = get_parser(file)
236
- sha64 = Base64.encode64(@sha) if @sha
237
- #puts "save key: #{sha64}"
238
- if parser.key?(sha64)
239
- meta = parser[sha64]
240
- else
241
- meta = {key: nil, iv: nil}
242
- parser[sha64] = meta
243
- end
244
- meta[:key] = Base64.encode64(@key) if @key
245
- meta[:iv] = Base64.encode64(@iv) if @iv
246
- set_parser(file, parser)
247
- end
248
-
249
- private
250
- def get_parser (file = nil)
251
- file = PARSER_FILE if !file
252
- # create the directory unless it exists
253
- Dir.mkdir(WORKING_DIR) unless Dir.exist?(WORKING_DIR)
254
- parser = {}
255
- if File.file?(file)
256
- fd = File.open(file,"r")
257
- parser = JSON.load(fd)
258
- fd.close
259
- end
260
- return parser
261
- end
262
- def set_parser (file = nil, parser = {})
263
- file = PARSER_FILE if !file
264
- # create the directory unless it exists
265
- Dir.mkdir(WORKING_DIR) unless Dir.exist?(WORKING_DIR)
266
- fd = File.open(file,"w")
267
- fd << parser.to_json
268
- fd.close
269
- end
270
- def sha256 (str = nil)
271
- sha = OpenSSL::Digest::SHA256.new
272
- digest = sha.digest(str) unless !str
273
- sha.reset
274
- digest
275
- end
276
- end
277
-
278
- def self.encrypt (str)
279
- cipher = OpenSSL::Cipher.new('aes-256-cbc')
280
- cipher.encrypt
281
- key = cipher.random_key
282
- iv = cipher.random_iv
283
-
284
- str_c = ""
285
- while str.length > 0
286
- str_c += cipher.update(str.slice!(0, 4096))
287
- end
288
- str_c += cipher.final
289
- EncryptedData.new({content: str_c, key: key, iv: iv})
290
- end
291
-
292
- def self.decrypt (encrypted_data)
293
- unless encrypted_data && encrypted_data.key && encrypted_data.iv
294
- return nil
295
- end
296
- cipher = OpenSSL::Cipher.new('aes-256-cbc')
297
- cipher.decrypt
298
- cipher.key = encrypted_data.key
299
- cipher.iv = encrypted_data.iv
300
- str_c = encrypted_data.content
301
- str = ""
302
- while str_c.length > 0
303
- str += cipher.update(str_c.slice!(0, 4096))
304
- #puts str[-50..-1] || str
305
- end
306
- str += cipher.final
307
- return str
308
- end
309
-
310
- end
311
- =begin
312
- class Includer
313
- include Crypto
314
- end
315
- CRYPTO = Includer.new
316
- =end
317
- end
318
- end
319
-
320
-
321
- run! if __FILE__==$0
@@ -1,7 +0,0 @@
1
- module Eco
2
- module Data
3
- module Crypto
4
- end
5
- end
6
- end
7
- require_relative 'crypto/encryption'