finapps 2.0.6 → 2.0.10

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 (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