digital_femsa 1.1.0 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95505b447016a0b25cb0fd3ffcc692f5dd7218e88166d818d68ef521d3cf0b6e
4
- data.tar.gz: 63803ed21b19398750bd0f281f77c1688b4ea9077b5e7d8115e83f9f238919cb
3
+ metadata.gz: 0f0452baa0bfee1932378770877461e46eb16cfc255de3af8dc1b39927a42c1b
4
+ data.tar.gz: c83fdf5e1968a1258436da39e15673ae498d0ac04b3b7168fff97288f3ec2541
5
5
  SHA512:
6
- metadata.gz: fd7e0e06fb721dd63255e72ceec83fb8c4c7fb6187ff07512c2a5a82dd1c58c1af24bab8a272c1608f233cf8d6df115d43e21807db3fe2ba3fa2f6dc0a41c561
7
- data.tar.gz: f219280b929af93bfac269dd3f368a7a1123427d1e4da32ab2c299d6982201c6ade80f38c59b2622898ee138086e31f5c536170ff6e123d70b86080425be6597
6
+ metadata.gz: d719bf015ab2a8f6bbd20e3c9ac13e9c2c67ff815090c035f48a5d75e176c4b460c06224b37a3cbc2dfe1b998195040449531078b949590f8a82a2bd0157d42b
7
+ data.tar.gz: 75861af98201f94c25573cc4530dba0d28da4dd152d4276d2ed8c54078685b5ee52bd4c06e4f87e4c9ea126f041a4c74a93902b4d5ccf88b1ae807d595e5cad7
data/Gemfile CHANGED
@@ -6,4 +6,6 @@ group :development, :test do
6
6
  gem 'rake', '~> 13.0.1'
7
7
  gem 'pry-byebug'
8
8
  gem 'rubocop', '~> 0.66.0'
9
+ gem 'simplecov', '~> 0.22.0'
10
+ gem 'simplecov-json', '~> 0.2'
9
11
  end
data/Gemfile.lock ADDED
@@ -0,0 +1,104 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ digital_femsa (1.1.1)
5
+ faraday (= 2.14.2)
6
+ faraday-multipart
7
+ marcel
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.3)
13
+ byebug (13.0.0)
14
+ reline (>= 0.6.0)
15
+ coderay (1.1.3)
16
+ date (3.5.1)
17
+ diff-lcs (1.6.2)
18
+ docile (1.4.1)
19
+ faraday (2.14.2)
20
+ faraday-net_http (>= 2.0, < 3.5)
21
+ json
22
+ logger
23
+ faraday-multipart (1.2.0)
24
+ multipart-post (~> 2.0)
25
+ faraday-net_http (3.4.3)
26
+ net-http (~> 0.5)
27
+ io-console (0.8.2)
28
+ jaro_winkler (1.5.6)
29
+ json (2.19.7)
30
+ logger (1.7.0)
31
+ marcel (1.2.1)
32
+ method_source (1.1.0)
33
+ multipart-post (2.4.1)
34
+ net-http (0.9.1)
35
+ uri (>= 0.11.1)
36
+ parallel (1.28.0)
37
+ parser (3.3.11.1)
38
+ ast (~> 2.4.1)
39
+ racc
40
+ pry (0.16.0)
41
+ coderay (~> 1.1)
42
+ method_source (~> 1.0)
43
+ reline (>= 0.6.0)
44
+ pry-byebug (3.12.0)
45
+ byebug (~> 13.0)
46
+ pry (>= 0.13, < 0.17)
47
+ psych (5.3.1)
48
+ date
49
+ stringio
50
+ racc (1.8.1)
51
+ rainbow (3.1.1)
52
+ rake (13.0.6)
53
+ reline (0.6.3)
54
+ io-console (~> 0.5)
55
+ rspec (3.13.2)
56
+ rspec-core (~> 3.13.0)
57
+ rspec-expectations (~> 3.13.0)
58
+ rspec-mocks (~> 3.13.0)
59
+ rspec-core (3.13.6)
60
+ rspec-support (~> 3.13.0)
61
+ rspec-expectations (3.13.5)
62
+ diff-lcs (>= 1.2.0, < 2.0)
63
+ rspec-support (~> 3.13.0)
64
+ rspec-mocks (3.13.8)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.13.0)
67
+ rspec-support (3.13.7)
68
+ rubocop (0.66.0)
69
+ jaro_winkler (~> 1.5.1)
70
+ parallel (~> 1.10)
71
+ parser (>= 2.5, != 2.5.1.1)
72
+ psych (>= 3.1.0)
73
+ rainbow (>= 2.2.2, < 4.0)
74
+ ruby-progressbar (~> 1.7)
75
+ unicode-display_width (>= 1.4.0, < 1.6)
76
+ ruby-progressbar (1.13.0)
77
+ simplecov (0.22.0)
78
+ docile (~> 1.1)
79
+ simplecov-html (~> 0.11)
80
+ simplecov_json_formatter (~> 0.1)
81
+ simplecov-html (0.13.2)
82
+ simplecov-json (0.2.3)
83
+ json
84
+ simplecov
85
+ simplecov_json_formatter (0.1.4)
86
+ stringio (3.2.0)
87
+ unicode-display_width (1.5.0)
88
+ uri (1.1.1)
89
+
90
+ PLATFORMS
91
+ arm64-darwin-25
92
+ ruby
93
+
94
+ DEPENDENCIES
95
+ digital_femsa!
96
+ pry-byebug
97
+ rake (~> 13.0.1)
98
+ rspec (~> 3.6, >= 3.6.0)
99
+ rubocop (~> 0.66.0)
100
+ simplecov (~> 0.22.0)
101
+ simplecov-json (~> 0.2)
102
+
103
+ BUNDLED WITH
104
+ 2.5.9
data/README.md CHANGED
@@ -7,7 +7,7 @@ Femsa sdk
7
7
  This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
