insights-api-common 4.0.3 → 4.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 972f294824d5a600f98ee785b45a310d83b2b056d1bc9e8fee4af2afd1d43f9c
4
- data.tar.gz: 93f294e0f183debaa844c4ff4272c4fa921a8aef51269d0caffbe8a630a84de7
3
+ metadata.gz: ce10f1b7fbf9b54ce62a4df70d74d36576b5aaf27edc46e7876ab9b8dc3b858d
4
+ data.tar.gz: 8d8396b33c3a823d38afce61af976daa07806c4c71373f03f21b738541dd611c
5
5
  SHA512:
6
- metadata.gz: 7f12eb12ddd1bd97b486d88e09463c5ac29f95350ad5431c1ff292df6eb222700628d9a8e0cc055ec7942a0e5a8814aad7249edfd4603f691d6426d85faceef1
7
- data.tar.gz: df4bbc507ad58eb38b94e8bddebd3dd3060a3f4eff33d807b85a88cfd5d9fa33ade8239db2dbae7197b56548fec1fbf456a953fa57226be2b9da1b709f04c0ca
6
+ metadata.gz: cd95076ae1ad48ccf33eb2fa9fcedc044c70c1f2ad995fbbc29d3a98cc3fd680620a1828d69a9b0dad213cc91f1c58ecc80c2a066d1018f35d24ec9719b3aad3
7
+ data.tar.gz: 196b69377f50c94460c5a2a564cf6786352e3962a5cac8d5cf6b69656415bc06420af8f78552758ddb9b3b1dbde3badbd02613e0ade3ae0e8d3264b5e52e46c6
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Insights::API::Common
2
2
 
