finapps 2.1.4 → 2.2.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -18
  3. data/.ruby-gemset +1 -1
  4. data/.travis.yml +5 -2
  5. data/README.md +1 -1
  6. data/finapps.gemspec +10 -12
  7. data/lib/finapps.rb +5 -21
  8. data/lib/finapps/rest/client.rb +42 -53
  9. data/lib/finapps/rest/institutions.rb +2 -2
  10. data/lib/finapps/rest/institutions_forms.rb +2 -2
  11. data/lib/finapps/rest/order_reports.rb +4 -4
  12. data/lib/finapps/rest/order_statuses.rb +2 -2
  13. data/lib/finapps/rest/order_tokens.rb +2 -3
  14. data/lib/finapps/rest/orders.rb +6 -6
  15. data/lib/finapps/rest/password_resets.rb +4 -4
  16. data/lib/finapps/rest/sessions.rb +2 -2
  17. data/lib/finapps/rest/user_institutions.rb +21 -26
  18. data/lib/finapps/rest/user_institutions_forms.rb +2 -2
  19. data/lib/finapps/rest/user_institutions_statuses.rb +2 -2
  20. data/lib/finapps/rest/users.rb +5 -5
  21. data/lib/finapps/rest/version.rb +1 -1
  22. data/lib/finapps/version.rb +1 -1
  23. data/spec/rest/client_spec.rb +4 -13
  24. data/spec/rest/institutions_forms_spec.rb +5 -2
  25. data/spec/rest/institutions_spec.rb +4 -2
  26. data/spec/rest/order_reports_spec.rb +4 -4
  27. data/spec/rest/order_statuses_spec.rb +3 -2
  28. data/spec/rest/order_tokens_spec.rb +3 -2
  29. data/spec/rest/orders_spec.rb +6 -5
  30. data/spec/rest/password_resets_spec.rb +4 -4
  31. data/spec/rest/sessions_spec.rb +2 -2
  32. data/spec/rest/user_institutions_forms_spec.rb +5 -2
  33. data/spec/rest/user_institutions_spec.rb +10 -9
  34. data/spec/rest/user_institutions_statuses_spec.rb +3 -2
  35. data/spec/rest/users_spec.rb +4 -4
  36. data/spec/rest/version_spec.rb +1 -1
  37. data/spec/spec_helper.rb +5 -3
  38. data/spec/spec_helpers/client.rb +1 -1
  39. metadata +49 -124
  40. data/lib/core_extensions/hash/compact.rb +0 -23
  41. data/lib/core_extensions/object/blank.rb +0 -69
  42. data/lib/core_extensions/object/is_integer.rb +0 -10
  43. data/lib/core_extensions/string/json_to_hash.rb +0 -10
  44. data/lib/finapps/error.rb +0 -17
  45. data/lib/finapps/middleware/middleware.rb +0 -22
  46. data/lib/finapps/middleware/request/accept_json.rb +0 -14
  47. data/lib/finapps/middleware/request/no_encoding_basic_authentication.rb +0 -21
  48. data/lib/finapps/middleware/request/tenant_authentication.rb +0 -20
  49. data/lib/finapps/middleware/request/user_agent.rb +0 -15
  50. data/lib/finapps/middleware/response/custom_logger.rb +0 -41
  51. data/lib/finapps/middleware/response/raise_error.rb +0 -46
  52. data/lib/finapps/rest/base_client.rb +0 -122
  53. data/lib/finapps/rest/configuration.rb +0 -31
  54. data/lib/finapps/rest/connection.rb +0 -35
  55. data/lib/finapps/rest/credentials.rb +0 -21
  56. data/lib/finapps/rest/defaults.rb +0 -80
  57. data/lib/finapps/rest/resources.rb +0 -64
  58. data/lib/finapps/utils/loggeable.rb +0 -14
  59. data/lib/finapps/utils/parameter_filter.rb +0 -32
  60. data/spec/core_extensions/hash/compact_spec.rb +0 -21
  61. data/spec/core_extensions/object/is_integer_spec.rb +0 -17
  62. data/spec/middleware/request/accept_json_spec.rb +0 -12
  63. data/spec/middleware/request/no_encoding_basic_authentication_spec.rb +0 -32
  64. data/spec/middleware/request/tenant_authentication_spec.rb +0 -34
  65. data/spec/middleware/request/user_agent_spec.rb +0 -12
  66. data/spec/middleware/response/raise_error_spec.rb +0 -24
  67. data/spec/rest/base_client_spec.rb +0 -120
  68. data/spec/rest/configuration_spec.rb +0 -39
  69. data/spec/rest/credentials_spec.rb +0 -20
  70. data/spec/rest/resources_spec.rb +0 -76
  71. data/spec/rest/timeout_spec.rb +0 -9
  72. data/spec/support/fixtures/relevance_ruleset_names.json +0 -47
  73. data/spec/utils/parameter_filter_spec.rb +0 -23
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
- module FinApps
3
- module REST
4
- module Defaults
5
- API_VERSION = '2'
6
-
7
- # noinspection SpellCheckingInspection
8
- DEFAULTS = {
9
- host: 'https://api.financialapps.com',
10
- user_identifier: nil,
11
- user_token: nil,
12
- timeout: 30,
13
- proxy: nil,
14
- retry_limit: 1,
15
- log_level: Logger::INFO
16
- }.freeze
17
-
18
- END_POINTS = {
19
- users_create: 'users/new',
20
- users_update: 'user',
21
- users_update_password: 'user/password',
22
- users_delete: 'users/:public_id',
23
- users_show: 'users/:public_id',
24
- users_login: 'users/login',
25
-
26
- relevance_rulesets_list: 'relevance/ruleset/names',
27
- relevance_rulesets_show: 'relevance/ruleset/:ruleset_name',
28
- relevance_rulesets_run: 'relevance/run',
29
-
30
- institutions_list: 'institutions/:search_term/search',
31
- institutions_form: 'institutions/:site_id/form',
32
-
33
- user_institutions_list: 'institutions/user',
34
- user_institutions_add: 'institutions/:site_id/add',
35
- user_institutions_show: 'institutions/user/:user_institution_id',
36
- user_institutions_update: 'institutions/user/:user_institution_id/credentials',
37
- user_institutions_delete: 'institutions/user/:user_institution_id',
38
- user_institutions_status: 'institutions/user/:user_institution_id/status',
39
- user_institutions_mfa: 'institutions/user/:user_institution_id/mfa',
40
- user_institutions_refresh: 'institutions/user/refresh',
41
- user_institutions_form: 'institutions/user/:user_institution_id/form',
42
-
43
- transactions_show: 'transaction/:transaction_id',
44
- transactions_list: 'transactions/search',
45
- transactions_update: 'transactions/edit',
46
-
47
- categories_list: 'categories',
48
- categories_new: 'categories',
49
- categories_update: 'categories',
50
- categories_show: 'categories/:category_id',
51
- categories_delete: 'categories/:category_id',
52
-
53
- budget_models_list: 'budget/templates',
54
- budget_models_show: 'budget/template/:budget_model_id',
55
-
56
- budget_calculation_create: 'budget/template/:budget_model_id/:income',
57
- budget_calculation_show: 'categories',
58
-
59
- budget_update: 'budget',
60
- budget_show: 'budget/:start_date/:end_date',
61
-
62
- cashflow_show: 'cashflow/:start_date/:end_date',
63
-
64
- alert_list: 'alerts/:page/:requested/:sort/:asc/:read',
65
- alert_update: 'alerts/:alert_id/:read',
66
- alert_delete: 'alerts/:alert_id',
67
-
68
- alert_definition_list: 'alerts/definitions',
69
- alert_definition_show: 'alerts/definitions/:alert_name',
70
-
71
- alert_settings_show: 'alerts/settings',
72
- alert_settings_update: 'alerts/settings',
73
-
74
- alert_preferences_show: 'alerts/preferences',
75
- alert_preferences_update: 'alerts/preferences'
76
-
77
- }.freeze
78
- end
79
- end
80
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
- module FinApps
3
- module REST
4
- class Resources # :nodoc:
5
- include FinApps::Utils::ParameterFilter
6
- require 'erb'
7
-
8
- attr_reader :client
9
-
10
- # @param [FinApps::REST::Client] client
11
- # @return [FinApps::REST::Resources]
12
- def initialize(client)
13
- raise MissingArgumentsError.new 'Missing argument: client.' if client.nil?
14
- raise InvalidArgumentsError.new 'Invalid argument: client.' unless client.is_a?(FinApps::REST::Client)
15
-
16
- @client = client
17
- end
18
-
19
- def list(path=nil)
20
- path = end_point.to_s if path.nil?
21
- request_with_body(path, :get, {})
22
- end
23
-
24
- def create(params={}, path=nil)
25
- request_with_body(path, :post, params)
26
- end
27
-
28
- def update(params={}, path=nil)
29
- request_with_body(path, :put, params)
30
- end
31
-
32
- def show(id=nil, path=nil)
33
- request_without_body(path, :get, id)
34
- end
35
-
36
- def destroy(id=nil, path=nil)
37
- request_without_body(path, :delete, id)
38
- end
39
-
40
- def request_without_body(path, method, id)
41
- raise MissingArgumentsError.new 'Missing argument: id.' if id.nil? && path.nil?
42
- path = "#{end_point}/:id".sub ':id', ERB::Util.url_encode(id) if path.nil?
43
- request_with_body path, method, {}
44
- end
45
-
46
- def request_with_body(path, method, params)
47
- path = end_point if path.nil?
48
- logger.debug "#{self.class.name}##{__method__} => path: #{path} params: #{skip_sensitive_data(params)}"
49
-
50
- client.send_request path, method, params
51
- end
52
-
53
- protected
54
-
55
- def logger
56
- client.logger
57
- end
58
-
59
- def end_point
60
- self.class.name.split('::').last.downcase
61
- end
62
- end
63
- end
64
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
- module FinApps
3
- module Utils
4
- # Adds logging capabilities when included into other classes
5
- module Loggeable
6
- def logger
7
- @logger ||= begin
8
- require 'logger'
9
- ::Logger.new(STDOUT)
10
- end
11
- end
12
- end
13
- end
14
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
- module FinApps
3
- module Utils
4
- module ParameterFilter
5
- using StringExtensions
6
- PROTECTED_KEYS = %w(login login1 username password password1 password_confirm token
7
- x-finapps-token authorization).freeze
8
-
9
- def skip_sensitive_data(hash)
10
- if hash.is_a? String
11
- hash = hash.json_to_hash
12
- end
13
- if hash.is_a? Hash
14
- filtered_hash = hash.clone
15
- filtered_hash.each do |key, value|
16
- if PROTECTED_KEYS.include? key.to_s.downcase
17
- filtered_hash[key] = '[REDACTED]'
18
- elsif value.is_a?(Hash)
19
- filtered_hash[key] = skip_sensitive_data(value)
20
- elsif value.is_a?(Array)
21
- filtered_hash[key] = value.map {|v| v.is_a?(Hash) ? skip_sensitive_data(v) : v }
22
- end
23
- end
24
-
25
- filtered_hash
26
- else
27
- hash
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe HashExtensions do
3
- context 'when refining hash' do
4
- using HashExtensions
5
-
6
- subject { {a: true, b: false, c: nil} }
7
-
8
- describe '#compact' do
9
- it 'returns a hash with non nil values' do
10
- expect(subject.compact).to eq(a: true, b: false)
11
- expect(subject).to eq(a: true, b: false, c: nil)
12
- end
13
- end
14
- describe '#compact!' do
15
- it 'replaces current hash with non nil values' do
16
- expect(subject.compact!).to eq(a: true, b: false)
17
- expect(subject).to eq(a: true, b: false)
18
- end
19
- end
20
- end
21
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe ObjectExtensions do
3
- context 'when refining Object' do
4
- using ObjectExtensions
5
-
6
- describe '#integer?' do
7
- context 'for integers' do
8
- subject { 1 + rand(10) }
9
- it { expect(subject.integer?).to eq(true) }
10
- end
11
- context 'for non integers' do
12
- subject { rand }
13
- it { expect(subject.integer?).to eq(false) }
14
- end
15
- end
16
- end
17
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::Middleware::AcceptJson do
3
- let(:fake_app) { proc {|env| env } }
4
- describe '#call' do
5
- subject { FinApps::Middleware::AcceptJson.new(fake_app) }
6
- env = {request_headers: {}}
7
-
8
- it('generates a UserAgent header') do
9
- expect(subject.call(env)[:request_headers][FinApps::Middleware::AcceptJson::KEY]).to eq('application/json')
10
- end
11
- end
12
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::Middleware::NoEncodingBasicAuthentication do
3
- let(:valid_credentials) { VALID_CREDENTIALS }
4
- let(:key) { FinApps::Middleware::NoEncodingBasicAuthentication::KEY }
5
-
6
- describe '#call' do
7
- fake_app = proc {|env| env }
8
-
9
- context 'when credentials were provided' do
10
- let(:middleware) do
11
- FinApps::Middleware::NoEncodingBasicAuthentication.new(fake_app, VALID_CREDENTIALS[:token])
12
- end
13
- let(:expected_header) { "Basic #{valid_credentials[:token]}" }
14
-
15
- context 'when header was not previously set' do
16
- let(:request_env) { {request_headers: {}} }
17
- subject(:actual_header) { middleware.call(request_env)[:request_headers][key] }
18
-
19
- it('generates a header') { expect(actual_header).to eq(expected_header) }
20
- end
21
-
22
- context 'when header was previously set' do
23
- let(:existing_header) { {FinApps::Middleware::NoEncodingBasicAuthentication::KEY => 'foo'} }
24
- let(:request_env) { {request_headers: existing_header} }
25
- subject(:actual_header) { middleware.call(request_env)[:request_headers][key] }
26
-
27
- it('does not override existing header') { expect(actual_header).to eq('foo') }
28
- it('does not generate a header') { expect(actual_header).to_not eq(expected_header) }
29
- end
30
- end
31
- end
32
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::Middleware::TenantAuthentication do
3
- let(:valid_tenant_options) { VALID_CREDENTIALS }
4
- let(:key) { FinApps::Middleware::TenantAuthentication::KEY }
5
-
6
- describe '#call' do
7
- fake_app = proc {|env| env }
8
-
9
- context 'when company credentials were provided' do
10
- let(:middleware) do
11
- FinApps::Middleware::TenantAuthentication.new(fake_app,
12
- VALID_CREDENTIALS[:identifier],
13
- VALID_CREDENTIALS[:token])
14
- end
15
- let(:expected_header) { "#{valid_tenant_options[:identifier]}=#{valid_tenant_options[:token]}" }
16
-
17
- context 'when header was not previously set' do
18
- let(:request_env) { {request_headers: {}} }
19
- subject(:actual_header) { middleware.call(request_env)[:request_headers][key] }
20
-
21
- it('generates a Tenant Authentication header') { expect(actual_header).to eq(expected_header) }
22
- end
23
-
24
- context 'when header was previously set' do
25
- let(:existing_header) { {FinApps::Middleware::TenantAuthentication::KEY => 'foo'} }
26
- let(:request_env) { {request_headers: existing_header} }
27
- subject(:actual_header) { middleware.call(request_env)[:request_headers][key] }
28
-
29
- it('does not override existing Tenant Authentication header') { expect(actual_header).to eq('foo') }
30
- it('does not generate a Tenant Authentication header') { expect(actual_header).to_not eq(expected_header) }
31
- end
32
- end
33
- end
34
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::Middleware::UserAgent do
3
- let(:fake_app) { proc {|env| env } }
4
- describe '#call' do
5
- subject { FinApps::Middleware::UserAgent.new(fake_app) }
6
- env = {request_headers: {}}
7
-
8
- it('generates a UserAgent header') do
9
- expect(subject.call(env)[:request_headers][FinApps::Middleware::UserAgent::KEY]).to start_with('finapps-ruby')
10
- end
11
- end
12
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::Middleware::RaiseError do
3
- let(:fake_app) { proc {|env| env } }
4
- Env = Struct.new(:status, :response_headers, :body)
5
-
6
- describe '#on_complete' do
7
- subject { FinApps::Middleware::RaiseError.new(fake_app) }
8
-
9
- context 'for succesful requests' do
10
- let(:env) { Env.new(200) }
11
- it { expect { subject.on_complete(env) }.not_to raise_error }
12
- end
13
- context 'for client errors' do
14
- let(:env) { Env.new(401, {}, '{"messages":["Invalid User Identifier or Credentials"]}') }
15
- error_message = 'the server responded with status 401'
16
- it { expect { subject.on_complete(env) }.to raise_error(Faraday::Error::ClientError, error_message) }
17
- end
18
- context 'for connection failed error' do
19
- let(:env) { Env.new(407) }
20
- error_message = '407 "Proxy Authentication Required"'
21
- it { expect { subject.on_complete(env) }.to raise_error(Faraday::Error::ConnectionFailed, error_message) }
22
- end
23
- end
24
- end
@@ -1,120 +0,0 @@
1
- # frozen_string_literal: true
2
- RSpec.describe FinApps::REST::BaseClient do
3
- let(:valid_tenant_options) do
4
- {tenant_identifier: VALID_CREDENTIALS[:identifier],
5
- tenant_token: VALID_CREDENTIALS[:token]}
6
- end
7
- subject { FinApps::REST::BaseClient.new(valid_tenant_options) }
8
-
9
- RESPONSE = 0
10
- ERROR_MESSAGES = 1
11
- let(:return_array) { %i(RESPONSE ERROR_MESSAGES) }
12
-
13
- describe '#new' do
14
- it 'assigns @config' do
15
- expect(subject.config).to be_a(FinApps::REST::Configuration)
16
- end
17
- end
18
-
19
- describe '#user_credentials?' do
20
- context 'when user credentials were not set' do
21
- it { expect(subject.user_credentials?).to eq(false) }
22
- end
23
- context 'when user credentials were set' do
24
- subject { FinApps::REST::BaseClient.new(valid_tenant_options.merge(user_identifier: 1, user_token: 2)) }
25
- it { expect(subject.user_credentials?).to eq(true) }
26
- end
27
- end
28
-
29
- describe '#connection' do
30
- it 'created a Faraday connection object' do
31
- expect(subject.connection).to be_a(Faraday::Connection)
32
- end
33
-
34
- it 'memoizes the results' do
35
- first = subject.connection
36
- second = subject.connection
37
- expect(first.object_id).to eq(second.object_id)
38
- end
39
- end
40
-
41
- describe '#send_request' do
42
- it 'should raise FinApps::InvalidArgumentsError if method is NOT supported' do
43
- expect { subject.send_request('fake_path', :option) }.to raise_error(FinApps::InvalidArgumentsError,
44
- 'Method not supported: option.')
45
- end
46
-
47
- it 'should raise FinApps::MissingArgumentsError if method is NOT provided' do
48
- expect { subject.send_request(nil, :get) }.to raise_error(FinApps::MissingArgumentsError,
49
- 'Missing argument: path.')
50
- end
51
-
52
- it 'should raise FinApps::MissingArgumentsError if path is NOT provided' do
53
- expect { subject.send_request('fake_path', nil) }.to raise_error(FinApps::MissingArgumentsError,
54
- 'Missing argument: method.')
55
- end
56
-
57
- context 'when method and path are provided' do
58
- subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('relevance/ruleset/names', :get) }
59
- let(:return_array) { %i(RESPONSE ERROR_MESSAGES) }
60
-
61
- it('returns an array of 2 items') do
62
- expect(subject).to be_a(Array)
63
- expect(subject.size).to eq(return_array.length)
64
- end
65
-
66
- context 'for unsupported methods' do
67
- subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('users', :options) }
68
-
69
- it do
70
- expect { subject.send_request(nil, :get) }
71
- .to raise_error(FinApps::InvalidArgumentsError, 'Method not supported: options.')
72
- end
73
- end
74
-
75
- context 'for client errors' do
76
- subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('client_error', :get) }
77
-
78
- it('result is null') { expect(subject[RESPONSE]).to be_nil }
79
- it('error_messages is an array') { expect(subject[ERROR_MESSAGES]).to be_a(Array) }
80
- it('error_messages gets populated') { expect(subject[ERROR_MESSAGES].first).to eq 'Password Minimum size is 8' }
81
- end
82
-
83
- context 'for server errors' do
84
- subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('server_error', :get) }
85
-
86
- it('the result should be nil') { expect(subject[RESPONSE]).to be_nil }
87
- it { expect(subject[ERROR_MESSAGES]).not_to be_nil }
88
- it { expect(subject[ERROR_MESSAGES]).to be_a(Array) }
89
- it { expect(subject[ERROR_MESSAGES].first).to eq 'the server responded with status 500' }
90
- end
91
-
92
- context 'for proxy errors' do
93
- subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('proxy_error', :get) }
94
-
95
- it { expect { subject }.to raise_error(Faraday::ConnectionFailed, '407 "Proxy Authentication Required"') }
96
- end
97
- end
98
-
99
- context 'if a block is provided' do
100
- it('gets executed on the response') do
101
- expect(subject.send_request('relevance/ruleset/names', :get, &:status)[RESPONSE]).to eq(200)
102
- expect(subject.send_request('relevance/ruleset/names', :get) {|r| r.body.length }[RESPONSE]).to eq(45)
103
- end
104
- end
105
- end
106
-
107
- describe '#method_missing' do
108
- context 'for unsupported methods' do
109
- it { expect { subject.unsupported }.to raise_error(NoMethodError) }
110
- end
111
- end
112
-
113
- describe '#respond_to_missing?' do
114
- context 'for supported methods' do
115
- [:get, :post, :put, :delete].each do |method|
116
- it("responds to #{method}") { expect(subject).to respond_to(method) }
117
- end
118
- end
119
- end
120
- end