finapps_core 5.0.7 → 5.0.13

Sign up to get free protection for your applications and to get access to all the features.
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