finapps 2.0.6 → 2.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -6
  3. data/Gemfile +1 -0
  4. data/Rakefile +1 -0
  5. data/finapps.gemspec +1 -1
  6. data/lib/core_extensions/hash/compact.rb +23 -0
  7. data/lib/core_extensions/object/blank.rb +69 -0
  8. data/lib/core_extensions/object/is_integer.rb +12 -0
  9. data/lib/finapps.rb +10 -6
  10. data/lib/finapps/error.rb +5 -0
  11. data/lib/finapps/middleware/middleware.rb +17 -0
  12. data/lib/finapps/middleware/request/accept_json.rb +14 -0
  13. data/lib/finapps/middleware/{tenant_authentication.rb → request/tenant_authentication.rb} +4 -3
  14. data/lib/finapps/middleware/request/user_agent.rb +15 -0
  15. data/lib/finapps/middleware/{raise_error.rb → response/raise_error.rb} +5 -2
  16. data/lib/finapps/rest/base_client.rb +29 -13
  17. data/lib/finapps/rest/client.rb +6 -4
  18. data/lib/finapps/rest/configuration.rb +11 -39
  19. data/lib/finapps/rest/connection.rb +17 -11
  20. data/lib/finapps/rest/credentials.rb +21 -0
  21. data/lib/finapps/rest/defaults.rb +9 -9
  22. data/lib/finapps/rest/orders.rb +4 -0
  23. data/lib/finapps/rest/resources.rb +2 -1
  24. data/lib/finapps/rest/users.rb +4 -0
  25. data/lib/finapps/utils/loggeable.rb +1 -0
  26. data/lib/finapps/version.rb +2 -1
  27. data/lib/tasks/releaser.rake +1 -0
  28. data/spec/middleware/accept_json_spec.rb +12 -0
  29. data/spec/middleware/tenant_authentication_spec.rb +6 -1
  30. data/spec/middleware/user_agent_spec.rb +12 -0
  31. data/spec/rest/base_client_spec.rb +9 -5
  32. data/spec/rest/client_spec.rb +1 -0
  33. data/spec/rest/configuration_spec.rb +16 -63
  34. data/spec/rest/credentials_spec.rb +20 -0
  35. data/spec/rest/orders_spec.rb +1 -0
  36. data/spec/rest/resources_spec.rb +1 -0
  37. data/spec/spec_helper.rb +2 -0
  38. data/spec/support/fake_api.rb +2 -0
  39. metadata +23 -32
  40. data/lib/finapps/core_extensions/integerable.rb +0 -14
  41. data/lib/finapps/hash_constructable.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3744a2198661b2f9ec29349d7fab215fec21ca59
4
- data.tar.gz: 89aa372c099626f02b74029badf483e8a8b5f857
3
+ metadata.gz: bcf4ea9c9605ea437a7c813888251d0ade6c48ff
4
+ data.tar.gz: 4566ea877d76bfd844191fa425dc520bb72a63d1
5
5
  SHA512:
6
- metadata.gz: 75115e8917ab7e2f6ca094113a7412d31e5f2aac5372b854a9218495de744d5b3f7d26be8a2b5564aab82a828359980df8b380b4d2090cf712079ce9c29f5b75
7
- data.tar.gz: f0962398b0663b53931eb3a5ee11f665c2f5f8b9ac906d6eaeb4b35e9c18a1be72a96b7ee1344defeb18b4628ca0e914c7a12f0d192a137ac99b9e9ce84e4f2e
6
+ metadata.gz: 1370d0de8ce5510d1defe65b08caf38c7a10d0ed507d38040ff3e6a5e6e75b2b4f7582ff02728c660c1082a271f0a9d3e09fa59e3dc9458779ff741cbf669cbb
7
+ data.tar.gz: 240d6213a3f48f1eb9395c9050754f74dc4eeabb4a8e2697fa92901ebf61c50a6d8a100c1f2d32d3abf8ba7913c9358f4c380f404f4d09e496c38bc6975b7c23
data/.codeclimate.yml CHANGED
@@ -1,15 +1,12 @@
1
1
  engines:
2
2
  rubocop:
3
3
  enabled: true
4
- #checks:
5
- # Rubocop/Metrics/ClassLength:
6
- # enabled: false
7
4
  brakeman:
8
- enabled: true
5
+ enabled: false
9
6
  eslint:
10
- enabled: true
7
+ enabled: false
11
8
  csslint:
12
- enabled: true
9
+ enabled: false
13
10
  duplication:
14
11
  enabled: true
15
12
  config:
data/Gemfile CHANGED
@@ -1,2 +1,3 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
  gemspec
data/Rakefile CHANGED
@@ -1 +1,2 @@
1
+ # frozen_string_literal: true
1
2
  import './lib/tasks/releaser.rake'
