finapps_core 5.0.7 → 5.0.13

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/release-drafter.yml +49 -0
  3. data/.github/workflows/main.yaml +37 -0
  4. data/.github/workflows/release-drafter.yml +15 -0
  5. data/.github/workflows/release.yml +54 -0
  6. data/.github/workflows/verify-pr-labeled.yml +14 -0
  7. data/.rubocop.yml +123 -73
  8. data/.ruby-version +1 -1
  9. data/.tmuxinator.yml +20 -0
  10. data/.travis.yml +5 -6
  11. data/finapps_core.gemspec +11 -11
  12. data/lib/finapps_core.rb +1 -0
  13. data/lib/finapps_core/middleware/middleware.rb +6 -3
  14. data/lib/finapps_core/middleware/request/accept_json.rb +2 -1
  15. data/lib/finapps_core/middleware/request/x_tenant_id.rb +20 -0
  16. data/lib/finapps_core/middleware/response/raise_error.rb +36 -7
  17. data/lib/finapps_core/rest/base_client.rb +20 -32
  18. data/lib/finapps_core/rest/configuration.rb +18 -5
  19. data/lib/finapps_core/rest/connection.rb +32 -22
  20. data/lib/finapps_core/rest/defaults.rb +1 -1
  21. data/lib/finapps_core/utils/loggeable.rb +1 -1
  22. data/lib/finapps_core/utils/validatable.rb +1 -1
  23. data/lib/finapps_core/version.rb +1 -1
  24. data/spec/core_extensions/object/is_integer_spec.rb +6 -7
  25. data/spec/middleware/request/accept_json_spec.rb +7 -3
  26. data/spec/middleware/request/no_encoding_basic_authentication_spec.rb +15 -6
  27. data/spec/middleware/request/request_id_spec.rb +4 -4
  28. data/spec/middleware/request/tenant_authentication_spec.rb +21 -14
  29. data/spec/middleware/request/user_agent_spec.rb +8 -3
  30. data/spec/middleware/request/x_consumer_id_spec.rb +4 -4
  31. data/spec/middleware/request/x_tenant_id_spec.rb +16 -0
  32. data/spec/middleware/response/raise_error_spec.rb +47 -15
  33. data/spec/rest/base_client_spec.rb +87 -43
  34. data/spec/rest/configuration_spec.rb +25 -18
  35. data/spec/rest/credentials_spec.rb +4 -4
  36. data/spec/rest/defaults_spec.rb +1 -1
  37. data/spec/rest/resources_spec.rb +10 -20
  38. data/spec/spec_helper.rb +3 -3
  39. data/spec/support/fake_api.rb +1 -1
  40. data/spec/utils/validatable_spec.rb +9 -8
  41. metadata +78 -69
@@ -1,6 +1,6 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
- lib = File.expand_path('../lib', __FILE__)
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'finapps_core/version'
6
6
  Gem::Specification.new do |spec|
@@ -20,17 +20,17 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = Dir['spec/**/*.rb']
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_runtime_dependency 'faraday', '~> 0.15', '>= 0.15.3'
24
- spec.add_runtime_dependency 'faraday_middleware', '~> 0.12', '>= 0.12.2'
23
+ spec.add_runtime_dependency 'faraday', '~> 1.0', '>= 1.0.1'
24
+ spec.add_runtime_dependency 'faraday_middleware', '~> 1.0', '>= 1.0'
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 2.0', '>= 2.0.2'
26
+ spec.add_development_dependency 'bundler', '~> 2.0', '>= 2.0.2'
27
27
  spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0', '>= 1.0.9'
28
- spec.add_development_dependency 'gem-release', '~> 2.0', '>= 2.0.3'
29
- spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.2'
30
- spec.add_development_dependency 'rspec', '~> 3.8', '>= 3.8.0'
31
- spec.add_development_dependency 'rubocop', '~> 0.75', '>= 0.75.0'
32
- spec.add_development_dependency 'rubocop-performance', '~> 1.5', '>= 1.5.0'
33
- spec.add_development_dependency 'rubocop-rspec', '~> 1.36', '>= 1.36.0'
28
+ spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
29
+ spec.add_development_dependency 'rspec', '~> 3.10', '>= 3.10.0'
30
+ spec.add_development_dependency 'rubocop', '~> 1.8', '>= 1.8.1'
31
+ spec.add_development_dependency 'rubocop-performance', '~> 1.9', '>= 1.9.2'
32
+ spec.add_development_dependency 'rubocop-rake', '~> 0.5', '>= 0.5.1'
33
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.1', '>= 2.1.0'
34
34
  spec.add_development_dependency 'sinatra', '~> 2.0', '>= 2.0.5'
