finapps 1.0.8 → 2.0.2

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