data/finapps.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'finapps/version'
@@ -20,7 +21,6 @@ Gem::Specification.new do |spec|
20
21
  spec.test_files = Dir['spec/**/*.rb']
21
22
  spec.require_paths = ['lib']
22
23
 
23
- spec.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.6'
24
24
  spec.add_runtime_dependency 'faraday', '~> 0.9', '>= 0.9.2'
25
25
  spec.add_runtime_dependency 'faraday_middleware', '~> 0.10', '>= 0.10.0'
26
26
  spec.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.2'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module HashExtensions
3
+ refine Hash do
4
+ # Returns a hash with non +nil+ values.
5
+ #
6
+ # hash = { a: true, b: false, c: nil}
7
+ # hash.compact # => { a: true, b: false}
8
+ # hash # => { a: true, b: false, c: nil}
9
+ # { c: nil }.compact # => {}
10
+ def compact
11
+ select {|_, value| !value.nil? }
12
+ end
13
+
14
+ # Replaces current hash with non +nil+ values.
15
+ #
16
+ # hash = { a: true, b: false, c: nil}
17
+ # hash.compact! # => { a: true, b: false}
18
+ # hash # => { a: true, b: false}
19
+ def compact!
20
+ reject! {|_, value| value.nil? }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ module ObjectExtensions
3
+ refine Object do
4
+ # An object is blank if it's false, empty, or a whitespace string.
5
+ # For example, +false+, '', ' ', +nil+, [], and {} are all blank.
6
+ #
7
+ # This simplifies
8
+ #
9
+ # !address || address.empty?
10
+ #
11
+ # to
12
+ #
13
+ # address.blank?
14
+ #
15
+ # @return [true, false]
16
+ def blank?
17
+ respond_to?(:empty?) ? !!empty? : !self
18
+ end
19
+
20
+ # An object is present if it's not blank.
21
+ #
22
+ # @return [true, false]
23
+ def present?
24
+ !blank?
25
+ end
26
+
27
+ # Returns the receiver if it's present otherwise returns +nil+.
28
+ # <tt>object.presence</tt> is equivalent to
29
+ #
30
+ # object.present? ? object : nil
31
+ #
32
+ # For example, something like
33
+ #
34
+ # state = params[:state] if params[:state].present?
35
+ # country = params[:country] if params[:country].present?
36
+ # region = state || country || 'US'
37
+ #
38
+ # becomes
39
+ #
40
+ # region = params[:state].presence || params[:country].presence || 'US'
41
+ #
42
+ # @return [Object]
43
+ def presence
44
+ self if present?
45
+ end
46
+ end
47
+ end
48
+
49
+ module StringExtensions
50
+ refine String do
51
+ BLANK_RE = /\A[[:space:]]*\z/
52
+
53
+ # A string is blank if it's empty or contains whitespaces only:
54
+ #
55
+ # ''.blank? # => true
56
+ # ' '.blank? # => true
57
+ # "\t\n\r".blank? # => true
58
+ # ' blah '.blank? # => false
59
+ #
60
+ # Unicode whitespace is supported:
61
+ #
62
+ # "\u00a0".blank? # => true
63
+ #
64
+ # @return [true, false]
65
+ def blank?
66
+ match BLANK_RE
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module ObjectExtensions
3
+ refine Object do
4
+ def integer?
5
+ Integer(self)
6
+ rescue
7
+ false
8
+ else
9
+ true
10
+ end
11
+ end
12
+ end
data/lib/finapps.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'finapps/version' unless defined?(FinApps::VERSION)
2
3
 
3
4
  require 'faraday'
@@ -5,15 +6,17 @@ require 'faraday_middleware'
5
6
  require 'typhoeus'
6
7
  require 'typhoeus/adapters/faraday'
7
8
 
8
- require 'active_support/core_ext/hash/compact'
9
- require 'active_support/core_ext/object/blank'
10
- require 'finapps/core_extensions/integerable'
11
- require 'finapps/hash_constructable'
9
+ require 'core_extensions/hash/compact'
10
+ require 'core_extensions/object/blank'
11
+ require 'core_extensions/object/is_integer'
12
12
  require 'finapps/utils/loggeable'
13
13
  require 'finapps/error'
14
14
 
15
- require 'finapps/middleware/tenant_authentication'
16
- require 'finapps/middleware/raise_error'
15
+ require 'finapps/middleware/request/tenant_authentication'
16
+ require 'finapps/middleware/request/accept_json'
17
+ require 'finapps/middleware/request/user_agent'
18
+ require 'finapps/middleware/response/raise_error'
19
+ require 'finapps/middleware/middleware'
17
20
 
18
21
  require 'finapps/rest/defaults'
19
22
  require 'finapps/rest/resources'
@@ -22,6 +25,7 @@ require 'finapps/rest/users'
22
25
  require 'finapps/rest/orders'
23
26
 
24
27
  require 'finapps/rest/configuration'