8
8
 
9
9
  - API version: 2.1.0
10
- - Package version: 1.1.0
10
+ - Package version: 1.1.1
11
11
  - Build date: 2026-03-26T20:52:06.650476795Z[Etc/UTC]
12
12
  - Generator version: 7.5.0
13
13
  - Build package: org.openapitools.codegen.languages.RubyClientCodegen
@@ -26,16 +26,16 @@ gem build digital_femsa.gemspec
26
26
  Then either install the gem locally:
27
27
 
28
28
  ```shell
29
- gem install ./digital_femsa-1.1.0.gem
29
+ gem install ./digital_femsa-1.1.1.gem
30
30
  ```
31
31
 
32
- (for development, run `gem install --dev ./digital_femsa-1.1.0.gem` to install the development dependencies)
32
+ (for development, run `gem install --dev ./digital_femsa-1.1.1.gem` to install the development dependencies)
33
33
 
34
34
  or publish the gem to a gem hosting service, e.g. [RubyGems](https://rubygems.org/).
35
35
 
36
36
  Finally add this to the Gemfile:
37
37
 
38
- gem 'digital_femsa', '~> 1.1.0'
38
+ gem 'digital_femsa', '~> 1.1.1'
39
39
 
40
40
  ### Install from Git
41
41
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.1.1
data/config-ruby.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "gemAuthor": "DigitalFemsa",
4
4
  "gemName" : "digital_femsa",
5
5
  "gemLicense": "MIT",
6
- "gemVersion": "1.1.0",
6
+ "gemVersion": "1.1.1",
7
7
  "hideGenerationTimestamp": false,
8
8
  "moduleName": "DigitalFemsa",
9
9
  "gemSummary" : "This library provides https://api.digitalfemsa.io operations",
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.required_ruby_version = ">= 2.6"
29
29
  s.metadata = {}
30
30
 
31
- s.add_runtime_dependency 'faraday', '>= 1.0.1', '< 3.0'
31
+ s.add_runtime_dependency 'faraday', '= 2.14.2'
32
32
  s.add_runtime_dependency 'faraday-multipart'
33
33
  s.add_runtime_dependency 'marcel'
34
34
 
@@ -12,6 +12,7 @@ Generator version: 7.5.0
12
12
 
13
13
  require 'date'
14
14
  require 'time'
15
+ require 'uri'
15
16
 
16
17
  module DigitalFemsa
17
18
  # Parameters used to create or update a webhook.
@@ -86,9 +87,10 @@ module DigitalFemsa
86
87
  invalid_properties.push('invalid value for "url", url cannot be nil.')
87
88
  end
88
89
 
89
- pattern = Regexp.new(/^(?!.*(localhost|127\.0\.0\.1)).*$/)
90
- if @url !~ pattern
91
- invalid_properties.push("invalid value for \"url\", must conform to the pattern #{pattern}.")
90
+ begin
91
+ validate_url_safety(@url) if @url
92
+ rescue ArgumentError => e
93
+ invalid_properties.push(e.message)
92
94
  end
93
95
 
94
96
  if @synchronous.nil?
@@ -103,7 +105,11 @@ module DigitalFemsa
103
105
  def valid?
104
106
  warn '[DEPRECATED] the `valid?` method is obsolete'
105
107
  return false if @url.nil?
106
- return false if @url !~ Regexp.new(/^(?!.*(localhost|127\.0\.0\.1)).*$/)
108
+ begin
109
+ validate_url_safety(@url)
110
+ rescue ArgumentError
111
+ return false
112
+ end
107
113
  return false if @synchronous.nil?
108
114
  true
109
115
  end
@@ -115,12 +121,245 @@ module DigitalFemsa
115
121
  fail ArgumentError, 'url cannot be nil'
116
122
  end
117
123
 
118
- pattern = Regexp.new(/^(?!.*(localhost|127\.0\.0\.1)).*$/)
119
- if url !~ pattern
120
- fail ArgumentError, "invalid value for \"url\", must conform to the pattern #{pattern}."
124
+ validate_url_safety(url)
125
+ @url = url
126
+ end
127
+
128
+ private
129
+
130
+ # Comprehensive URL validation to prevent SSRF attacks
131
+ # @param [String] url URL to validate
132
+ def validate_url_safety(url)
133
+ # Parse the URL to extract hostname
134
+ begin
135
+ uri = URI.parse(url)
136
+ hostname = uri.hostname
137
+ port = uri.port
138
+
139
+ # Ensure URL has a valid scheme (http/https)
140
+ unless uri.scheme =~ /\A(https?)\z/
141
+ fail ArgumentError, "invalid value for \"url\", must use http or https scheme"
142
+ end
143
+
144
+ # Block if hostname is nil or empty
145
+ if hostname.nil? || hostname.empty?
146
+ fail ArgumentError, "invalid value for \"url\", hostname cannot be empty"
147
+ end
148
+
149
+ # Block localhost variations and private IP ranges
150
+ if hostname_matches_restricted_patterns?(hostname)
151
+ fail ArgumentError, "invalid value for \"url\", hostname points to restricted network resource"
152
+ end
153
+
154
+ # Block ports commonly used for internal services
155
+ if port_matches_restricted_ports?(port)
156
+ fail ArgumentError, "invalid value for \"url\", port is not allowed"
157
+ end
158
+
159
+ rescue URI::InvalidURIError
160
+ fail ArgumentError, "invalid value for \"url\", must be a valid URL"
121
161
  end
162
+ end
122
163
 
123
- @url = url
164
+ # Check if hostname matches restricted patterns
165
+ # @param [String] hostname Hostname to check
166
+ # @return [Boolean] true if hostname is restricted
167
+ def hostname_matches_restricted_patterns?(hostname)
168
+ # Convert to lowercase for case-insensitive comparison
169
+ hostname = hostname.downcase
170
+
171
+ # Block localhost variations
172
+ localhost_patterns = [
173
+ 'localhost',
174
+ '127.0.0.1',
175
+ '127.0.0.0',
176
+ '0.0.0.0',
177
+ '::1',
178
+ '0:0:0:0:0:0:0:1',
179
+ 'ip6-localhost',
180
+ 'ip6-loopback'
181
+ ]
182
+
183
+ # Block private IP ranges
184
+ private_ip_patterns = [
185
+ /^127\.\d+\.\d+\.\d+/, # 127.0.0.0/8 (loopback)
186
+ /^10\.\d+\.\d+\.\d+/, # 10.0.0.0/8
187
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\.\d+\.\d+/, # 172.16.0.0/12
188
+ /^192\.168\.\d+\.\d+/, # 192.168.0.0/16
189
+ /^169\.254\.\d+\.\d+/, # 169.254.0.0/16 (link-local)
190
+ /^224\.\d+\.\d+\.\d+/, # 224.0.0.0/4 (multicast)
191
+ /^fc00:/, # fc00::/7 (IPv6 unique local)
192
+ /^fe80:/, # fe80::/10 (IPv6 link-local)
193
+ /^ff00:/ # ff00::/8 (IPv6 multicast)
194
+ ]
195
+
196
+ # Block internal hostnames and services
197
+ internal_hostnames = [
198
+ 'internal',
199
+ 'intranet',
200
+ 'corp',
201
+ 'private',
202
+ 'admin',
203
+ 'management',
204
+ 'api-gateway',
205
+ 'database',
206
+ 'cache',
207
+ 'redis',
208
+ 'mongo',
209
+ 'mysql',
210
+ 'postgres',
211
+ 'elasticsearch',
212
+ 'kibana',
213
+ 'grafana',
214
+ 'prometheus',
215
+ 'consul',
216
+ 'vault',
217
+ 'etcd',
218
+ 'zookeeper',
219
+ 'kafka',
220
+ 'rabbitmq'
221
+ ]
222
+
223
+ # Check localhost patterns
224
+ return true if localhost_patterns.include?(hostname)
225
+
226
+ # Check private IP ranges
227
+ private_ip_patterns.each do |pattern|
228
+ return true if hostname.match?(pattern)
229
+ end
230
+
231
+ # Check internal hostnames (including subdomains)
232
+ internal_hostnames.each do |internal_name|
233
+ return true if hostname.include?(internal_name)
234
+ end
235
+
236
+ # Check for common DNS rebinding services
237
+ dns_rebinding_domains = [
238
+ 'xip.io',
239
+ 'nip.io',
240
+ 'sslip.io',
241
+ 'localtest.me',
242
+ 'vcap.me',
243
+ 'localho.st',
244
+ '127-0-0-1.org.uk'
245
+ ]
246
+
247
+ dns_rebinding_domains.each do |domain|
248
+ return true if hostname.end_with?(domain)
249
+ end
250
+
251
+ # Check if hostname resolves to private IP (basic check)
252
+ # Note: In production, you might want to add actual DNS resolution here
253
+ if hostname_resolves_to_private_ip?(hostname)
254
+ return true
255
+ end
256
+
257
+ false
258
+ end
259
+
260
+ # Check if port matches restricted ports
261
+ # @param [Integer] port Port to check
262
+ # @return [Boolean] true if port is restricted
263
+ def port_matches_restricted_ports?(port)
264
+ return false if port.nil? # Allow default ports
265
+
266
+ # Block ports commonly used for internal services
267
+ restricted_ports = [
268
+ 22, # SSH
269
+ 23, # Telnet
270
+ 25, # SMTP
271
+ 53, # DNS
272
+ 135, # Windows RPC
273
+ 139, # NetBIOS
274
+ 445, # SMB
275
+ 1433, # SQL Server
276
+ 1521, # Oracle
277
+ 2049, # NFS
278
+ 2181, # Zookeeper
279
+ 3306, # MySQL
280
+ 3389, # RDP
281
+ 5432, # PostgreSQL
282
+ 5672, # RabbitMQ
283
+ 5984, # CouchDB
284
+ 6379, # Redis
285
+ 6380, # Redis SSL
286
+ 8080, # Common internal web services
287
+ 8081, # Alternative web services
288
+ 8443, # Alternative HTTPS
289
+ 9000, # Common internal services
290
+ 9042, # Cassandra
291
+ 9092, # Kafka
292
+ 9200, # Elasticsearch
293
+ 9300, # Elasticsearch transport
294
+ 11211, # Memcached
295
+ 27017, # MongoDB
296
+ 27018, # MongoDB shard
297
+ 27019, # MongoDB config
298
+ 5000, # Common internal services
299
+ 5001, # Alternative services
300
+ 6000, # Common internal services
301
+ 7000, # Common internal services
302
+ 7001, # WebLogic
303
+ 8000, # Common internal services
304
+ 8001, # Alternative services
305
+ 8009, # AJP
306
+ 8443, # Tomcat SSL
307
+ 8888, # Common internal services
308
+ 9001, # Common internal services
309
+ 9090, # Common internal services
310
+ 9091, # Common internal services
311
+ 9093, # Common internal services
312
+ 9999, # Common internal services
313
+ 10000, # Common internal services
314
+ 10001, # Common internal services
315
+ 10002, # Common internal services
316
+ 10003, # Common internal services
317
+ 10004, # Common internal services
318
+ 10005, # Common internal services
319
+ 10006, # Common internal services
320
+ 10007, # Common internal services
321
+ 10008, # Common internal services
322
+ 10009, # Common internal services
323
+ 10010 # Common internal services
324
+ ]
325
+
326
+ restricted_ports.include?(port)
327
+ end
328
+
329
+ # Basic check if hostname might resolve to private IP
330
+ # @param [String] hostname Hostname to check
331
+ # @return [Boolean] true if hostname might resolve to private IP
332
+ def hostname_resolves_to_private_ip?(hostname)
333
+ # This is a basic heuristic. In production, you might want to
334
+ # actually resolve the hostname and check the IP addresses.
335
+
336
+ # Check for common patterns that might resolve to internal IPs
337
+ suspicious_patterns = [
338
+ /^internal-/,
339
+ /^private-/,
340
+ /^intranet-/,
341
+ /^corp-/,
342
+ /^dev-/,
343
+ /^test-/,
344
+ /^staging-/,
345
+ /^admin-/,
346
+ /^db-/,
347
+ /^cache-/,
348
+ /^api-/,
349
+ /^service-/,
350
+ /^worker-/,
351
+ /^node-/,
352
+ /^server-/,
353
+ /^host-/,
354
+ /^vm-/,
355
+ /^container-/
356
+ ]
357
+
358
+ suspicious_patterns.each do |pattern|
359
+ return true if hostname.match?(pattern)
360
+ end
361
+
362
+ false
124
363
  end
125
364
 
126
365
  # Checks equality by comparing each attribute.
@@ -11,5 +11,5 @@ Generator version: 7.5.0
11
11
  =end
12
12
 
13
13
  module DigitalFemsa
14
- VERSION = '1.1.0'
14
+ VERSION = '1.1.1'
15
15
  end
@@ -13,35 +13,37 @@ Generator version: 7.5.0
13
13
  require 'spec_helper'
14
14
  require 'json'
15
15
 
16
- # Unit tests for DigitalFemsa::BalancesApi
17
- # Automatically generated by openapi-generator (https://openapi-generator.tech)
18
- # Please update as you see appropriate
19
- describe 'BalancesApi' do
20
- before do
21
- # run before each test
22
- @api_instance = DigitalFemsa::BalancesApi.new
23
- end
16
+ RSpec.describe DigitalFemsa::BalancesApi do
17
+ let(:config) { DigitalFemsa::Configuration.new }
18
+ let(:api_client) { instance_double(DigitalFemsa::ApiClient) }
19
+ let(:api_instance) { described_class.new(api_client) }
24
20
 
25
- after do
26
- # run after each test
21
+ before do
22
+ allow(api_client).to receive(:config).and_return(config)
23
+ allow(api_client).to receive(:select_header_accept).and_return('application/vnd.app-v2.1.0+json')
27
24
  end
28
25
 
29
26
  describe 'test an instance of BalancesApi' do
30
- it 'should create an instance of BalancesApi' do
31
- expect(@api_instance).to be_instance_of(DigitalFemsa::BalancesApi)
27
+ it 'creates an instance of BalancesApi' do
28
+ expect(api_instance).to be_instance_of(DigitalFemsa::BalancesApi)
32
29
  end
33
30
  end
34
31
 
35
- # unit tests for get_balance
36
- # Get a company&#39;s balance
37
- # Get a company&#39;s balance
38
- # @param [Hash] opts the optional parameters
39
- # @option opts [String] :accept_language Use for knowing which language to use
40
- # @return [BalanceResponse]
41
- describe 'get_balance test' do
42
- it 'should work' do
43
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
32
+ describe '#get_balance_with_http_info' do
33
+ it 'raises for invalid accept_language' do
34
+ expect do
35
+ api_instance.get_balance_with_http_info(accept_language: 'fr')
36
+ end.to raise_error(ArgumentError, /invalid value for "accept_language"/)
44
37
  end
45
- end
46
38
 
39
+ it 'sends GET request to balance endpoint' do
40
+ expect(api_client).to receive(:call_api).with(:GET, '/balance', hash_including(
41
+ operation: :'BalancesApi.get_balance',
42
+ return_type: 'BalanceResponse'
43
+ )).and_return([:balance, 200, {}])
44
+
45
+ data = api_instance.get_balance(accept_language: 'es')
46
+ expect(data).to eq(:balance)
47
+ end
48
+ end
47
49
  end