35
35
  spec.add_development_dependency 'webmock', '~> 3.6', '>= 3.6.0'
36
36
 
@@ -18,6 +18,7 @@ require 'finapps_core/middleware/request/accept_json'
18
18
  require 'finapps_core/middleware/request/user_agent'
19
19
  require 'finapps_core/middleware/request/request_id'
20
20
  require 'finapps_core/middleware/request/x_consumer_id'
21
+ require 'finapps_core/middleware/request/x_tenant_id'
21
22
  require 'finapps_core/middleware/response/raise_error'
22
23
  require 'finapps_core/middleware/middleware'
23
24
 
@@ -6,8 +6,10 @@ module FinAppsCore
6
6
  module Middleware
7
7
  autoload :AcceptJson, 'finapps_core/middleware/request/accept_json'
8
8
  autoload :UserAgent, 'finapps_core/middleware/request/user_agent'
9
- autoload :NoEncodingBasicAuthentication, 'finapps_core/middleware/request/no_encoding_basic_authentication'
10
- autoload :TenantAuthentication, 'finapps_core/middleware/request/tenant_authentication'
9
+ autoload :NoEncodingBasicAuthentication,
10
+ 'finapps_core/middleware/request/no_encoding_basic_authentication'
11
+ autoload :TenantAuthentication,
12
+ 'finapps_core/middleware/request/tenant_authentication'
11
13
  autoload :RequestId, 'finapps_core/middleware/request/request_id'
12
14
  autoload :XConsumerId, 'finapps_core/middleware/request/x_consumer_id'
13
15
 
@@ -18,7 +20,8 @@ module FinAppsCore
18
20
  no_encoding_basic_authentication: -> { NoEncodingBasicAuthentication },
19
21
  tenant_authentication: -> { TenantAuthentication },
20
22
  request_id: -> { RequestId },
21
- x_consumer_id: -> { XConsumerId }
23
+ x_consumer_id: -> { XConsumerId },
24
+ x_tenant_id: -> { XTenantId }
22
25
  end
23
26
  end
24
27
  end
@@ -2,7 +2,8 @@
2
2
 
3
3
  module FinAppsCore
4
4
  module Middleware
5
- # This middleware sets the Accept request-header field to specify JSON as acceptable media type for the response.
5
+ # This middleware sets the Accept request-header field to specify JSON
6
+ # as acceptable media type for the response.
6
7
  class AcceptJson < Faraday::Middleware
7
8
  KEY = 'Accept' unless defined? KEY
8
9
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FinAppsCore
4
+ module Middleware
5
+ # Adds a header to specify tenant to retrieve data for
6
+ class XTenantId < Faraday::Middleware
7
+ KEY = 'X-Tenant-ID' unless defined? KEY
8
+
9
+ def initialize(app, x_tenant_id)
10
+ super(app)
11
+ @x_tenant_id = x_tenant_id.to_s.strip
12
+ end
13
+
14
+ def call(env)
15
+ env[:request_headers][KEY] ||= @x_tenant_id
16
+ @app.call(env)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -16,12 +16,7 @@ module FinAppsCore
16
16
  def on_complete(env)
17
17
  return if SUCCESS_STATUSES.include?(env[:status])
18
18
 
19
- raise(FinAppsCore::ApiUnauthenticatedError, 'API Invalid Session') if env[:status] == API_UNAUTHENTICATED
20
- raise(FinAppsCore::ApiSessionTimeoutError, 'API Session Timed out') if env[:status] == API_SESSION_TIMEOUT
21
- raise(FinAppsCore::ConnectionFailedError, 'Connection Failed') if env[:status] == CONNECTION_FAILED_STATUS
22
- raise(FinAppsCore::UserLockoutError, 'User is Locked') if user_is_locked?(env)
23
-
24
- raise(Faraday::ClientError, response_values(env))
19
+ failures env
25
20
  end