28
+ require 'finapps/rest/credentials'
25
29
  require 'finapps/rest/connection'
26
30
  require 'finapps/rest/base_client'
27
31
  require 'finapps/rest/client'
data/lib/finapps/error.rb CHANGED
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+ # Defines some errors to identify Exceptions within this gem
1
3
  module FinApps # :nodoc:
4
+ # Base error class.
2
5
  class Error < StandardError; end
6
+ # Raised for existing but invalid arguments.
3
7
  class InvalidArgumentsError < Error; end
8
+ # Raised whenever a required argument is missing.
4
9
  class MissingArgumentsError < Error; end
5
10
 
6
11
  %i(InvalidArgumentsError MissingArgumentsError).each {|const| Error.const_set(const, FinApps.const_get(const)) }
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ require 'faraday' unless defined? Faraday
3
+
4
+ module FinApps
5
+ module Middleware
6
+ autoload :AcceptJson, 'finapps/middleware/request/accept_json'
7
+ autoload :UserAgent, 'finapps/middleware/request/user_agent'
8
+ autoload :TenantAuthentication, 'finapps/middleware/request/tenant_authentication'
9
+
10
+ if Faraday::Middleware.respond_to? :register_middleware
11
+ Faraday::Request.register_middleware \
12
+ accept_json: -> { AcceptJson },
13
+ user_agent: -> { UserAgent },
14
+ tenant_authentication: -> { TenantAuthentication }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module FinApps
3
+ module Middleware
4
+ # This middleware sets the Accept request-header field to specify JSON as acceptable media type for the response.
5
+ class AcceptJson < Faraday::Middleware
6
+ KEY = 'Accept' unless defined? KEY
7
+
8
+ def call(env)
9
+ env[:request_headers][KEY] = 'application/json'
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module Middleware
3
4
  # Adds a custom header for tenant level authorization.
4
5
  # If the value for this header already exists, it is not overriden.
5
6
  class TenantAuthentication < Faraday::Middleware
6
- KEY = 'X-FinApps-Token'.freeze unless defined? KEY
7
+ KEY = 'X-FinApps-Token' unless defined? KEY
7
8
 
8
- def initialize(app, options={})
9
+ def initialize(app, identifier, token)
9
10
  super(app)
10
- @header_value = "#{options[:identifier].to_s.strip}=#{options[:token].to_s.strip}"
11
+ @header_value = "#{identifier.to_s.strip}=#{token.to_s.strip}"
11
12
  end
12
13
 
13
14
  def call(env)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module FinApps
3
+ module Middleware
4
+ # This middleware sets the User-Agent request-header field to identify thei client.
5
+ class UserAgent < Faraday::Middleware
6
+ KEY = 'User-Agent' unless defined? KEY
7
+ RUBY = "#{RUBY_ENGINE}/#{RUBY_PLATFORM} #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
8
+
9
+ def call(env)
10
+ env[:request_headers][KEY] = "finapps-ruby/#{FinApps::VERSION} (#{RUBY})"
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module Middleware
3
4
  class RaiseError < Faraday::Response::Middleware # :nodoc:
5
+ using ObjectExtensions
6
+ using StringExtensions
4
7
  include FinApps::Utils::Loggeable
5
8
 
6
9
  CLIENT_ERROR_STATUSES = 400...600
@@ -31,9 +34,9 @@ module FinApps
31
34
  private
32
35
 
33
36
  def error_messages(body)
34
- return nil unless body.present?
37
+ return nil if body.blank?
35
38
  body = parse_string(body) if body.is_a?(String)
36
- body.is_a?(Hash) ? body['messages'].presence : nil
39
+ body.is_a?(Hash) && body.key?('messages') ? body['messages'] : nil
37
40
  end
38
41
 
39
42
  def parse_string(body)
@@ -1,11 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
- class BaseClient # :nodoc:
4
+ # base client functionality
5
+ class BaseClient
4
6
  include ::FinApps::Utils::Loggeable
7
+ include ::FinApps::REST::Connection
8
+ using ObjectExtensions
9
+ using StringExtensions
5
10
 
6
11
  attr_reader :config
7
12
 
8
- def initialize(options={}, logger=nil)
13
+ def initialize(options, logger=nil)
9
14
  @config = FinApps::REST::Configuration.new options
10
15
  @logger = logger
11
16
  end
@@ -14,7 +19,7 @@ module FinApps
14
19
  #
15
20
  # @return Faraday::Connection.
16
21
  def connection
17
- @connection ||= FinApps::REST::Connection.faraday(config, logger)
22
+ @connection ||= faraday(config, logger)
18
23
  end
19
24
 
20
25
  # Performs HTTP GET, POST, UPDATE and DELETE requests.
@@ -30,11 +35,11 @@ module FinApps
30
35
  raise FinApps::MissingArgumentsError.new 'Missing argument: method.' if method.blank?
31
36
 
32
37
  response, error_messages = execute_request(method, params, path)
