finapps 1.0.8 → 2.0.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rspec +1 -2
  4. data/.rubocop.yml +102 -0
  5. data/.ruby-gemset +1 -1
  6. data/.ruby-version +1 -1
  7. data/Rakefile +1 -1
  8. data/finapps.gemspec +10 -10
  9. data/lib/finapps/core_extensions/hash/compact.rb +22 -0
  10. data/lib/finapps/core_extensions/integerable.rb +14 -0
  11. data/lib/finapps/core_extensions/object/blank.rb +145 -0
  12. data/lib/finapps/error.rb +7 -0
  13. data/lib/finapps/hash_constructable.rb +9 -0
  14. data/lib/finapps/middleware/raise_error.rb +46 -0
  15. data/lib/finapps/middleware/tenant_authentication.rb +19 -0
  16. data/lib/finapps/rest/base_client.rb +96 -0
  17. data/lib/finapps/rest/client.rb +11 -199
  18. data/lib/finapps/rest/configuration.rb +55 -0
  19. data/lib/finapps/rest/connection.rb +14 -33
  20. data/lib/finapps/rest/defaults.rb +55 -64
  21. data/lib/finapps/rest/resource.rb +3 -6
  22. data/lib/finapps/rest/resources.rb +11 -6
  23. data/lib/finapps/rest/users.rb +17 -57
  24. data/lib/finapps/utils/loggeable.rb +13 -0
  25. data/lib/finapps/version.rb +1 -1
  26. data/lib/finapps.rb +11 -23
  27. data/lib/tasks/releaser.rake +2 -2
  28. data/spec/middleware/tenant_authentication_spec.rb +29 -0
  29. data/spec/rest/base_client_spec.rb +89 -0
  30. data/spec/rest/client_spec.rb +16 -102
  31. data/spec/rest/configuration_spec.rb +75 -0
  32. data/spec/spec_helper.rb +10 -7
  33. data/spec/support/fake_api.rb +9 -2
  34. data/spec/support/fixtures/error.json +5 -0
  35. data/spec/support/fixtures/relevance_ruleset_names.json +47 -0
  36. metadata +49 -57
  37. data/lib/finapps/middleware/api_token.rb +0 -26
  38. data/lib/finapps/middleware/raise_http_exceptions.rb +0 -92
  39. data/lib/finapps/middleware/response_logger.rb +0 -37
  40. data/lib/finapps/rest/alert.rb +0 -62
  41. data/lib/finapps/rest/alert_definition.rb +0 -40
  42. data/lib/finapps/rest/alert_preferences.rb +0 -40
  43. data/lib/finapps/rest/alert_settings.rb +0 -40
  44. data/lib/finapps/rest/budget_calculation.rb +0 -45
  45. data/lib/finapps/rest/budget_models.rb +0 -42
  46. data/lib/finapps/rest/budgets.rb +0 -103
  47. data/lib/finapps/rest/cashflows.rb +0 -87
  48. data/lib/finapps/rest/categories.rb +0 -21
  49. data/lib/finapps/rest/errors.rb +0 -155
  50. data/lib/finapps/rest/institutions.rb +0 -47
  51. data/lib/finapps/rest/relevance/rulesets.rb +0 -64
  52. data/lib/finapps/rest/transactions.rb +0 -45
  53. data/lib/finapps/rest/user_institutions.rb +0 -138
  54. data/lib/finapps/utils/logging.rb +0 -95
  55. data/lib/finapps/utils/utils.rb +0 -57
  56. data/spec/middleware/api_token_spec.rb +0 -32
  57. data/spec/rest/connection_spec.rb +0 -40
  58. data/spec/rest/users_spec.rb +0 -24
  59. data/spec/utils/logging_spec.rb +0 -28