26
21
 
27
22
  def response_values(env)
@@ -35,6 +30,39 @@ module FinAppsCore
35
30
 
36
31
  private
37
32
 
33
+ def failures(env)
34
+ api_authentication_fail env
35
+ api_session_timeout_fail env
36
+ locked_user_fail env
37
+ connection_fail env
38
+
39
+ fail(Faraday::ClientError, response_values(env))
40
+ end
41
+
42
+ def locked_user_fail(env)
43
+ return unless user_is_locked?(env)
44
+
45
+ fail(FinAppsCore::UserLockoutError, 'User is Locked')
46
+ end
47
+
48
+ def api_session_timeout_fail(env)
49
+ return unless env[:status] == API_SESSION_TIMEOUT
50
+
51
+ fail(FinAppsCore::ApiSessionTimeoutError, 'API Session Timed out')
52
+ end
53
+
54
+ def connection_fail(env)
55
+ return unless env[:status] == CONNECTION_FAILED_STATUS
56
+
57
+ fail(FinAppsCore::ConnectionFailedError, 'Connection Failed')
58
+ end
59
+
60
+ def api_authentication_fail(env)
61
+ return unless env[:status] == API_UNAUTHENTICATED
62
+
63
+ fail(FinAppsCore::ApiUnauthenticatedError, 'API Invalid Session')
64
+ end
65
+
38
66
  def error_messages(body)
39
67
  return nil if empty?(body)
40
68
 
@@ -59,7 +87,8 @@ module FinAppsCore
59
87
  end
60
88
 
61
89
  def user_is_locked?(env)
62
- env.status == FORBIDDEN && error_messages(env.body)&.[](0)&.downcase == LOCKOUT_MESSAGE
90
+ env.status == FORBIDDEN &&
91
+ error_messages(env.body)&.[](0)&.downcase == LOCKOUT_MESSAGE
63
92
  end
64
93
 
65
94
  def symbolize(obj)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './configuration.rb'
4
- require_relative './connection.rb'
3
+ require_relative './configuration'
4
+ require_relative './connection'
5
5
  require_relative '../utils/loggeable'
6
6
  require_relative '../utils/validatable'
7
7
 
@@ -31,7 +31,8 @@ module FinAppsCore
31
31
  end
32
32
 
33
33
  # Performs HTTP GET, POST, UPDATE and DELETE requests.
34
- # You shouldn't need to use this method directly, but it can be useful for debugging.
34
+ # You shouldn't need to use this method directly,
35
+ # but it can be useful for debugging.
35
36
  # Returns a hash obtained from parsing the JSON object in the response body.
36
37
  #
37
38
  # @param [String] path
@@ -42,7 +43,7 @@ module FinAppsCore
42
43
  not_blank(path, :path)
43
44
  not_blank(method, :method)
44
45
 
45
- response, error_messages = execute_request(path, method, params)
46
+ response, error_messages = execute_request(method, path, params)
46
47
  result = block_given? ? yield(response) : response_body(response)
47
48
 
48
49
  [result, error_messages]
@@ -76,26 +77,19 @@ module FinAppsCore
76
77
  end
77
78
  end
78
79
 
79
- def execute_request(path, method, params)
80
- response = nil
81
- errors = []
82
-
83
- begin
84
- response = execute_method path, method, params
85
- rescue FinAppsCore::InvalidArgumentsError,
86
- FinAppsCore::MissingArgumentsError,
87
- Faraday::Error::ConnectionFailed => e
88
- handle_error e
89
- rescue Faraday::ClientError => e
90
- errors = handle_client_error(e)
91
- end
92
-
93
- [response, errors]
80
+ def execute_request(method, path, params)
81
+ [send(method, path, params), []]
82
+ rescue FinAppsCore::InvalidArgumentsError,
83
+ FinAppsCore::MissingArgumentsError,
84
+ Faraday::ConnectionFailed => e
85
+ [nil, handle_error(e)]
86
+ rescue Faraday::ClientError => e
87
+ [nil, handle_client_error(e)]
94
88
  end
95
89
 
96
90
  def handle_error(error)
97
91
  logger.fatal "#{self.class}##{__method__} => #{error}"
98
- raise error
92
+ fail error
99
93
  end
100
94
 
