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