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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rspec +1 -2
- data/.rubocop.yml +102 -0
- data/.ruby-gemset +1 -1
- data/.ruby-version +1 -1
- data/Rakefile +1 -1
- data/finapps.gemspec +10 -10
- data/lib/finapps/core_extensions/hash/compact.rb +22 -0
- data/lib/finapps/core_extensions/integerable.rb +14 -0
- data/lib/finapps/core_extensions/object/blank.rb +145 -0
- data/lib/finapps/error.rb +7 -0
- data/lib/finapps/hash_constructable.rb +9 -0
- data/lib/finapps/middleware/raise_error.rb +46 -0
- data/lib/finapps/middleware/tenant_authentication.rb +19 -0
- data/lib/finapps/rest/base_client.rb +96 -0
- data/lib/finapps/rest/client.rb +11 -199
- data/lib/finapps/rest/configuration.rb +55 -0
- data/lib/finapps/rest/connection.rb +14 -33
- data/lib/finapps/rest/defaults.rb +55 -64
- data/lib/finapps/rest/resource.rb +3 -6
- data/lib/finapps/rest/resources.rb +11 -6
- data/lib/finapps/rest/users.rb +17 -57
- data/lib/finapps/utils/loggeable.rb +13 -0
- data/lib/finapps/version.rb +1 -1
- data/lib/finapps.rb +11 -23
- data/lib/tasks/releaser.rake +2 -2
- data/spec/middleware/tenant_authentication_spec.rb +29 -0
- data/spec/rest/base_client_spec.rb +89 -0
- data/spec/rest/client_spec.rb +16 -102
- data/spec/rest/configuration_spec.rb +75 -0
- data/spec/spec_helper.rb +10 -7
- data/spec/support/fake_api.rb +9 -2
- data/spec/support/fixtures/error.json +5 -0
- data/spec/support/fixtures/relevance_ruleset_names.json +47 -0
- metadata +49 -57
- data/lib/finapps/middleware/api_token.rb +0 -26
- data/lib/finapps/middleware/raise_http_exceptions.rb +0 -92
- data/lib/finapps/middleware/response_logger.rb +0 -37
- data/lib/finapps/rest/alert.rb +0 -62
- data/lib/finapps/rest/alert_definition.rb +0 -40
- data/lib/finapps/rest/alert_preferences.rb +0 -40
- data/lib/finapps/rest/alert_settings.rb +0 -40
- data/lib/finapps/rest/budget_calculation.rb +0 -45
- data/lib/finapps/rest/budget_models.rb +0 -42
- data/lib/finapps/rest/budgets.rb +0 -103
- data/lib/finapps/rest/cashflows.rb +0 -87
- data/lib/finapps/rest/categories.rb +0 -21
- data/lib/finapps/rest/errors.rb +0 -155
- data/lib/finapps/rest/institutions.rb +0 -47
- data/lib/finapps/rest/relevance/rulesets.rb +0 -64
- data/lib/finapps/rest/transactions.rb +0 -45
- data/lib/finapps/rest/user_institutions.rb +0 -138
- data/lib/finapps/utils/logging.rb +0 -95
- data/lib/finapps/utils/utils.rb +0 -57
- data/spec/middleware/api_token_spec.rb +0 -32
- data/spec/rest/connection_spec.rb +0 -40
- data/spec/rest/users_spec.rb +0 -24
- 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
|
data/lib/finapps/utils/utils.rb
DELETED
@@ -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
|
data/spec/rest/users_spec.rb
DELETED
@@ -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
|
data/spec/utils/logging_spec.rb
DELETED
@@ -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
|