33
- result = if response.present?
34
- block_given? ? yield(response) : response.body
35
- else
38
+ result = if response.blank?
36
39
  logger.error "##{__method__} => Null response found. Unable to process it."
37
40
  nil
41
+ else
42
+ block_given? ? yield(response) : response.body
38
43
  end
39
44
 
40
45
  [result, error_messages]
@@ -44,25 +49,36 @@ module FinApps
44
49
 
45
50
  def execute_request(method, params, path)
46
51
  error_messages = []
47
-
48
52
  begin
49
53
  response = execute_method method, params, path
50
54
  rescue FinApps::InvalidArgumentsError,
51
55
  FinApps::MissingArgumentsError,
52
56
  Faraday::Error::ConnectionFailed => error
53
- logger.fatal "##{__method__} => #{error}"
54
- raise error
57
+ handle_error error
55
58
  rescue Faraday::Error::ClientError => error
56
- error_messages = error.response[:error_messages].blank? ? [error.message] : error.response[:error_messages]
57
- logger.error "##{__method__} => Faraday::Error::ClientError, #{error}"
59
+ error_messages = handle_client_error error
58
60
  rescue StandardError => error
59
- error_messages << 'Unexpected error.'
60
- logger.fatal "##{__method__} => StandardError, #{error}"
61
+ error_messages = handle_standard_error error
61
62
  end
62
63
 
63
64
  [response, error_messages]
64
65
  end
65
66
 
67
+ def handle_error(error)
68
+ logger.fatal "#{self.class}##{__method__} => #{error}"
69
+ raise error
70
+ end
71
+
72
+ def handle_client_error(error)
73
+ logger.error "#{self.class}##{__method__} => Faraday::Error::ClientError, #{error}"
74
+ error.response[:error_messages] || [error.message]
75
+ end
76
+
77
+ def handle_standard_error(error)
78
+ logger.error "#{self.class}##{__method__} => StandardError, #{error}"
79
+ ['Unexpected error.']
80
+ end
81
+
66
82
  def execute_method(method, params, path)
67
83
  case method
68
84
  when :get
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  class Client < BaseClient # :nodoc:
5
+ using ObjectExtensions
6
+ using StringExtensions
7
+
4
8
  include FinApps::REST::Defaults
5
9
 
6
10
  # @param [String] tenant_identifier
@@ -11,10 +15,8 @@ module FinApps
11
15
  raise FinApps::MissingArgumentsError.new 'Invalid company_identifier.' if tenant_identifier.blank?
12
16
  raise FinApps::MissingArgumentsError.new 'Invalid company_token.' if tenant_token.blank?
13
17
 
14
- merged_options = FinApps::REST::Defaults::DEFAULTS.merge options
15
- merged_options[:tenant_credentials] = {identifier: tenant_identifier,
16
- token: tenant_token}
17
-
18
+ merged_options = FinApps::REST::Defaults::DEFAULTS.merge(options.merge(tenant_identifier: tenant_identifier,
19
+ tenant_token: tenant_token))
18
20
  super(merged_options, logger)
19
21
  end
20
22
 
@@ -1,51 +1,23 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
4
+ # Represents the client configuration options
3
5
  class Configuration # :nodoc:
4
- include FinApps::HashConstructable
6
+ using ObjectExtensions
7
+ using HashExtensions
5
8
 
6
- using CoreExtensions::Integerable
9
+ attr_accessor :host,
10
+ :tenant_identifier, :tenant_token,
11
+ :user_identifier, :user_token,
12
+ :proxy, :timeout, :retry_limit, :log_level
7
13
 
8
- RUBY = "#{RUBY_ENGINE}/#{RUBY_PLATFORM} #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}".freeze
9
- HEADERS = {
10
- accept: 'application/json',
11
- user_agent: "finapps-ruby/#{FinApps::VERSION} (#{RUBY})"
12
- }.freeze
13
-
14
- attr_accessor :host, :timeout, :tenant_credentials, :user_credentials, :url,
15
- :proxy_addr, :proxy_port, :proxy_user, :proxy_pass,
16
- :retry_limit, :log_level
17
-
18
- def initialize(options)
19
- super(options, FinApps::REST::Defaults::DEFAULTS)
20
- validate
21
- @url = "#{host}/v#{FinApps::REST::Defaults::API_VERSION}/"
22
- end
23
-
24
- def connection_options
25
- {url: url,
26
- request: {open_timeout: timeout, timeout: timeout},
27
- headers: {accept: HEADERS[:accept], user_agent: HEADERS[:user_agent]}}
28
- end
29
-
30
- def valid_user_credentials?
31
- valid_credentials? user_credentials
32
- end
33
-
34
- private
35
-
36
- def validate
37
- raise FinApps::MissingArgumentsError.new 'Missing tenant_credentials.' unless valid_tenant_credentials?
14
+ def initialize(options={})
15
+ FinApps::REST::Defaults::DEFAULTS.merge(options.compact).each {|key, value| public_send("#{key}=", value) }
38
16
  raise FinApps::InvalidArgumentsError.new "Invalid argument. {host: #{host}}" unless valid_host?