3
3
  [![Build Status](https://travis-ci.org/RedHatInsights/insights-api-common-rails.svg)](https://travis-ci.org/RedHatInsights/insights-api-common-rails)
4
- [![Maintainability](https://api.codeclimate.com/v1/badges/790ea6c77d82da6be68a/maintainability)](https://codeclimate.com/github/RedHatInsights/insights-api-common-rails/maintainability)
5
- [![Test Coverage](https://api.codeclimate.com/v1/badges/790ea6c77d82da6be68a/test_coverage)](https://codeclimate.com/github/RedHatInsights/insights-api-common-rails/test_coverage)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/8ec8a19165383fdaed47/maintainability)](https://codeclimate.com/github/RedHatInsights/insights-api-common-rails/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/8ec8a19165383fdaed47/test_coverage)](https://codeclimate.com/github/RedHatInsights/insights-api-common-rails/test_coverage)
6
6
  [![Security](https://hakiri.io/github/RedHatInsights/insights-api-common-rails/master.svg)](https://hakiri.io/github/RedHatInsights/insights-api-common-rails/master)
7
7
 
8
8
  Header, Encryption, RBAC, Serialization, Pagination and other common behavior for Insights microservices built with Rails
@@ -1,3 +1,4 @@
1
+ require "insights/api/common/custom_exceptions"
1
2
  require "insights/api/common/engine"
2
3
  require "insights/api/common/entitlement"
3
4
  require "insights/api/common/error_document"
@@ -7,19 +7,28 @@ module Insights
7
7
 
8
8
  def self.included(other)
9
9
  other.rescue_from(StandardError, RuntimeError) do |exception|
10
- logger.error("#{exception.class.name}: #{exception.message}\n#{exception.backtrace.join("\n")}")
11
- errors = Insights::API::Common::ErrorDocument.new.tap do |error_document|
12
- exception_list_from(exception).each do |exc|
13
- if api_client_exception?(exc)
14
- api_client_errors(exc, error_document)
15
- else
16
- error_document.add(error_code_from_class(exc).to_s, "#{exc.class}: #{exc.message}")
17
- end
18
- end
10
+ rescue_from_handler(exception) do |error_document, exc|
11
+ error_document.add(error_code_from_class(exc).to_s, "#{exc.class}: #{exc.message}")
19
12
  end
13
+ end
14
+ end
20
15
 
21
- render :json => errors.to_h, :status => error_code_from_class(exception)
16
+ def rescue_from_handler(exception)
17
+ logger.error("#{exception.class.name}: #{exception.message}\n#{exception.backtrace.join("\n")}")
18
+ errors = Insights::API::Common::ErrorDocument.new.tap do |error_document|
19
+ exception_list_from(exception).each do |exc|
20
+ if api_client_exception?(exc)
21
+ api_client_errors(exc, error_document)
22
+ elsif custom_exception?(exc)
23
+ message = fetch_custom_message(exc)
24
+ error_document.add(error_code_from_class(exc).to_s, message)
25
+ else
26
+ yield error_document, exc
27
+ end
28
+ end
22
29
  end
30
+
31
+ render :json => errors.to_h, :status => error_code_from_class(exception)
23
32
  end
24
33
 
25
34
  def exception_list_from(exception)
@@ -31,6 +40,14 @@ module Insights
31
40
  end
32
41
  end
33
42
 
43
+ def custom_exception?(exception)
44
+ Insights::API::Common::CustomExceptions::CUSTOM_EXCEPTION_LIST.include?(exception.class.to_s)
45
+ end
46
+
47
+ def fetch_custom_message(exception)
48
+ Insights::API::Common::CustomExceptions.custom_message(exception)
49
+ end
50
+
34
51
  def error_code_from_class(exception)
35
52
  if ActionDispatch::ExceptionWrapper.rescue_responses.key?(exception.class.to_s)
36
53
  Rack::Utils.status_code(ActionDispatch::ExceptionWrapper.rescue_responses[exception.class.to_s])
@@ -45,7 +62,7 @@ module Insights
45
62
  end
46
63
 
47
64
  def api_client_errors(exc, error_document)
48
- body = JSON.parse(exc.response_body)
65
+ body = json_parsed_body(exc)
49
66
  if body.is_a?(Hash) && body.key?('errors') && body['errors'].is_a?(Array)
50
67
  body['errors'].each do |error|
51
68
  next unless error.key?('status') && error.key?('detail')
@@ -56,6 +73,12 @@ module Insights
56
73
  error_document.add(exc.code.to_s, exc.message )
57
74
  end
58
75
  end
76
+
77
+ def json_parsed_body(exc)
78
+ JSON.parse(exc.response_body)
79
+ rescue StandardError
80
+ nil
81
+ end
59
82
  end
60
83
  end
61
84
  end
@@ -0,0 +1,16 @@
1
+ module Insights
2
+ module API
3
+ module Common
4
+ class CustomExceptions
5
+ CUSTOM_EXCEPTION_LIST = %w[Pundit::NotAuthorizedError].freeze
6
+
7
+ def self.custom_message(exception)
8
+ case exception.class.to_s
9
+ when "Pundit::NotAuthorizedError"
10
+ "You are not authorized to #{exception.query.to_s.delete_suffix('?')} this #{exception.record.model_name.human.downcase}"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,18 +6,21 @@ module Insights
6
6
  require 'prometheus_exporter'
7
7
  require 'prometheus_exporter/client'
8
8
 
9
+ setup_custom_metrics(args[:custom_metrics])
10
+
11
+ return if metrics_port == 0
12
+
9
13
  ensure_exporter_server
10
14
  enable_in_process_metrics
11
15
  enable_web_server_metrics(prefix)
12
- setup_custom_metrics(args[:custom_metrics])
13
16
  end
14
17
 
15
18
  private_class_method def self.ensure_exporter_server
16
19
  require 'socket'
17
- TCPSocket.open("localhost", 9394) {}
20
+ TCPSocket.open("localhost", metrics_port) {}
18
21
  rescue Errno::ECONNREFUSED
19
22
  require 'prometheus_exporter/server'
20
- server = PrometheusExporter::Server::WebServer.new(port: 9394)
23
+ server = PrometheusExporter::Server::WebServer.new(port: metrics_port)
21
24
  server.start
22
25
 
23
26
  PrometheusExporter::Client.default = PrometheusExporter::LocalClient.new(collector: server.collector)
@@ -39,18 +42,26 @@ module Insights
39
42
  return if custom_metrics.nil?
40
43
 
41
44
  custom_metrics.each do |metric|
42
- instance_variable_set("@#{metric[:name]}_#{metric[:type]}", PrometheusExporter::Client.default.register(metric[:type], metric[:name], metric[:description]))
43
-
44
- define_singleton_method(metric[:name]) do
45
- case metric[:type]
46
- when :counter
47
- instance_variable_get("@#{metric[:name]}_#{metric[:type]}")&.observe(1)
48
- else
49
- "Metric of type #{metric[:type]} unsupported, implement it in Insights::API::Common::Metrics#L45"
45
+ if metrics_port == 0
46
+ define_singleton_method(metric[:name]) {}
47
+ else
48
+ instance_variable_set("@#{metric[:name]}_#{metric[:type]}", PrometheusExporter::Client.default.register(metric[:type], metric[:name], metric[:description]))
49
+
50
+ define_singleton_method(metric[:name]) do
51
+ case metric[:type]
52
+ when :counter
53
+ instance_variable_get("@#{metric[:name]}_#{metric[:type]}")&.observe(1)
54
+ else
55
+ "Metric of type #{metric[:type]} unsupported, implement it in Insights::API::Common::Metrics#L45"
56
+ end
50
57
  end
51
58
  end
52
59
  end
53
60
  end
61
+
62
+ private_class_method def self.metrics_port
63
+ @metrics_port ||= (ENV['METRICS_PORT']&.to_i || 9394)
64
+ end
54
65
  end
55
66
  end
56
67
  end
@@ -1,2 +1,3 @@
1
1
  require "insights/api/common/open_api/docs"
2
+ require "insights/api/common/open_api/version_from_prefix"
2
3
  require "insights/api/common/open_api/serializer"
@@ -441,7 +441,7 @@ module Insights
441
441
  end
442
442
 
443
443
  # Take existing attrs, that we won't generate
444
- ['example', 'format', 'readOnly', 'title', 'description'].each do |property_key|
444
+ ['example', 'format', 'nullable', 'readOnly', 'title', 'description'].each do |property_key|
445
445
  property_value = openapi_contents.dig(*path_parts(SCHEMAS_PATH), klass_name, "properties", key, property_key)
446
446
  properties_value[property_key] = property_value if property_value
447
447
  end
@@ -3,27 +3,40 @@ module Insights
3
3
  module Common
4
4
  module OpenApi
5
5
  module Serializer
6
+ include VersionFromPrefix
7
+
6
8
  def as_json(arg = {})
7
- previous = super
9
+ previous = super(:except => _excluded_attributes(arg))
10
+
8
11
  encrypted_columns_set = (self.class.try(:encrypted_columns) || []).to_set
9
12
  encryption_filtered = previous.except(*encrypted_columns_set)
10
13
  return encryption_filtered unless arg.key?(:prefixes)
11
- version = api_version_from_prefix(arg[:prefixes].first)
12
- presentation_name = self.class.try(:presentation_name) || self.class.name
13
- schema = ::Insights::API::Common::OpenApi::Docs.instance[version].definitions[presentation_name]
14
- attrs = encryption_filtered.slice(*schema["properties"].keys)
15
- schema["properties"].keys.each do |name|
14
+
15
+ attrs = encryption_filtered.slice(*_schema_properties(arg).keys)
16
+ _schema_properties(arg).keys.each do |name|
16
17
  next if attrs[name].nil?
17
18
  attrs[name] = attrs[name].iso8601 if attrs[name].kind_of?(Time)
18
19
  attrs[name] = attrs[name].to_s if name.ends_with?("_id") || name == "id"
19
- attrs[name] = self.public_send(name) if !attrs.key?(name) && !encrypted_columns_set.include?(name)
20
20
  end
21
21
  attrs.compact
22
22
  end
23
23
 
24
- def api_version_from_prefix(prefix)
25
- /\/?\w+\/v(?<major>\d+)[x\.]?(?<minor>\d+)?\// =~ prefix
26
- [major, minor].compact.join(".")
24
+ private
25
+
26
+ def _excluded_attributes(arg)
27
+ return [] unless arg.key?(:prefixes)
28
+
29
+ self.attributes.keys - _schema_properties(arg).keys
30
+ end
31
+
32
+ def _schema_properties(arg)
33
+ @schema_properties ||= _schema(arg)["properties"]
34
+ end
35
+
36
+ def _schema(arg)
37
+ version = api_version_from_prefix(arg[:prefixes].first)
38
+ presentation_name = self.class.try(:presentation_name) || self.class.name
39
+ ::Insights::API::Common::OpenApi::Docs.instance[version].definitions[presentation_name]
27
40
  end
28
41
  end
29
42
  end
@@ -0,0 +1,14 @@
1
+ module Insights
2
+ module API
3
+ module Common
4
+ module OpenApi
5
+ module VersionFromPrefix
6
+ def api_version_from_prefix(prefix)
7
+ /\/?\w+\/v(?<major>\d+)[x\.]?(?<minor>\d+)?\// =~ prefix
8
+ [major, minor].compact.join(".")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -8,7 +8,7 @@ module Insights
8
8
  @route_mapper = route_mapper
9
9
  end
10
10
 
11
- def redirect_major_version(version, prefix, via: [:delete, :get, :options, :patch, :post])
11
+ def redirect_major_version(version, prefix, via: [:delete, :get, :options])
12
12
  route_mapper.match(
13
13
  "/#{version.split('.').first}/*path(.:format)",
14
14
  :format => false,
@@ -1,7 +1,7 @@
1
1
  module Insights
2
2
  module API
3
3
  module Common
4
- VERSION = "4.0.3".freeze
4
+ VERSION = "4.1.4".freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: insights-api-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 4.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Insights Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-13 00:00:00.000000000 Z
11
+ date: 2020-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_tenant
@@ -58,20 +58,20 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '5.2'
61
+ version: 5.2.2
62
62
  - - ">="
63
63
  - !ruby/object:Gem::Version
64
- version: 5.2.1.1
64
+ version: 5.2.2.1
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
- version: '5.2'
71
+ version: 5.2.2
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: 5.2.1.1
74
+ version: 5.2.2.1
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: manageiq-loggers
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '0.2'
95
+ version: 0.2.1
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0.2'
102
+ version: 0.2.1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: prometheus_exporter
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -236,16 +236,16 @@ dependencies:
236
236
  name: rake
237
237
  requirement: !ruby/object:Gem::Requirement
238
238
  requirements:
239
- - - "~>"
239
+ - - ">="
240
240
  - !ruby/object:Gem::Version
241
- version: '10.0'
241
+ version: 12.3.3
242
242
  type: :development
243
243
  prerelease: false
244
244
  version_requirements: !ruby/object:Gem::Requirement
245
245
  requirements:
246
- - - "~>"
246
+ - - ">="
247
247
  - !ruby/object:Gem::Version
248
- version: '10.0'
248
+ version: 12.3.3
249
249
  - !ruby/object:Gem::Dependency
250
250
  name: rspec
251
251
  requirement: !ruby/object:Gem::Requirement
@@ -292,16 +292,16 @@ dependencies:
292
292
  name: simplecov
293
293
  requirement: !ruby/object:Gem::Requirement
294
294
  requirements:
295
- - - ">="
295
+ - - "~>"
296
296
  - !ruby/object:Gem::Version
297
- version: '0'
297
+ version: 0.17.1
298
298
  type: :development
299
299
  prerelease: false
300
300
  version_requirements: !ruby/object:Gem::Requirement
301
301
  requirements:
302
- - - ">="
302
+ - - "~>"
303
303
  - !ruby/object:Gem::Version
304
- version: '0'
304
+ version: 0.17.1
305
305
  - !ruby/object:Gem::Dependency
306
306
  name: webmock
307
307
  requirement: !ruby/object:Gem::Requirement
@@ -345,6 +345,7 @@ files:
345
345
  - lib/insights/api/common/application_controller_mixins/request_body_validation.rb
346
346
  - lib/insights/api/common/application_controller_mixins/request_parameter_validation.rb
347
347
  - lib/insights/api/common/application_controller_mixins/request_path.rb
348
+ - lib/insights/api/common/custom_exceptions.rb
348
349
  - lib/insights/api/common/engine.rb
349
350
  - lib/insights/api/common/entitlement.rb
350
351
  - lib/insights/api/common/error_document.rb
@@ -371,6 +372,7 @@ files:
371
372
  - lib/insights/api/common/open_api/docs/object_definition.rb
372
373
  - lib/insights/api/common/open_api/generator.rb
373
374
  - lib/insights/api/common/open_api/serializer.rb
375
+ - lib/insights/api/common/open_api/version_from_prefix.rb
374
376
  - lib/insights/api/common/option_redirect_enhancements.rb
375
377
  - lib/insights/api/common/paginated_response.rb
376
378
  - lib/insights/api/common/paginated_response_v2.rb