101
95
  def handle_client_error(error)
@@ -103,19 +97,13 @@ module FinAppsCore
103
97
  error.response && error.response[:error_messages] ? error.response[:error_messages] : [error.message]
104
98
  end
105
99
 
106
- def execute_method(path, method, params)
107
- case method
108
- when :get
109
- get(path)
110
- when :post
111
- post(path, params)
112
- when :put
113
- put(path, params)
114
- when :delete
115
- delete(path, params)
116
- else
117
- raise FinAppsCore::UnsupportedHttpMethodError, "Method not supported: #{method}."
100
+ def execute_method(method, path, params)
101
+ unless %i(get post put delete).include?(method)
102
+ fail FinAppsCore::UnsupportedHttpMethodError,
103
+ "Method not supported: #{method}."
118
104
  end
105
+
106
+ send(method, path, params)
119
107
  end
120
108
  end
121
109
  end
@@ -8,14 +8,13 @@ module FinAppsCore
8
8
 
9
9
  attr_accessor :tenant_token, :user_identifier, :user_token,
10
10
  :host, :proxy, :timeout, :retry_limit, :rashify,
11
- :log_level, :request_id, :consumer_id
11
+ :log_level, :request_id, :consumer_id, :tenant_id
12
12
 
13
13
  def initialize(options = {})
14
14
  FinAppsCore::REST::Defaults::DEFAULTS.merge(remove_empty_options(options))
15
15
  .each {|key, value| public_send("#{key}=", value) }
16
-
17
- raise FinAppsCore::InvalidArgumentsError, "Invalid argument. {host: #{host}}" unless valid_host?
18
- raise FinAppsCore::InvalidArgumentsError, "Invalid argument. {timeout: #{timeout}}" unless timeout.integer?
16
+ fail_invalid_host
17
+ fail_invalid_timeout
19
18
  end
20
19
 
21
20
  def valid_user_credentials?
@@ -24,12 +23,26 @@ module FinAppsCore
24
23
 
25
24
  private
26
25
 
26
+ def fail_invalid_host
27
+ return if valid_host?
28
+
29
+ fail FinAppsCore::InvalidArgumentsError,
30
+ "Invalid argument. {host: #{host}}"
31
+ end
32
+
33
+ def fail_invalid_timeout
34
+ return if timeout.integer?
35
+
36
+ fail FinAppsCore::InvalidArgumentsError,
37
+ "Invalid argument. {timeout: #{timeout}}"
38
+ end
39
+
27
40
  def valid_host?
28
41
  host.start_with?('http://', 'https://')
29
42
  end
30
43
 
31
44
  def remove_empty_options(hash)
32
- hash.reject {|_, value| value.nil? }
45
+ hash.compact
33
46
  end
34
47
  end
35
48
  end
@@ -8,40 +8,50 @@ module FinAppsCore
8
8
  options = connection_options config
9
9
 
10
10
  Faraday.new(options) do |conn|
11
- conn.request :accept_json
12
- conn.request :user_agent
13
- if config.valid_user_credentials?
14
- conn.request :no_encoding_basic_authentication, config.user_token
15
- else
16
- conn.request :tenant_authentication, config.tenant_token
17
- end
18
- conn.request :x_consumer_id, config.consumer_id if config.consumer_id
19
- conn.request :json
20
- conn.request :retry
21
- conn.request :multipart
22
- conn.request :url_encoded
23
- conn.request :request_id, config.request_id if config.request_id
24
-
25
11
  conn.use FinAppsCore::Middleware::RaiseError
26
- conn.response :json,
27
- content_type: /\bjson$/,
28
- parser_options: { symbolize_names: true }
29
- conn.response :logger, logger, bodies: true
12
+ init_connection_request conn, config
13
+ init_connection_response conn, logger
14
+ init_connection_auth conn, config
30
15
 
31
16
  # Adapter (ensure that the adapter is always last.)
32
17
  conn.adapter Faraday.default_adapter
33
18
  end
34
19
  end