39
17
  raise FinApps::InvalidArgumentsError.new "Invalid argument. {timeout: #{timeout}}" unless timeout.integer?
40
18
  end
41
19
 
42
- def valid_tenant_credentials?
43
- valid_credentials? tenant_credentials
44
- end
45
-
46
- def valid_credentials?(h)
47
- h.is_a?(Hash) && %i(identifier token).all? {|x| h.key? x } && h.values.all?(&:present?)
48
- end
20
+ private
49
21
 
50
22
  def valid_host?
51
23
  host.start_with?('http://', 'https://')
@@ -1,31 +1,37 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  module Connection # :nodoc:
4
- module_function
5
-
5
+ # @return [Faraday::Connection]
6
6
  def faraday(config, logger)
7
- Faraday.new(config.connection_options) do |conn|
8
- # tenant level authentication
9
- conn.use FinApps::Middleware::TenantAuthentication, config.tenant_credentials
10
-
11
- # user level authentication
12
- if config.valid_user_credentials?
13
- conn.request :basic_auth, config.user_credentials[:identifier], config.user_credentials[:token]
14
- end
7
+ options = {
8
+ url: "#{config.host}/v#{Defaults::API_VERSION}/",
9
+ request: {open_timeout: config.timeout,
10
+ timeout: config.timeout}
11
+ }
15
12
 
13
+ Faraday.new(options) do |conn|
14
+ conn.request :accept_json
15
+ conn.request :user_agent
16
+ conn.request :tenant_authentication, config.tenant_identifier, config.tenant_token
16
17
  conn.request :json
17
18
  conn.request :retry
18
19
  conn.request :multipart
19
20
  conn.request :url_encoded
21
+ if FinApps::REST::Credentials.new(config.user_identifier, config.user_token).valid?
22
+ conn.request :basic_auth, config.user_identifier, config.user_token
23
+ end
24
+
20
25
  conn.use FinApps::Middleware::RaiseError
21
26
  conn.response :rashify
22
27
  conn.response :json, content_type: /\bjson$/
23
- conn.response :logger, logger # , bodies: true
28
+ conn.response :logger, logger, bodies: true
24
29
 
25
30
  # Adapter (ensure that the adapter is always last.)
26
31
  conn.adapter :typhoeus
27
32
  end
28
33
  end
34
+ module_function :faraday # becomes available as a *private instance method* to classes that mix in the module
29
35
  end
30
36
  end
31
37
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ module FinApps
3
+ module REST
4
+ # represents both tenant and user credentials
5
+ class Credentials
6
+ using ObjectExtensions
7
+ using StringExtensions
8
+
9
+ attr_reader :identifier, :token
10
+
11
+ def initialize(identifier, token)
12
+ @identifier = identifier
13
+ @token = token
14
+ end
15
+
16
+ def valid?
17
+ identifier.present? && token.present?
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,18 +1,18 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  module Defaults
4
- API_VERSION = '2'.freeze
5
+ API_VERSION = '2'
5
6
 
6
7
  # noinspection SpellCheckingInspection
7
8
  DEFAULTS = {
8
- host: 'https://dev.financialapps.com',
9
- timeout: 30,
10
- proxy_addr: nil,
11
- proxy_port: nil,
12
- proxy_user: nil,
13
- proxy_pass: nil,
14
- retry_limit: 1,
15
- log_level: Logger::INFO
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
16
  }.freeze
17
17
 
