finapps 2.1.4 → 2.2.1

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