35
- module_function :faraday
20
+
21
+ def init_connection_response(conn, logger)
22
+ conn.response :logger, logger, bodies: true
23
+ conn.response :json,
24
+ content_type: /\bjson$/,
25
+ parser_options: {symbolize_names: true}
26
+ end
27
+
28
+ def init_connection_request(conn, config)
29
+ conn.request :accept_json
30
+ conn.request :user_agent
31
+ conn.request :x_consumer_id, config.consumer_id if config.consumer_id
32
+ conn.request :x_tenant_id, config.tenant_id if config.tenant_id
33
+ conn.request :json
34
+ conn.request :retry
35
+ conn.request :multipart
36
+ conn.request :url_encoded
37
+ conn.request :request_id, config.request_id if config.request_id
38
+ end
39
+
40
+ def init_connection_auth(conn, config)
41
+ if config.valid_user_credentials?
42
+ conn.request :no_encoding_basic_authentication, config.user_token
43
+ else
44
+ conn.request :tenant_authentication, config.tenant_token
45
+ end
46
+ end
36
47
 
37
48
  def connection_options(config)
38
49
  {
39
50
  url: "#{config.host}/v#{Defaults::API_VERSION}/",
40
- request: { open_timeout: config.timeout,
41
- timeout: config.timeout }
51
+ request: {open_timeout: config.timeout,
52
+ timeout: config.timeout}
42
53
  }
43
54
  end
44
- module_function :connection_options
45
55
  end
46
56
  end
47
57
  end
@@ -12,7 +12,7 @@ module FinAppsCore
12
12
  host: 'https://api.finclear.io',
13
13
  timeout: 30,
14
14
  proxy: nil,
15
- log_level: Logger::INFO
15
+ log_level: Logger::UNKNOWN
16
16
  }.freeze
17
17
  end
18
18
  end
@@ -7,7 +7,7 @@ module FinAppsCore
7
7
  def logger
8
8
  @logger ||= begin
9
9
  require 'logger'
10
- logger = Logger.new(STDOUT)
10
+ logger = Logger.new($stdout)
11
11
  logger.level = FinAppsCore::REST::Defaults::DEFAULTS[:log_level]
12
12
  logger
13
13
  end
@@ -8,7 +8,7 @@ module FinAppsCore
8
8
  # Adds validation capabilities when included into other classes
9
9
  module Validatable
10
10
  def not_blank(value, name = nil)
11
- raise FinAppsCore::MissingArgumentsError, name.nil? ? nil : ": #{name}" if nil_or_empty?(value)
11
+ fail FinAppsCore::MissingArgumentsError, name.nil? ? nil : ": #{name}" if nil_or_empty?(value)
12
12
  end
13
13
 
14
14
  def nil_or_empty?(value)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FinAppsCore
4
- VERSION = '5.0.7'
4
+ VERSION = '5.0.13'
5
5
  end
@@ -2,16 +2,15 @@
2
2
 
3
3
  RSpec.describe ObjectExtensions do
4
4
  context 'when refining Object' do
5
- using ObjectExtensions
5
+ using described_class
6
6
 
7
7
  describe '#integer?' do
8
- context 'for integers' do
9
- subject { rand(1..10) }
10
- it { expect(subject.integer?).to eq(true) }
8
+ context 'with integers' do
9
+ it { expect(rand(1..10).integer?).to eq(true) }
11
10
  end
12
- context 'for non integers' do
13
- subject { rand }
14
- it { expect(subject.integer?).to eq(false) }
11
+
12
+ context 'with non integers' do
13
+ it { expect(rand.integer?).to eq(false) }
15
14
  end
16
15
  end
17
16
  end
@@ -2,12 +2,16 @@
2
2
 
3
3
  RSpec.describe FinAppsCore::Middleware::AcceptJson do
4
4
  let(:fake_app) { proc {|env| env } }
5
+
5
6
  describe '#call' do
6
- subject { FinAppsCore::Middleware::AcceptJson.new(fake_app) }
7
- env = { request_headers: {} }
7
+ subject(:accept_json) { described_class.new(fake_app) }
8
+
9
+ env = {request_headers: {}}
8
10
 
9
11
  it('generates a UserAgent header') do
10
- expect(subject.call(env)[:request_headers][FinAppsCore::Middleware::AcceptJson::KEY]).to eq('application/json')
12
+ header_key = FinAppsCore::Middleware::AcceptJson::KEY
13
+ expect(accept_json.call(env)[:request_headers][header_key])
14
+ .to eq('application/json')
11
15
  end
12
16
  end
13
17
  end