18
18
  END_POINTS = {
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  class Orders < FinApps::REST::Resources # :nodoc:
5
+ using ObjectExtensions
6
+ using StringExtensions
7
+
4
8
  def show(id)
5
9
  raise MissingArgumentsError.new 'Missing argument: params.' if id.blank?
6
10
  super
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  class Resources # :nodoc:
@@ -8,7 +9,7 @@ module FinApps
8
9
  # @param [FinApps::REST::Client] client
9
10
  # @return [FinApps::REST::Resources]
10
11
  def initialize(client)
11
- raise MissingArgumentsError.new 'Missing argument: client.' if client.blank?
12
+ raise MissingArgumentsError.new 'Missing argument: client.' if client.nil?
12
13
  @client = client
13
14
  end
14
15
 
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module REST
3
4
  class Users < FinApps::REST::Resources # :nodoc:
5
+ using ObjectExtensions
6
+ using StringExtensions
7
+
4
8
  END_POINTS = {
5
9
  list: nil,
6
10
  create: 'users/new',
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
3
  module Utils
3
4
  # Adds logging capabilities when included into other classes
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module FinApps
2
- VERSION = '2.0.6'.freeze
3
+ VERSION = '2.0.10'
3
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  desc 'Bumps the version to the next patch level, tags and pushes the code to
2
3
  origin repository and releases the gem. BOOM!'
3
4
  task :release do
@@ -0,0 +1,12 @@
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,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::Middleware::TenantAuthentication do
2
3
  let(:valid_tenant_options) { VALID_CREDENTIALS }
3
4
  let(:key) { FinApps::Middleware::TenantAuthentication::KEY }
@@ -6,7 +7,11 @@ RSpec.describe FinApps::Middleware::TenantAuthentication do
6
7
  fake_app = proc {|env| env }
7
8
 
8
9
  context 'when company credentials were provided' do
9
- let(:middleware) { FinApps::Middleware::TenantAuthentication.new fake_app, valid_tenant_options }
10
+ let(:middleware) do
11
+ FinApps::Middleware::TenantAuthentication.new(fake_app,
12
+ VALID_CREDENTIALS[:identifier],
13
+ VALID_CREDENTIALS[:token])
14
+ end
10
15
  let(:expected_header) { "#{valid_tenant_options[:identifier]}=#{valid_tenant_options[:token]}" }
11
16
 
12
17
  context 'when header was not previously set' do
@@ -0,0 +1,12 @@
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,5 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::REST::BaseClient do
2
- let(:valid_tenant_options) { {tenant_credentials: VALID_CREDENTIALS} }
3
+ let(:valid_tenant_options) do
4
+ {tenant_identifier: VALID_CREDENTIALS[:identifier],
5
+ tenant_token: VALID_CREDENTIALS[:token]}
6
+ end
3
7
  subject { FinApps::REST::BaseClient.new(valid_tenant_options) }
4
8
 
5
9
  RESPONSE = 0
@@ -54,10 +58,10 @@ RSpec.describe FinApps::REST::BaseClient do
54
58
  context 'for client errors' do
55
59
  subject { FinApps::REST::BaseClient.new(valid_tenant_options).send_request('client_error', :get) }
56
60
 
57
- it('the result should be nil') { expect(subject[RESPONSE]).to be_nil }
58
- it { expect(subject[ERROR_MESSAGES]).not_to be_nil }
59
- it { expect(subject[ERROR_MESSAGES]).to be_a(Array) }
60
- it { expect(subject[ERROR_MESSAGES].length).to be > 0 }
61
+ it('result is null') { expect(subject[RESPONSE]).to be_nil }
62
+ it('error_messages is not null') { expect(subject[ERROR_MESSAGES]).not_to be_nil }
63
+ it('error_messages is an array') { expect(subject[ERROR_MESSAGES]).to be_a(Array) }
64
+ it('error messages array contains elements') { expect(subject[ERROR_MESSAGES].length).to be > 0 }
61
65
  end
62
66
 
63
67
  context 'for server errors' do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::REST::Client do
2
3
  describe '#new' do
3
4
  it 'raises for missing company_identifier' do
@@ -1,74 +1,27 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::REST::Configuration do
2
3
  describe '#new' do
3
- it 'raises for missing tenant credentials' do
4
- expect { FinApps::REST::Configuration.new({}) }
5
- .to raise_error(FinApps::MissingArgumentsError, 'Missing tenant_credentials.')
4
+ context 'for invalid timeout configuration' do
5
+ subject { FinApps::REST::Configuration.new(timeout: 'whatever') }
6
+ it { expect { subject }.to raise_error(FinApps::InvalidArgumentsError, 'Invalid argument. {timeout: whatever}') }
6
7
  end
7
8
 
8
- it 'raises for invalid tenant credentials (identifier)' do
9
- expect { FinApps::REST::Configuration.new(tenant_credentials: {token: :token}) }
10
- .to raise_error(FinApps::MissingArgumentsError, 'Missing tenant_credentials.')
9
+ context 'for missing timeout configuration' do
10
+ subject { FinApps::REST::Configuration.new(timeout: nil) }
11
+ it 'should have a default timeout value' do
12
+ expect(subject.timeout).to eq(FinApps::REST::Defaults::DEFAULTS[:timeout])
13
+ end
11
14
  end
12
15
 
13
- it 'raises for invalid tenant credentials (token)' do
14
- expect { FinApps::REST::Configuration.new(tenant_credentials: {identifier: :identifier}) }
15
- .to raise_error(FinApps::MissingArgumentsError, 'Missing tenant_credentials.')
16
+ context 'for invalid host configuration' do
17
+ subject { FinApps::REST::Configuration.new(host: 'whatever') }
18
+ it { expect { subject }.to raise_error(FinApps::InvalidArgumentsError, 'Invalid argument. {host: whatever}') }
16
19
  end
17
20
 
18
- context 'for valid tenant credentials' do
19
- let(:valid_tenant_options) { {tenant_credentials: VALID_CREDENTIALS} }
20
-
21
- context 'when valid user credentials were provided' do
22
- let(:valid_creds) { valid_tenant_options.merge(user_credentials: VALID_CREDENTIALS) }
23
- subject { FinApps::REST::Configuration.new(valid_creds) }
24
- it('should have user_credentials') { expect(subject.user_credentials).to eq(VALID_CREDENTIALS) }
25
- it('user_credentials are valid') { expect(subject.valid_user_credentials?).to eq true }
26
- end
27
-
28
- context 'for missing user credentials' do
29
- subject { FinApps::REST::Configuration.new(valid_tenant_options) }
30
- it('user_credentials are not valid') { expect(subject.valid_user_credentials?).to eq false }
31
- end
32
-
33
- context 'for invalid user credentials (token)' do
34
- let(:invalid_user_creds) { {identifier: :identifier, token: ''} }
35
- subject { FinApps::REST::Configuration.new(valid_tenant_options.merge(user_credentials: invalid_user_creds)) }
36
-
37
- it('user_credentials are not valid') { expect(subject.valid_user_credentials?).to eq false }
38
- end
39
-
40
- context 'for invalid user credentials (identifier)' do
41
- let(:invalid_user_creds) { {identifier: '', token: :token} }
42
- subject { FinApps::REST::Configuration.new(valid_tenant_options.merge(user_credentials: invalid_user_creds)) }
43
-
44
- it('user_credentials are not valid') { expect(subject.valid_user_credentials?).to eq false }
45
- end
46
-
47
- it 'raises for invalid timeout values' do
48
- expect { FinApps::REST::Configuration.new(valid_tenant_options.merge(timeout: 'whatever')) }
49
- .to raise_error(FinApps::InvalidArgumentsError, 'Invalid argument. {timeout: whatever}')
50
- end
51
-
52
- context 'for valid timeout' do
53
- subject { FinApps::REST::Configuration.new(valid_tenant_options.merge(timeout: nil)) }
54
- it 'should have a default timeout value' do
55
- config = FinApps::REST::Configuration.new(valid_tenant_options.merge(timeout: nil))
56
- expect(config.timeout).to eq(FinApps::REST::Defaults::DEFAULTS[:timeout])
57
- end
58
- end
59
-
60
- it 'raises for invalid host values' do
61
- expect { FinApps::REST::Configuration.new(valid_tenant_options.merge(host: 'whatever')) }
62
- .to raise_error(FinApps::InvalidArgumentsError, 'Invalid argument. {host: whatever}')
63
- end
64
-
65
- context 'for valid host' do
66
- subject { FinApps::REST::Configuration.new(valid_tenant_options.merge(host: nil)) }
67
-
68
- it('should have a default host') { expect(subject.host).to eq(FinApps::REST::Defaults::DEFAULTS[:host]) }
69
- it('url should include version') do
70
- expect(subject.url).to eq("#{subject.host}/v#{FinApps::REST::Defaults::API_VERSION}/")
71
- end
21
+ context 'for missing host configuration' do
22
+ subject { FinApps::REST::Configuration.new(host: nil) }
23
+ it 'should have a default host value' do
24
+ expect(subject.host).to eq(FinApps::REST::Defaults::DEFAULTS[:host])
72
25
  end
73
26
  end
74
27
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ RSpec.describe FinApps::REST::Credentials do
3
+ describe '#valid?' do
4
+ context 'when missing identifier' do
5
+ it { expect(FinApps::REST::Credentials.new(nil, :token).valid?).to eql(false) }
6
+ end
7
+
8
+ context 'when missing token' do
9
+ it { expect(FinApps::REST::Credentials.new(:identifier, nil).valid?).to eql(false) }
10
+ end
11
+
12
+ context 'when missing both identifier and token' do
13
+ it { expect(FinApps::REST::Credentials.new(nil, nil).valid?).to eql(false) }
14
+ end
15
+
16
+ context 'when having identifier and token' do
17
+ it { expect(FinApps::REST::Credentials.new(:identifier, :token).valid?).to eql(true) }
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::REST::Orders do
2
3
  describe '#show' do
3
4
  let(:client) { FinApps::REST::Client.new :company_identifier, :company_token }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe FinApps::REST::Resources do
2
3
  let(:client) { FinApps::REST::Client.new :company_identifier, :company_token }
3
4
  describe '#new' do
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  if ENV['CODECLIMATE_REPO_TOKEN']
2
3
  require 'codeclimate-test-reporter'
3
4
  CodeClimate::TestReporter.start
@@ -29,6 +30,7 @@ RSpec.configure do |config|
29
30
  base_url = "#{FinApps::REST::Defaults::DEFAULTS[:host]}/v#{FinApps::REST::Defaults::API_VERSION}/"
30
31
  stub_request(:any, /#{base_url}/).to_rack(::FakeApi)
31
32
  end
33
+ WebMock.disable_net_connect!(allow: 'codeclimate.com')
32
34
  end
33
35
 
34
36
  VALID_CREDENTIALS = {identifier: '49fb918d-7e71-44dd-7378-58f19606df2a',
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  require 'sinatra/base'
2
3
 
4
+ # the FakeApi class is used to mock API requests while testing.
3
5
  class FakeApi < Sinatra::Base
4
6
  # resource
5
7
  post('/v2/resources') { json_response 201, 'resource.json' }
metadata CHANGED
@@ -1,35 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finapps
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.6
4
+ version: 2.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erich Quintero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-14 00:00:00.000000000 Z
11
+ date: 2016-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '4.2'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 4.2.6
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '4.2'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 4.2.6
33
13
  - !ruby/object:Gem::Dependency
34
14
  name: faraday
35
15
  requirement: !ruby/object:Gem::Requirement
@@ -265,16 +245,21 @@ files:
265
245
  - README.md
266
246
  - Rakefile
267
247
  - finapps.gemspec
248
+ - lib/core_extensions/hash/compact.rb
249
+ - lib/core_extensions/object/blank.rb
250
+ - lib/core_extensions/object/is_integer.rb
268
251
  - lib/finapps.rb
269
- - lib/finapps/core_extensions/integerable.rb
270
252
  - lib/finapps/error.rb
271
- - lib/finapps/hash_constructable.rb
272
- - lib/finapps/middleware/raise_error.rb
273
- - lib/finapps/middleware/tenant_authentication.rb
253
+ - lib/finapps/middleware/middleware.rb
254
+ - lib/finapps/middleware/request/accept_json.rb
255
+ - lib/finapps/middleware/request/tenant_authentication.rb
256
+ - lib/finapps/middleware/request/user_agent.rb
257
+ - lib/finapps/middleware/response/raise_error.rb
274
258
  - lib/finapps/rest/base_client.rb
275
259
  - lib/finapps/rest/client.rb
276
260
  - lib/finapps/rest/configuration.rb
277
261
  - lib/finapps/rest/connection.rb
262
+ - lib/finapps/rest/credentials.rb
278
263
  - lib/finapps/rest/defaults.rb
279
264
  - lib/finapps/rest/orders.rb
280
265
  - lib/finapps/rest/resources.rb
@@ -282,10 +267,13 @@ files:
282
267
  - lib/finapps/utils/loggeable.rb
283
268
  - lib/finapps/version.rb
284
269
  - lib/tasks/releaser.rake
270
+ - spec/middleware/accept_json_spec.rb
285
271
  - spec/middleware/tenant_authentication_spec.rb
272
+ - spec/middleware/user_agent_spec.rb
286
273
  - spec/rest/base_client_spec.rb
287
274
  - spec/rest/client_spec.rb
288
275
  - spec/rest/configuration_spec.rb
276
+ - spec/rest/credentials_spec.rb
289
277
  - spec/rest/orders_spec.rb
290
278
  - spec/rest/resources_spec.rb
291
279
  - spec/spec_helper.rb
@@ -320,16 +308,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
320
308
  version: '0'
321
309
  requirements: []
322
310
  rubyforge_project:
323
- rubygems_version: 2.6.6
311
+ rubygems_version: 2.5.1
324
312
  signing_key:
325
313
  specification_version: 4
326
314
  summary: FinApps REST API ruby client.
327
315
  test_files:
328
- - spec/spec_helper.rb
329
- - spec/support/fake_api.rb
316
+ - spec/middleware/accept_json_spec.rb
330
317
  - spec/middleware/tenant_authentication_spec.rb
331
- - spec/rest/resources_spec.rb
332
- - spec/rest/client_spec.rb
333
- - spec/rest/orders_spec.rb
318
+ - spec/middleware/user_agent_spec.rb
334
319
  - spec/rest/base_client_spec.rb
320
+ - spec/rest/client_spec.rb
335
321
  - spec/rest/configuration_spec.rb
322
+ - spec/rest/credentials_spec.rb
323
+ - spec/rest/orders_spec.rb
324
+ - spec/rest/resources_spec.rb
325
+ - spec/spec_helper.rb
326
+ - spec/support/fake_api.rb
@@ -1,14 +0,0 @@
1
- module CoreExtensions
2
- # adds an integer? method to any object when used in a class
3
- module Integerable
4
- refine Object do
5
- def integer?
6
- Integer(self)
7
- rescue
8
- false
9
- else
10
- true
11
- end
12
- end
13
- end
14
- end
@@ -1,9 +0,0 @@
1
- module FinApps
2
- # when included into any object, allows to initialize public attributes from a hash
3
- module HashConstructable
4
- def initialize(options_hash={}, defaults=nil)
5
- merged_hash = defaults.nil? ? options_hash : defaults.merge(options_hash.compact)
6
- merged_hash.each {|k, v| public_send("#{k}=", v) }
7
- end
8
- end
9
- end