@@ -1,95 +0,0 @@
1
- module FinApps
2
- module Logging
3
-
4
- SEVERITY_LABEL = %w(DEBUG INFO WARN ERROR FATAL UNKNOWN)
5
- PROTECTED_KEYS = %w(login login1 password password1 password_confirm token)
6
- FORMAT = "\033[%sm[%s#%d] %5s -- %s: %s\033[0m\n"
7
- FORMAT_TAG = "\033[%sm[%s#%d] %5s -- %s: %s %s\033[0m\n"
8
- SEVERITY_COLOR_MAP = {:debug => '0', :info => '32', :warn => '33', :error => '31', :fatal => '31', :unknown => '0;37'}
9
-
10
-
11
- class << self;
12
- attr_accessor :tag, :level;
13
- end
14
-
15
- def logger=(logger)
16
- @logger = logger
17
- end
18
-
19
- # noinspection SpellCheckingInspection
20
- def logger
21
-
22
- @logger ||= begin
23
- require 'logger' unless defined?(::Logger)
24
- ::Logger.new(STDOUT).tap do |log|
25
- log.progname = "#{self.class.to_s}"
26
- log.level = Logging.level if Logging.level.present?
27
- log.formatter = proc do |severity, time, progname, msg|
28
- Logging.tag.present? ?
29
- FORMAT_TAG % [severity_to_color(severity), format_datetime(time), $$, severity, progname, Logging.tag.to_s, msg2str(msg)] :
30
- FORMAT % [severity_to_color(severity), format_datetime(time), $$, severity, progname, msg2str(msg)]
31
-
32
- end
33
- end
34
- end
35
-
36
- end
37
-
38
- def logger_config(config)
39
- Logging.tag= config[:logger_tag] if config[:logger_tag].present?
40
- Logging.level = config[:log_level] if config[:log_level].present?
41
- end
42
-
43
- # noinspection SpellCheckingInspection
44
- def set_up_logger_session_params(uuid, session_id)
45
- if uuid.present? || session_id.present?
46
- uuid ||= '-'
47
- session_id ||= '-'
48
- logger.formatter = proc do |severity, time, progname, msg|
49
- "[%s#%d] %5s -- %s: [#{uuid}] [#{session_id}] %s\n" % [format_datetime(time), $$, severity, progname, msg2str(msg)]
50
- end
51
- end
52
- end
53
-
54
- # @param [Hash] hash
55
- def skip_sensitive_data(hash)
56
- if hash.is_a? Hash
57
- filtered_hash = hash.clone
58
- filtered_hash.each do |key, value|
59
- if PROTECTED_KEYS.include? key.to_s.downcase
60
- filtered_hash[key] = '[REDACTED]'
61
- elsif value.is_a?(Hash)
62
- filtered_hash[key] = self.skip_sensitive_data(value)
63
- elsif value.is_a?(Array)
64
- filtered_hash[key] = value.map { |v| v.is_a?(Hash) ? self.skip_sensitive_data(v) : v }
65
- end
66
- end
67
-
68
- filtered_hash
69
- else
70
- hash
71
- end
72
- end
73
-
74
- private
75
- def format_datetime(time)
76
- time.strftime('%Y-%m-%dT%H:%M:%S.') << '%06d ' % time.usec
77
- end
78
-
79
- def msg2str(msg)
80
- case msg
81
- when ::String
82
- msg
83
- when ::Exception
84
- "#{ msg.message } (#{ msg.class })\n" << (msg.backtrace || []).join("\n")
85
- else
86
- msg.inspect
87
- end
88
- end
89
-
90
- def severity_to_color(severity)
91
- SEVERITY_COLOR_MAP[severity.downcase.to_sym]
92
- end
93
-
94
- end
95
- end
@@ -1,57 +0,0 @@
1
- class Object
2
- # An object is blank if it's false, empty, or a whitespace string.
3
- # For example, "", " ", +nil+, [], and {} are all blank.
4
- #
5
- # This simplifies:
6
- #
7
- # if address.nil? || address.empty?
8
- #
9
- # ...to:
10
- #
11
- # if address.blank?
12
- def blank?
13
- respond_to?(:empty?) ? empty? : !self
14
- end
15
-
16
- # An object is present if it's not <tt>blank?</tt>.
17
- def present?
18
- !blank?
19
- end
20
-
21
- # Returns object if it's <tt>present?</tt> otherwise returns +nil+.
22
- # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>.
23
- #
24
- # This is handy for any representation of objects where blank is the same
25
- # as not present at all. For example, this simplifies a common check for
26
- # HTTP POST/query parameters:
27
- #
28
- # state = params[:state] if params[:state].present?
29
- # country = params[:country] if params[:country].present?
30
- # region = state || country || 'US'
31
- #
32
- # ...becomes:
33
- #
34
- # region = params[:state].presence || params[:country].presence || 'US'
35
- def presence
36
- self if present?
37
- end
38
-
39
- def trim
40
- respond_to?(:strip) ? self.strip : self
41
- end
42
- end
43
-
44
-
45
-
46
- class Hash
47
- def validate_required_strings!
48
- self.each do |key, value|
49
- raise FinApps::REST::MissingArgumentsError.new "Missing argument: #{key}." if value.blank?
50
- raise FinApps::REST::InvalidArgumentsError.new "Invalid #{key} specified: #{value.inspect} must be a string or symbol." unless value.is_a?(String) || value.is_a?(Symbol)
51
- end
52
- end
53
-
54
- def compact
55
- self.delete_if { |_, v| v.nil? }
56
- end
57
- end
@@ -1,32 +0,0 @@
1
- RSpec.describe FinApps::Middleware::ApiToken do
2
-
3
- describe '#call' do
4
-
5
- fake_app = Proc.new { |env| env }
6
- valid_credentials = {:company_identifier => 'id', :company_token => 'token'}
7
-
8
- context 'when company_identifier is NOT provided' do
9
- let(:api_token) { FinApps::Middleware::ApiToken.new fake_app, valid_credentials.select { |x| x!= :company_identifier } }
10
- it { expect { api_token.call({}) }.to raise_error(FinApps::REST::MissingArgumentsError) }
11
- end
12
-
13
- context 'when company_token is NOT provided' do
14
- let(:api_token) { FinApps::Middleware::ApiToken.new fake_app, valid_credentials.select { |x| x!= :company_token } }
15
- it { expect { api_token.call({}) }.to raise_error(FinApps::REST::MissingArgumentsError) }
16
- end
17
-
18
- context 'when company credentials were provided' do
19
-
20
- let(:api_token) { FinApps::Middleware::ApiToken.new fake_app, valid_credentials }
21
- let(:expected_header_value) { "#{valid_credentials[:company_identifier]}=#{valid_credentials[:company_token]}" }
22
- subject(:call) { api_token.call({:request_headers => {}}) }
23
-
24
- it { expect { call }.not_to raise_error }
25
- it 'should generate the X-FinApps-Token header' do
26
- expect(call[:request_headers]['X-FinApps-Token']).to eq(expected_header_value)
27
- end
28
- end
29
-
30
- end
31
- end
32
-
@@ -1,40 +0,0 @@
1
- require 'base64'
2
-
3
- RSpec.describe FinApps::REST::Connection do
4
-
5
- let(:dummy_class) { Class.new { extend FinApps::REST::Connection } }
6
- let(:valid_credentials) { {:company_identifier => 'id', :company_token => 'token'} }
7
- let(:user_credentials) { {:user_identifier => 'user_id', :user_token => 'user_token'} }
8
-
9
- it { expect(dummy_class).to respond_to(:set_up_connection) }
10
-
11
- describe '#set_up_connection' do
12
-
13
- context 'when using valid company credentials' do
14
- subject(:set_up_connection) { dummy_class.set_up_connection(valid_credentials, {}) }
15
- it { expect(set_up_connection).to be_an_instance_of(Faraday::Connection) }
16
- it { expect(set_up_connection.headers).to include({'Accept' => FinApps::REST::Defaults::HEADERS[:accept]}) }
17
- it { expect(set_up_connection.headers).to include({'User-Agent' => FinApps::REST::Defaults::HEADERS[:user_agent]}) }
18
- context 'when NOT providing user credentials' do
19
- it { expect(set_up_connection.builder.handlers).not_to include(Faraday::Request::BasicAuthentication) }
20
- end
21
- end
22
-
23
- context 'when using valid user credentials' do
24
- subject(:set_up_connection) { dummy_class.set_up_connection(valid_credentials, user_credentials) }
25
- let(:header) { Faraday::Request::BasicAuthentication.header(user_credentials[:user_identifier], user_credentials[:user_token]) }
26
-
27
- it { expect(set_up_connection.builder.handlers).to include(Faraday::Request::BasicAuthentication) }
28
- it 'sets a proper authorization header' do
29
- stub_request(:get, "#{FinApps::REST::Defaults::DEFAULTS[:host]}/auth-echo").to_return(:status => 200)
30
- expect(set_up_connection.get('/auth-echo').env.request_headers).to include({:authorization => header})
31
- end
32
- end
33
-
34
- context 'using an invalid host_url parameter' do
35
- subject(:set_up_connection) { dummy_class.set_up_connection(valid_credentials, {:host => 'yahoo.com'}) }
36
- it { expect { set_up_connection }.to raise_error(FinApps::REST::InvalidArgumentsError) }
37
- end
38
-
39
- end
40
- end
@@ -1,24 +0,0 @@
1
- RSpec.describe FinApps::REST::Users do
2
-
3
- context 'after initialized' do
4
- let(:users) { FinApps::REST::Users.new(FinApps::REST::Client.new(:id, :token)) }
5
-
6
- [:show, :create, :update, :update_password, :login, :delete].each do |method|
7
- it "responds to #{method}" do
8
- expect(users).to respond_to(method)
9
- end
10
- end
11
-
12
- describe '#show' do
13
-
14
- context 'when public_id is NOT provided' do
15
- it { expect { users.show(nil) }.to raise_error(FinApps::REST::MissingArgumentsError) }
16
- end
17
-
18
- it { expect(users.show(1)[0]).to be_an_instance_of(FinApps::REST::User) }
19
-
20
- end
21
-
22
- end
23
-
24
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe FinApps::Logging do
4
-
5
- let(:dummy_class) { Class.new { extend FinApps::Logging } }
6
- let(:simple_hash) { {:login => 'login', :password => 'secret'} }
7
- let(:deep_hash) { {:parameters => {:login => 'login', :password => 'secret'}} }
8
- let(:array_of_hashes) { {:parameters => [{:login => 'login', :password => 'secret'},
9
- {:login1 => 'login1', :password1 => 'secret1'},
10
- {:user => 'user', :token => 'secret'}]} }
11
-
12
- it 'should redact protected keys on a simple Hash' do
13
- redacted = dummy_class.skip_sensitive_data simple_hash
14
- expect(redacted[:password]).to eq('[REDACTED]')
15
- end
16
-
17
- it 'should redact protected keys on a deep Hash' do
18
- redacted = dummy_class.skip_sensitive_data deep_hash
19
- expect(redacted[:parameters][:password]).to eq('[REDACTED]')
20
- end
21
-
22
- it 'should redact protected keys on an array of Hashes' do
23
- redacted = dummy_class.skip_sensitive_data array_of_hashes
24
- expect(redacted[:parameters][0][:password]).to eq('[REDACTED]')
25
- expect(redacted[:parameters][1][:password1]).to eq('[REDACTED]')
26
- expect(redacted[:parameters][2][:token]).to eq('[REDACTED]')
27
- end
28
- end