ibanity 1.1.1 → 1.7.0

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +27 -0
  3. data/.github/workflows/gem-push.yml +29 -0
  4. data/.gitignore +3 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +33 -0
  7. data/README.md +1 -1
  8. data/ibanity.gemspec +1 -2
  9. data/lib/ibanity.rb +9 -0
  10. data/lib/ibanity/api/base_resource.rb +4 -2
  11. data/lib/ibanity/api/o_auth_resource.rb +6 -0
  12. data/lib/ibanity/api/ponto_connect/account.rb +5 -0
  13. data/lib/ibanity/api/ponto_connect/integration.rb +10 -0
  14. data/lib/ibanity/api/ponto_connect/onboarding_details.rb +10 -0
  15. data/lib/ibanity/api/ponto_connect/sandbox/financial_institution_account.rb +21 -0
  16. data/lib/ibanity/api/ponto_connect/sandbox/financial_institution_transaction.rb +31 -0
  17. data/lib/ibanity/api/ponto_connect/token.rb +27 -10
  18. data/lib/ibanity/api/ponto_connect/usage.rb +10 -0
  19. data/lib/ibanity/api/ponto_connect/user_info.rb +10 -0
  20. data/lib/ibanity/api/xs2a/bulk_payment_initiation_request.rb +33 -0
  21. data/lib/ibanity/api/xs2a/financial_institution_country.rb +10 -0
  22. data/lib/ibanity/api/xs2a/periodic_payment_initiation_request.rb +33 -0
  23. data/lib/ibanity/collection.rb +10 -0
  24. data/lib/ibanity/http_signature.rb +24 -19
  25. data/lib/ibanity/util.rb +11 -4
  26. data/lib/ibanity/version.rb +1 -1
  27. data/spec/lib/ibanity/http_signature_spec.rb +39 -0
  28. data/spec/lib/ibanity/util_spec.rb +89 -0
  29. data/spec/spec_helper.rb +102 -0
  30. data/spec/support/crypto_helper.rb +21 -0
  31. data/spec/support/fixtures/signature/test-certificate.pem +21 -0
  32. data/spec/support/fixtures/signature/test-private_key.pem +28 -0
  33. data/spec/support/fixtures/signature/test-public_key.pem +9 -0
  34. metadata +32 -22
  35. data/.travis.yml +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58760dd2b572c44765101af4d96b7549a8af0403d161690c43e6ca61630f3903
4
- data.tar.gz: 6d12cec2d46f49470c7e5a30d381bd4d1685e74d65407c1cfd47c059efeb7c25
3
+ metadata.gz: c7fd6f89318c851b7400543ff611a42ae6212bd62ce5073422d1bd36c822369a
4
+ data.tar.gz: c8fe8aaf323a55636815cd8c6669192005eb358fc396bb9e0528add3790ba3e3
5
5
  SHA512:
6
- metadata.gz: fe4f9a8a9a267d188a6e8276d55d3775f4873007c04bd3e9974db9622b17192c9e03047bf35828932cf7c0d0ca33dd1fa97305d4b47ea0d1701e2c79cb8c9fc8
7
- data.tar.gz: 481aa49242a63f94a2a4494bd4f645cbb891b129260bfe10b334585cd283e2cbdb0d7d8ea439495eb914ef43e0e88e84f127788544e84496705b7321bcd9da75
6
+ metadata.gz: 4190b626cf11725cd578cf7865307eb65610bf98e4c6c89f47e3559a679d8e07be9423b0dc44263c23b07361f6d050b0fface497077c26dfa30cd41c39dcfa06
7
+ data.tar.gz: 19e030f8f098906171c1784c88b25a58e51f486b15c8cdad4e8ca61ddba81b18d83684478c6e77681d4f28c287762f256228c24876261fe924d5af4f025dd364
@@ -0,0 +1,27 @@
1
+ name: Ruby CI
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - name: Set up Ruby
12
+ uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: 2.6
15
+ - name: Install dependencies
16
+ run: bundle install
17
+ - name: Run tests
18
+ run: bundle exec rspec
19
+ - name: Notify slack failure on master branch
20
+ if: contains(github.ref, 'master') && failure()
21
+ env:
22
+ SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
23
+ uses: voxmedia/github-action-slack-notify-build@v1.1.2
24
+ with:
25
+ channel: ibanity-support-tech
26
+ status: FAILED
27
+ color: danger
@@ -0,0 +1,29 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ release:
5
+ types: [created]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build + Publish
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - name: Set up Ruby 2.6
15
+ uses: actions/setup-ruby@v1
16
+ with:
17
+ ruby-version: 2.6
18
+
19
+ - name: Publish to RubyGems
20
+ run: |
21
+ mkdir -p $HOME/.gem
22
+ touch $HOME/.gem/credentials
23
+ chmod 0600 $HOME/.gem/credentials
24
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
25
+ gem build *.gemspec
26
+ gem push *.gem
27
+ rm -rf $HOME/.gem/credentials
28
+ env:
29
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/.gitignore CHANGED
@@ -16,3 +16,6 @@ mkmf.log
16
16
  .ruby*
17
17
  *.gem
18
18
  *.env
19
+ /.idea
20
+ /bin
21
+ .rakeTasks
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/CHANGELOG.md CHANGED
@@ -1,4 +1,37 @@
1
1
  # Changelog
2
+ ## 1.7
3
+ ### Enhancements
4
+
5
+ * [Ponto Connect] Add support for the /onboarding-details endpoint.
6
+
7
+ ## 1.6
8
+ ### Enhancements
9
+
10
+ * [Ponto Connect] Added a new revoke account endpoint. It allows to remove an account from your integration. (The bank account will not be deleted from the Ponto account itself).
11
+
12
+ * [Ponto Connect] Added a new delete organization integration endpoint. It provides an alternative method to revoke the integration (in addition to the revoke refresh token endpoint). This endpoint remains accessible with a client access token, even if your refresh token is lost or expired.
13
+
14
+ ## 1.5
15
+
16
+ * Proper release of previous enhancements
17
+
18
+ ## 1.4
19
+
20
+ *Don't use this version as it was not properly released !*
21
+
22
+ ## 1.3
23
+
24
+ ### Enhancements
25
+
26
+ * [Ponto Connect] Add support for the /userinfo and /organizations/{id}/usage endpoints.
27
+
28
+ ## 1.2
29
+
30
+ ### Enhancements
31
+
32
+ * Default signature algorithm is now ["hs2019"](https://tools.ietf.org/html/draft-cavage-http-signatures-12#appendix-E.2)
33
+ * Add support for periodic and bulk payments
34
+ * Add snake-case transformation for deeply nested data structures
2
35
 
3
36
  ## 1.1.1
4
37
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/ibanity/ibanity-ruby.svg?branch=master)](https://travis-ci.org/ibanity/ibanity-ruby)
1
+ ![Ruby CI](https://github.com/ibanity/ibanity-ruby/workflows/Ruby%20CI/badge.svg?branch=master)
2
2
 
3
3
  # Ibanity Ruby Library
4
4
 
data/ibanity.gemspec CHANGED
@@ -19,6 +19,5 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "rest-client", ">= 1.8.0"
22
- spec.add_development_dependency "rspec", "3.4.0"
23
- spec.add_development_dependency "webmock", "1.24.2"
22
+ spec.add_development_dependency "rspec", "3.9.0"
24
23
  end
data/lib/ibanity.rb CHANGED
@@ -15,12 +15,15 @@ require_relative "ibanity/api/xs2a/account"
15
15
  require_relative "ibanity/api/xs2a/transaction"
16
16
  require_relative "ibanity/api/xs2a/holding"
17
17
  require_relative "ibanity/api/xs2a/financial_institution"
18
+ require_relative "ibanity/api/xs2a/financial_institution_country"
18
19
  require_relative "ibanity/api/xs2a/account_information_access_request"
19
20
  require_relative "ibanity/api/xs2a/account_information_access_request_authorization"
20
21
  require_relative "ibanity/api/xs2a/payment_initiation_request_authorization"
21
22
  require_relative "ibanity/api/xs2a/customer_access_token"
22
23
  require_relative "ibanity/api/xs2a/customer"
23
24
  require_relative "ibanity/api/xs2a/payment_initiation_request"
25
+ require_relative "ibanity/api/xs2a/bulk_payment_initiation_request"
26
+ require_relative "ibanity/api/xs2a/periodic_payment_initiation_request"
24
27
  require_relative "ibanity/api/xs2a/synchronization"
25
28
  require_relative "ibanity/api/o_auth_resource"
26
29
  require_relative "ibanity/api/isabel_connect/account"
@@ -43,6 +46,12 @@ require_relative "ibanity/api/ponto_connect/synchronization"
43
46
  require_relative "ibanity/api/consent/consent"
44
47
  require_relative "ibanity/api/consent/processing_operation"
45
48
  require_relative "ibanity/api/ponto_connect/payment"
49
+ require_relative "ibanity/api/ponto_connect/user_info"
50
+ require_relative "ibanity/api/ponto_connect/usage"
51
+ require_relative "ibanity/api/ponto_connect/integration"
52
+ require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_account"
53
+ require_relative "ibanity/api/ponto_connect/sandbox/financial_institution_transaction"
54
+ require_relative "ibanity/api/ponto_connect/onboarding_details"
46
55
 
47
56
  module Ibanity
48
57
  class << self
@@ -92,18 +92,20 @@ module Ibanity
92
92
  attributes = raw["attributes"] || {}
93
93
  meta = raw["meta"] || {}
94
94
  params = base.merge(attributes).merge(meta)
95
- Ibanity::Util.underscorize_hash(params)
95
+ Ibanity::Util.underscorize(params)
96
96
  end
97
97
 
98
98
  def setup_relationships(relationships, customer_access_token = nil)
99
99
  relationships.each do |key, relationship|
100
100
  if relationship["data"]
101
+ self[Ibanity::Util.underscore("#{key}_id")] = relationship["data"]["id"]
102
+ return unless relationship.dig("links", "related")
103
+
101
104
  klass = relationship_klass(key)
102
105
  method_name = Ibanity::Util.underscore(key)
103
106
  define_singleton_method(method_name) do |headers: nil|
104
107
  klass.find_by_uri(uri: relationship["links"]["related"], headers: headers, customer_access_token: customer_access_token)
105
108
  end
106
- self[Ibanity::Util.underscore("#{key}_id")] = relationship["data"]["id"]
107
109
  else
108
110
  singular_key = key[0..-2]
109
111
  klass = relationship_klass(singular_key)
@@ -6,6 +6,12 @@ module Ibanity
6
6
  new(raw_item)
7
7
  end
8
8
 
9
+ def self.find_by_uri(uri:, customer_access_token: nil, headers: nil)
10
+ raw_item = Ibanity.client.get(uri: uri, customer_access_token: customer_access_token, headers: headers)
11
+ raw_item = {} if raw_item == ""
12
+ new(raw_item)
13
+ end
14
+
9
15
  def initialize(raw)
10
16
  super(raw)
11
17
  end
@@ -10,6 +10,11 @@ module Ibanity
10
10
  uri = Ibanity.ponto_connect_api_schema["accounts"].sub("{accountId}", id)
11
11
  find_by_uri(uri: uri, customer_access_token: access_token)
12
12
  end
13
+
14
+ def self.delete(access_token:, id:)
15
+ uri = Ibanity.ponto_connect_api_schema["accounts"].sub("{accountId}", id)
16
+ destroy_by_uri(uri: uri, customer_access_token: access_token)
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -0,0 +1,10 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ class Integration < Ibanity::BaseResource
4
+ def self.delete(client_access_token:, organization_id:)
5
+ uri = Ibanity.ponto_connect_api_schema["organizations"]["integration"].sub("{organizationId}", organization_id)
6
+ destroy_by_uri(uri: uri, customer_access_token: client_access_token)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ class OnboardingDetails < Ibanity::BaseResource
4
+ def self.create(client_access_token:, **attributes)
5
+ uri = Ibanity.ponto_connect_api_schema["onboardingDetails"]
6
+ create_by_uri(uri: uri, resource_type: "onboardingDetails", attributes: attributes, customer_access_token: client_access_token)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ module Sandbox
4
+ class FinancialInstitutionAccount < Ibanity::BaseResource
5
+ def self.list(access_token:, financial_institution_id:, **query_params)
6
+ uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccounts"]
7
+ .gsub("{financialInstitutionId}", financial_institution_id)
8
+ .gsub("{financialInstitutionAccountId}", "")
9
+ list_by_uri(uri: uri, query_params: query_params, customer_access_token: access_token)
10
+ end
11
+
12
+ def self.find(access_token:, id:, financial_institution_id:)
13
+ uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccounts"]
14
+ .gsub("{financialInstitutionId}", financial_institution_id)
15
+ .gsub("{financialInstitutionAccountId}", id)
16
+ find_by_uri(uri: uri, customer_access_token: access_token)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ module Sandbox
4
+ class FinancialInstitutionTransaction < Ibanity::BaseResource
5
+ def self.list(access_token:, financial_institution_account_id:, financial_institution_id:, **query_params)
6
+ uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
7
+ .gsub("{financialInstitutionId}", financial_institution_id)
8
+ .gsub("{financialInstitutionAccountId}", financial_institution_account_id)
9
+ .gsub("{financialInstitutionTransactionId}", "")
10
+ list_by_uri(uri: uri, query_params: query_params, customer_access_token: access_token)
11
+ end
12
+
13
+ def self.find(access_token:, id:, financial_institution_id:, financial_institution_account_id:)
14
+ uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
15
+ .gsub("{financialInstitutionId}", financial_institution_id)
16
+ .gsub("{financialInstitutionAccountId}", financial_institution_account_id)
17
+ .gsub("{financialInstitutionTransactionId}", id)
18
+ find_by_uri(uri: uri, customer_access_token: access_token)
19
+ end
20
+
21
+ def self.create(access_token:, financial_institution_id:, financial_institution_account_id:, **attributes)
22
+ uri = Ibanity.ponto_connect_api_schema["sandbox"]["financialInstitution"]["financialInstitutionAccount"]["financialInstitutionTransactions"]
23
+ .sub("{financialInstitutionId}", financial_institution_id)
24
+ .sub("{financialInstitutionAccountId}", financial_institution_account_id)
25
+ .sub("{financialInstitutionTransactionId}", "")
26
+ create_by_uri(uri: uri, resource_type: "financialInstitutionTransaction", attributes: attributes, customer_access_token: access_token)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -2,16 +2,33 @@ module Ibanity
2
2
  module PontoConnect
3
3
  class Token < Ibanity::OAuthResource
4
4
  def self.create(refresh_token: nil, authorization_code: nil, redirect_uri: nil, idempotency_key: nil, code_verifier: nil)
5
- uri = Ibanity.ponto_connect_api_schema["oauth2"]["token"]
6
- grant_type = refresh_token ? "refresh_token" : "authorization_code"
7
- arguments = [
8
- ["grant_type", grant_type],
9
- ["client_id", Ibanity.client.ponto_connect_client_id]
10
- ]
11
- arguments << ["code", authorization_code] << ["code_verifier", code_verifier] << ["redirect_uri", redirect_uri] if authorization_code
12
- arguments << ["refresh_token", refresh_token] if refresh_token
13
- payload = URI.encode_www_form(arguments)
14
- create_by_uri(uri: uri, payload: payload, idempotency_key: idempotency_key, headers: self.headers)
5
+ arguments =
6
+ if refresh_token
7
+ [
8
+ ["grant_type", "refresh_token"],
9
+ ["client_id", Ibanity.client.ponto_connect_client_id],
10
+ ["refresh_token", refresh_token]
11
+ ]
12
+ elsif authorization_code
13
+ [
14
+ ["grant_type", "authorization_code"],
15
+ ["client_id", Ibanity.client.ponto_connect_client_id],
16
+ ["code", authorization_code],
17
+ ["code_verifier", code_verifier],
18
+ ["redirect_uri", redirect_uri]
19
+ ]
20
+ else
21
+ [
22
+ ["grant_type", "client_credentials"]
23
+ ]
24
+ end
25
+
26
+ create_by_uri(
27
+ uri: Ibanity.ponto_connect_api_schema["oauth2"]["token"],
28
+ payload: URI.encode_www_form(arguments),
29
+ idempotency_key: idempotency_key,
30
+ headers: self.headers
31
+ )
15
32
  end
16
33
 
17
34
  def self.delete(refresh_token:)
@@ -0,0 +1,10 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ class Usage < Ibanity::BaseResource
4
+ def self.find(client_access_token:, organization_id:, month:)
5
+ uri = Ibanity.ponto_connect_api_schema["organizations"]["usage"].sub("{organizationId}", organization_id).sub("{month}", month)
6
+ find_by_uri(uri: uri, customer_access_token: client_access_token)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Ibanity
2
+ module PontoConnect
3
+ class UserInfo < Ibanity::OAuthResource
4
+ def self.find(access_token:)
5
+ uri = Ibanity.ponto_connect_api_schema["userinfo"]
6
+ find_by_uri(uri: uri, customer_access_token: access_token)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module Ibanity
2
+ module Xs2a
3
+ class BulkPaymentInitiationRequest < Ibanity::BaseResource
4
+ def self.create_for_financial_institution(financial_institution_id:, customer_access_token:, idempotency_key: nil, **attributes)
5
+ path = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["bulkPaymentInitiationRequests"]
6
+ .gsub("{financialInstitutionId}", financial_institution_id)
7
+ .sub("{paymentInitiationRequestId}", "")
8
+ uri = Ibanity.client.build_uri(path)
9
+ create_by_uri(
10
+ uri: uri,
11
+ resource_type: "bulkPaymentInitiationRequest",
12
+ attributes: attributes,
13
+ customer_access_token: customer_access_token,
14
+ idempotency_key: idempotency_key
15
+ )
16
+ end
17
+
18
+ def self.find(id:, financial_institution_id:, customer_access_token:)
19
+ uri = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["bulkPaymentInitiationRequests"]
20
+ .gsub("{financialInstitutionId}", financial_institution_id)
21
+ .sub("{paymentInitiationRequestId}", id)
22
+ find_by_uri(uri: uri, customer_access_token: customer_access_token)
23
+ end
24
+
25
+ def self.delete(id:, financial_institution_id:, customer_access_token:)
26
+ uri = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["bulkPaymentInitiationRequests"]
27
+ .gsub("{financialInstitutionId}", financial_institution_id)
28
+ .sub("{paymentInitiationRequestId}", id)
29
+ destroy_by_uri(uri: uri, customer_access_token: customer_access_token)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ module Ibanity
2
+ module Xs2a
3
+ class FinancialInstitutionCountry < Ibanity::BaseResource
4
+ def self.list(**query_params)
5
+ uri = Ibanity.xs2a_api_schema["financialInstitutionCountries"]
6
+ list_by_uri(uri: uri, query_params: query_params)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module Ibanity
2
+ module Xs2a
3
+ class PeriodicPaymentInitiationRequest < Ibanity::BaseResource
4
+ def self.create_for_financial_institution(financial_institution_id:, customer_access_token:, idempotency_key: nil, **attributes)
5
+ path = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["periodicPaymentInitiationRequests"]
6
+ .gsub("{financialInstitutionId}", financial_institution_id)
7
+ .sub("{paymentInitiationRequestId}", "")
8
+ uri = Ibanity.client.build_uri(path)
9
+ create_by_uri(
10
+ uri: uri,
11
+ resource_type: "periodicPaymentInitiationRequest",
12
+ attributes: attributes,
13
+ customer_access_token: customer_access_token,
14
+ idempotency_key: idempotency_key
15
+ )
16
+ end
17
+
18
+ def self.find(id:, financial_institution_id:, customer_access_token:)
19
+ uri = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["periodicPaymentInitiationRequests"]
20
+ .gsub("{financialInstitutionId}", financial_institution_id)
21
+ .sub("{paymentInitiationRequestId}", id)
22
+ find_by_uri(uri: uri, customer_access_token: customer_access_token)
23
+ end
24
+
25
+ def self.delete(id:, financial_institution_id:, customer_access_token:)
26
+ uri = Ibanity.xs2a_api_schema["customer"]["financialInstitution"]["periodicPaymentInitiationRequests"]
27
+ .gsub("{financialInstitutionId}", financial_institution_id)
28
+ .sub("{paymentInitiationRequestId}", id)
29
+ destroy_by_uri(uri: uri, customer_access_token: customer_access_token)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,10 @@
1
1
  module Ibanity
2
2
  class Collection < DelegateClass(Array)
3
3
  attr_accessor :page_limit,
4
+ :page_number,
5
+ :page_size,
6
+ :total_entries,
7
+ :total_pages,
4
8
  :before_cursor,
5
9
  :after_cursor,
6
10
  :offset,
@@ -8,6 +12,7 @@ module Ibanity
8
12
  :first_link,
9
13
  :next_link,
10
14
  :previous_link,
15
+ :last_link,
11
16
  :latest_synchronization,
12
17
  :synchronized_at
13
18
 
@@ -23,6 +28,10 @@ module Ibanity
23
28
  links ||= {}
24
29
  @klass = klass
25
30
  @page_limit = paging["limit"]
31
+ @page_number = paging["pageNumber"]
32
+ @page_size = paging["pageSize"]
33
+ @total_entries = paging["totalEntries"]
34
+ @total_pages = paging["totalPages"]
26
35
  @before_cursor = paging["before"]
27
36
  @after_cursor = paging["after"]
28
37
  @offset = paging["offset"]
@@ -30,6 +39,7 @@ module Ibanity
30
39
  @first_link = links["first"]
31
40
  @next_link = links["next"]
32
41
  @previous_link = links["prev"]
42
+ @last_link = links["last"]
33
43
  @synchronized_at = synchronized_at
34
44
  @latest_synchronization = latest_synchronization
35
45
  super(items)
@@ -2,6 +2,9 @@ require "base64"
2
2
 
3
3
  module Ibanity
4
4
  class HttpSignature
5
+ PSS_DIGEST_ALGORITHM = "SHA256"
6
+ SIGNATURE_ALGORITHM = "hs2019"
7
+
5
8
  def initialize(certificate:, certificate_id:, key:, method:, uri:, query_params:, headers:, payload:)
6
9
  @certificate = certificate
7
10
  @certificate_id = certificate_id
@@ -13,6 +16,21 @@ module Ibanity
13
16
  @query_params = query_params
14
17
  end
15
18
 
19
+ def signature_headers
20
+ {
21
+ "Digest" => payload_digest,
22
+ "Signature" => [
23
+ %(keyId="#{@certificate_id}"),
24
+ %(created="#{date}"),
25
+ %(algorithm="#{SIGNATURE_ALGORITHM}"),
26
+ %(headers="#{headers_to_sign.join(" ")}"),
27
+ %(signature="#{base64_signature}"),
28
+ ].join(",")
29
+ }
30
+ end
31
+
32
+ private
33
+
16
34
  def payload_digest
17
35
  digest = OpenSSL::Digest::SHA512.new
18
36
  string_payload = @payload.nil? ? "" : @payload
@@ -21,12 +39,8 @@ module Ibanity
21
39
  "SHA-512=#{base64}"
22
40
  end
23
41
 
24
- def signature_algorithm
25
- @certificate.signature_algorithm.match("sha256") ? "rsa-sha256" : "rsa-sha512"
26
- end
27
-
28
42
  def headers_to_sign
29
- result = ["(request-target)", "host", "digest", "date"]
43
+ result = ["(request-target)", "host", "digest", "(created)"]
30
44
  result << "authorization" unless @headers["Authorization"].nil?
31
45
  @headers.keys.each do |header|
32
46
  result << header.to_s.downcase if header.to_s.match(/ibanity/i)
@@ -35,13 +49,12 @@ module Ibanity
35
49
  end
36
50
 
37
51
  def request_target
38
- @uri.query = URI.encode_www_form(URI.decode_www_form(@uri.query.to_s).concat(@query_params.to_a)) if @query_params&.keys&.any?
52
+ @uri.query = RestClient::Utils.encode_query_string(@query_params) if @query_params&.keys&.any?
39
53
  "#{@method} #{@uri.request_uri}"
40
54
  end
41
55
 
42
56
  def base64_signature
43
- digest = signature_algorithm == "rsa-sha256" ? OpenSSL::Digest::SHA256.new : OpenSSL::Digest::SHA512.new
44
- signature = @key.sign(digest, signing_string)
57
+ signature = @key.sign_pss(PSS_DIGEST_ALGORITHM, signing_string, salt_length: :digest, mgf1_hash: PSS_DIGEST_ALGORITHM)
45
58
  Base64.urlsafe_encode64(signature)
46
59
  end
47
60
 
@@ -50,13 +63,13 @@ module Ibanity
50
63
  end
51
64
 
52
65
  def date
53
- @date ||= Time.now.utc.iso8601
66
+ @date ||= Time.now.to_i
54
67
  end
55
68
 
56
69
  def signing_string
57
70
  result = []
58
71
  headers_to_sign.each do |header_to_sign|
59
- value = header_value(header_to_sign)
72
+ value = header_value(header_to_sign)
60
73
  result << "#{header_to_sign}: #{value}"
61
74
  end
62
75
  result.join("\n")
@@ -70,20 +83,12 @@ module Ibanity
70
83
  host
71
84
  when "digest"
72
85
  payload_digest
73
- when "date"
86
+ when "(created)"
74
87
  date
75
88
  else
76
89
  camelized_header = header.split("-").collect(&:capitalize).join("-")
77
90
  @headers[camelized_header]
78
91
  end
79
92
  end
80
-
81
- def signature_headers
82
- {
83
- "Date" => date,
84
- "Digest" => payload_digest,
85
- "Signature" => "keyId=\"#{@certificate_id}\" algorithm=\"#{signature_algorithm}\" headers=\"#{headers_to_sign.join(" ")}\" signature=\"#{base64_signature}\""
86
- }
87
- end
88
93
  end
89
94
  end
data/lib/ibanity/util.rb CHANGED
@@ -1,9 +1,16 @@
1
1
  module Ibanity
2
2
  module Util
3
- def self.underscorize_hash(attributes)
4
- attributes.keys.reduce({}) do |result, key|
5
- result[underscore(key)] = attributes[key]
6
- result
3
+ def self.underscorize(obj)
4
+ case obj
5
+ when Array
6
+ obj.map { |e| underscorize(e) }
7
+ when Hash
8
+ obj.keys.reduce({}) do |result, key|
9
+ result[underscore(key)] = underscorize(obj[key])
10
+ result
11
+ end
12
+ else
13
+ obj
7
14
  end
8
15
  end
9
16
 
@@ -1,3 +1,3 @@
1
1
  module Ibanity
2
- VERSION = "1.1.1"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -0,0 +1,39 @@
1
+ require "ibanity/http_signature"
2
+
3
+ RSpec.describe Ibanity::HttpSignature do
4
+
5
+ describe ".signature_headers" do
6
+ let(:signature) do
7
+ Ibanity::HttpSignature.new(
8
+ certificate: CryptoHelper.load_certificate("test"),
9
+ certificate_id: "ec0c29ef-3b39-4b6f-93ff-866bed032399",
10
+ key: CryptoHelper.load_private_key("test"),
11
+ method: "post",
12
+ uri: "https://api.ibanity.com/xs2a/customer-access-tokens",
13
+ headers: {"ibanity-idempotency-key" => "cf17b515-5f6f-4213-a8fe-e4cd40653d00"},
14
+ payload: "{\"foo\": \"bar\"}",
15
+ query_params: {}
16
+ )
17
+ end
18
+
19
+ let(:parts_regex) do
20
+ /keyId="(?<keyId>.*)",\s?created="(?<created>.*)?",?\s?algorithm="(?<algorithm>.*)",\s?headers="(?<headers>.*)",?\s?signature="(?<signature>.*)"/
21
+ end
22
+
23
+ let(:signature_parts) do
24
+ signature.signature_headers["Signature"].match(parts_regex).named_captures
25
+ end
26
+
27
+ ["Digest", "Signature"].each do |header|
28
+ it "contains the '#{header}' header" do
29
+ expect(signature.signature_headers).to include(header)
30
+ end
31
+ end
32
+
33
+ ["keyId", "algorithm", "headers", "signature", "created"].each do |part|
34
+ it "has a signature containing the part '#{part}'" do
35
+ expect(signature_parts).to include(part)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ require 'ibanity/util'
2
+
3
+ RSpec.describe Ibanity::Util do
4
+ describe ".underscorize" do
5
+ it "transforms all keys to snake_case" do
6
+ hash = {
7
+ "currency" => "EUR",
8
+ "amount" => 1,
9
+ "debtorName" => "Sophie Schowalter",
10
+ "debtorAccountReference" => "BE59823362319793",
11
+ }
12
+
13
+ expected = {
14
+ "currency" => "EUR",
15
+ "amount" => 1,
16
+ "debtor_name" => "Sophie Schowalter",
17
+ "debtor_account_reference" => "BE59823362319793",
18
+ }
19
+
20
+ expect(Ibanity::Util.underscorize(hash)).to eq(expected)
21
+ end
22
+
23
+ it "processes hashes recursively" do
24
+ hash = {
25
+ "currency" => "EUR",
26
+ "amount" => 1,
27
+ "debtorName" => "Sophie Schowalter",
28
+ "details" => {
29
+ "debtorAccountReference" => "BE59823362319793"
30
+ }
31
+ }
32
+
33
+ expected = {
34
+ "currency" => "EUR",
35
+ "amount" => 1,
36
+ "debtor_name" => "Sophie Schowalter",
37
+ "details" => {
38
+ "debtor_account_reference" => "BE59823362319793"
39
+ }
40
+ }
41
+
42
+ expect(Ibanity::Util.underscorize(hash)).to eq(expected)
43
+ end
44
+
45
+ it "processes each array element" do
46
+ hash = {
47
+ "currency" => "EUR",
48
+ "amount" => 1,
49
+ "debtorName" => "Sophie Schowalter",
50
+ "details" => [
51
+ {"debtorAccountReference" => "BE59823362319793"}
52
+ ]
53
+ }
54
+
55
+ expected = {
56
+ "currency" => "EUR",
57
+ "amount" => 1,
58
+ "debtor_name" => "Sophie Schowalter",
59
+ "details" => [
60
+ {"debtor_account_reference" => "BE59823362319793"}
61
+ ]
62
+ }
63
+
64
+ expect(Ibanity::Util.underscorize(hash)).to eq(expected)
65
+ end
66
+
67
+ it "leaves arrays elements untouched if they are not themselves hashes or arrays" do
68
+ hash = {
69
+ "currency" => "EUR",
70
+ "amount" => 1,
71
+ "debtorName" => "Sophie Schowalter",
72
+ "details" => [
73
+ "BE59823362319793"
74
+ ]
75
+ }
76
+
77
+ expected = {
78
+ "currency" => "EUR",
79
+ "amount" => 1,
80
+ "debtor_name" => "Sophie Schowalter",
81
+ "details" => [
82
+ "BE59823362319793"
83
+ ]
84
+ }
85
+
86
+ expect(Ibanity::Util.underscorize(hash)).to eq(expected)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,102 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
17
+
18
+ RSpec.configure do |config|
19
+ # rspec-expectations config goes here. You can use an alternate
20
+ # assertion/expectation library such as wrong or the stdlib/minitest
21
+ # assertions if you prefer.
22
+ config.expect_with :rspec do |expectations|
23
+ # This option will default to `true` in RSpec 4. It makes the `description`
24
+ # and `failure_message` of custom matchers include text for helper methods
25
+ # defined using `chain`, e.g.:
26
+ # be_bigger_than(2).and_smaller_than(4).description
27
+ # # => "be bigger than 2 and smaller than 4"
28
+ # ...rather than:
29
+ # # => "be bigger than 2"
30
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
31
+ end
32
+
33
+ # rspec-mocks config goes here. You can use an alternate test double
34
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
35
+ config.mock_with :rspec do |mocks|
36
+ # Prevents you from mocking or stubbing a method that does not exist on
37
+ # a real object. This is generally recommended, and will default to
38
+ # `true` in RSpec 4.
39
+ mocks.verify_partial_doubles = true
40
+ end
41
+
42
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
43
+ # have no way to turn it off -- the option exists only for backwards
44
+ # compatibility in RSpec 3). It causes shared context metadata to be
45
+ # inherited by the metadata hash of host groups and examples, rather than
46
+ # triggering implicit auto-inclusion in groups with matching metadata.
47
+ config.shared_context_metadata_behavior = :apply_to_host_groups
48
+
49
+ # The settings below are suggested to provide a good initial experience
50
+ # with RSpec, but feel free to customize to your heart's content.
51
+ =begin
52
+ # This allows you to limit a spec run to individual examples or groups
53
+ # you care about by tagging them with `:focus` metadata. When nothing
54
+ # is tagged with `:focus`, all examples get run. RSpec also provides
55
+ # aliases for `it`, `describe`, and `context` that include `:focus`
56
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
57
+ config.filter_run_when_matching :focus
58
+
59
+ # Allows RSpec to persist some state between runs in order to support
60
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
61
+ # you configure your source control system to ignore this file.
62
+ config.example_status_persistence_file_path = "spec/examples.txt"
63
+
64
+ # Limits the available syntax to the non-monkey patched syntax that is
65
+ # recommended. For more details, see:
66
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
67
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
68
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
69
+ config.disable_monkey_patching!
70
+
71
+ # This setting enables warnings. It's recommended, but in some cases may
72
+ # be too noisy due to issues in dependencies.
73
+ config.warnings = true
74
+
75
+ # Many RSpec users commonly either run the entire suite or an individual
76
+ # file, and it's useful to allow more verbose output when running an
77
+ # individual spec file.
78
+ if config.files_to_run.one?
79
+ # Use the documentation formatter for detailed output,
80
+ # unless a formatter has already been configured
81
+ # (e.g. via a command-line flag).
82
+ config.default_formatter = "doc"
83
+ end
84
+
85
+ # Print the 10 slowest examples and example groups at the
86
+ # end of the spec run, to help surface which specs are running
87
+ # particularly slow.
88
+ config.profile_examples = 10
89
+
90
+ # Run specs in random order to surface order dependencies. If you find an
91
+ # order dependency and want to debug it, you can fix the order by providing
92
+ # the seed, which is printed after each run.
93
+ # --seed 1234
94
+ config.order = :random
95
+
96
+ # Seed global randomization in this process using the `--seed` CLI option.
97
+ # Setting this allows you to use `--seed` to deterministically reproduce
98
+ # test failures related to randomization by passing the same `--seed` value
99
+ # as the one that triggered the failure.
100
+ Kernel.srand config.seed
101
+ =end
102
+ end
@@ -0,0 +1,21 @@
1
+ require "pathname"
2
+ require "openssl"
3
+
4
+ module CryptoHelper
5
+ FIXTURE_DIRECTORY = Pathname.getwd().join("spec", "support", "fixtures", "signature")
6
+
7
+ def self.load_certificate(name)
8
+ pem = File.read(FIXTURE_DIRECTORY.join("#{name}-certificate.pem"))
9
+ ::OpenSSL::X509::Certificate.new(pem)
10
+ end
11
+
12
+ def self.load_public_key(name)
13
+ pem = File.read(FIXTURE_DIRECTORY.join("#{name}-public_key.pem"))
14
+ ::OpenSSL::PKey::RSA.new(pem)
15
+ end
16
+
17
+ def self.load_private_key(name)
18
+ pem = File.read(FIXTURE_DIRECTORY.join("#{name}-private_key.pem"))
19
+ ::OpenSSL::PKey::RSA.new(pem)
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDdjCCAl4CCQCxpvuEfl5slTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJC
3
+ RTERMA8GA1UECAwIQnJ1c3NlbHMxETAPBgNVBAcMCEJydXNzZWxzMRAwDgYDVQQK
4
+ DAdJYmFuaXR5MRMwEQYDVQQDDAppYmFuaXR5LmJlMSEwHwYJKoZIhvcNAQkBFhJj
5
+ b21wYW55QGliYW5pdHkuYmUwHhcNMTkwNjI3MTE1NjAyWhcNMjkwNjI0MTE1NjAy
6
+ WjB9MQswCQYDVQQGEwJCRTERMA8GA1UECAwIQnJ1c3NlbHMxETAPBgNVBAcMCEJy
7
+ dXNzZWxzMRAwDgYDVQQKDAdJYmFuaXR5MRMwEQYDVQQDDAppYmFuaXR5LmJlMSEw
8
+ HwYJKoZIhvcNAQkBFhJjb21wYW55QGliYW5pdHkuYmUwggEiMA0GCSqGSIb3DQEB
9
+ AQUAA4IBDwAwggEKAoIBAQDcaDiqP4EkTYXzDqCLZGiEEQnx0iazY/f3IMZNnYVf
10
+ BDSLl3m2x1+3ch4Pe/E35Aag1webnvDh/VVRch0+n4KV/4Toe0Oq9VP6xKqOXYtZ
11
+ ZAVWXzs1TjdT/dk+rRXa+wnyq2KklPJ0aowzAyr3EzivW1v19uhWdqguhPEPopr/
12
+ 2sue3vloZrigamOov29iFkiFLtSqAyEZI7x48w/3X2nkZ1UivYxBRrLnulVMUJDZ
13
+ zvydu3stlu6mSlaQ3Mpdgzyz4V41NImzNeJnW1F6riwd6hud9xokDZSvredC/XhM
14
+ byl0LdrKABzyHnOFSBlIkIHDeQUPa9YKBESRMtOVmyrvAgMBAAEwDQYJKoZIhvcN
15
+ AQELBQADggEBAKMwFzfoXXxasB/6ZlnAMy7aWmb8xp55E6aZZoZXhoHHA03z+Jj2
16
+ cVy/PMgNDOk5MLf4ddpj7iVf42iLAGpgqo0oQjE11UCwYBBDIQ3vjR+MctoN2B+L
17
+ Qpx7OGDoqSnVucVTS9KmWbJM3PAfbeexSRfqRJ3Jn2DvQDx1k32L//KtP1FRMtku
18
+ Dqoizz7NSLjrmIkXLAuepKdfDSVKnLHD1fB6gKvDNPBNivlFqceZe0XoXdlGwZcC
19
+ 7aTdzYzZNCbg1w1bTxv7dom3ubAM1DPKUEA3afW25691ZsBf9W52hb/tOlVOw78j
20
+ +gUJtiEKTkcfmrfCgPDrcDjsm+iaQclAhK4=
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcaDiqP4EkTYXz
3
+ DqCLZGiEEQnx0iazY/f3IMZNnYVfBDSLl3m2x1+3ch4Pe/E35Aag1webnvDh/VVR
4
+ ch0+n4KV/4Toe0Oq9VP6xKqOXYtZZAVWXzs1TjdT/dk+rRXa+wnyq2KklPJ0aowz
5
+ Ayr3EzivW1v19uhWdqguhPEPopr/2sue3vloZrigamOov29iFkiFLtSqAyEZI7x4
6
+ 8w/3X2nkZ1UivYxBRrLnulVMUJDZzvydu3stlu6mSlaQ3Mpdgzyz4V41NImzNeJn
7
+ W1F6riwd6hud9xokDZSvredC/XhMbyl0LdrKABzyHnOFSBlIkIHDeQUPa9YKBESR
8
+ MtOVmyrvAgMBAAECggEAOS3olXJIJIzgFUBUMhVob+qjs9KbK6rhp4EfMP+OnCnR
9
+ H+26K8rpcAPw/H9hAujrN0rRtHO1dktsmOaL47UqAZP6fP2NfoqKsOHYhXqLLjOe
10
+ ltu51ohmHioa9AGfS+IYoJYJzzy88aq6mHlX6iVYbVW8M8FMYTIDS549k5rRr1Iu
11
+ SqGQSoIo8vGKhMyp6UbIvBhx1CRs2xeoknL0H5uEHnqB6oJTqfnbkQ1sVX4vZuHl
12
+ +WOIKQPlFKy74Lcs9ap1Dr9llD/PoVB3b2KbLRJTda352ezMLspb6CVUOFw7S0eB
13
+ vHVFlR+V922GaMvEmxZ58ZY+DwqBGPeuiG7/kYFNAQKBgQD8e64NptLgw7Wk8mvn
14
+ tGTB28ycUkc9wT/NdiePqlUT56ynD4oCBGcbEu6hH5ntYR93Kpi7fINTKglkVGdK
15
+ MkU/QOV0bs7wItqmQvkMeUbypnWXeQPICs3z/synytwbDYl7/FslTPxdjAgodQZJ
16
+ FY3Lui9bqe05VjvefEtEb9/yrwKBgQDfeimt/bVmA6Ldg4k+K72aAwP+g8l8Dyg1
17
+ Fba2vSFoS/MyvhCqTgP6Uh2fl8qXOqGJEv0koD3yRADa5/FlHSCeLhsyYqsLd/Zm
18
+ 0Ogts7dhVm2v9jvVdmnWUQnGp/mPAGX6gB6Q1WHHEAdUNp6qAG7GatrJcttU0+7U
19
+ 9cYKyc9bwQKBgC7oi53dsLAxrD3JDGMwEMgzngAtCS9gCAqUOSVn8AaStHEVYf6d
20
+ 8soE6nDk/iQsNzxcnaO3rm51EOmjBM20KUlnNTo8nBXhY94f80VuAtByPMa3pQw1
21
+ da4vWLaT6fDcwv5WFFkJxJlcuudJVrGdX4rKPKI7H+fXLahYT2OXpXPhAoGBAIO9
22
+ Vli1WXw75ITFB+DYlDr4UCB3vA0gOkmg9Ucgk1MSgtmE5fofZ4TnZ4MvTkR8UcGm
23
+ qggvVpU8tWxWkx1SYGofL/Ux6Tcnjt/pgxV9/jqpYpv6gidCWP34Y9TyLNG6IGPd
24
+ pycmQy/AKTHhyQLaonLhhvx+cwG8texgvlCZy12BAoGAYsahYudgvuUi/IKjQvkH
25
+ 0F/kwBnd0mRHttsEMIVjrG1Y82EUh5Ja05IGpOSSMeBVhIlJ/DnwFOoSmIVzGfsA
26
+ 4GHtXmHd1xByxjW4nbr4NH7u8ElULkOPjcxSLgXhDb5KtG1XwCPEMUqvApcM6cfv
27
+ CQn8vQRR2J42gXEcTmt0zVQ=
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,9 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3Gg4qj+BJE2F8w6gi2Ro
3
+ hBEJ8dIms2P39yDGTZ2FXwQ0i5d5tsdft3IeD3vxN+QGoNcHm57w4f1VUXIdPp+C
4
+ lf+E6HtDqvVT+sSqjl2LWWQFVl87NU43U/3ZPq0V2vsJ8qtipJTydGqMMwMq9xM4
5
+ r1tb9fboVnaoLoTxD6Ka/9rLnt75aGa4oGpjqL9vYhZIhS7UqgMhGSO8ePMP919p
6
+ 5GdVIr2MQUay57pVTFCQ2c78nbt7LZbupkpWkNzKXYM8s+FeNTSJszXiZ1tReq4s
7
+ HeobnfcaJA2Ur63nQv14TG8pdC3aygAc8h5zhUgZSJCBw3kFD2vWCgREkTLTlZsq
8
+ 7wIDAQAB
9
+ -----END PUBLIC KEY-----
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ibanity
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ibanity
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-30 00:00:00.000000000 Z
11
+ date: 2021-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -30,28 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 3.4.0
33
+ version: 3.9.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 3.4.0
41
- - !ruby/object:Gem::Dependency
42
- name: webmock
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '='
46
- - !ruby/object:Gem::Version
47
- version: 1.24.2
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '='
53
- - !ruby/object:Gem::Version
54
- version: 1.24.2
40
+ version: 3.9.0
55
41
  description: A Ruby wrapper for the Ibanity API.
56
42
  email:
57
43
  - info@ibanity.com
@@ -59,9 +45,11 @@ executables: []
59
45
  extensions: []
60
46
  extra_rdoc_files: []
61
47
  files:
48
+ - ".github/workflows/ci.yml"
49
+ - ".github/workflows/gem-push.yml"
62
50
  - ".gitignore"
63
51
  - ".gitkeep"
64
- - ".travis.yml"
52
+ - ".rspec"
65
53
  - CHANGELOG.md
66
54
  - Gemfile
67
55
  - LICENSE.txt
@@ -83,10 +71,16 @@ files:
83
71
  - lib/ibanity/api/o_auth_resource.rb
84
72
  - lib/ibanity/api/ponto_connect/account.rb
85
73
  - lib/ibanity/api/ponto_connect/financial_institution.rb
74
+ - lib/ibanity/api/ponto_connect/integration.rb
75
+ - lib/ibanity/api/ponto_connect/onboarding_details.rb
86
76
  - lib/ibanity/api/ponto_connect/payment.rb
77
+ - lib/ibanity/api/ponto_connect/sandbox/financial_institution_account.rb
78
+ - lib/ibanity/api/ponto_connect/sandbox/financial_institution_transaction.rb
87
79
  - lib/ibanity/api/ponto_connect/synchronization.rb
88
80
  - lib/ibanity/api/ponto_connect/token.rb
89
81
  - lib/ibanity/api/ponto_connect/transaction.rb
82
+ - lib/ibanity/api/ponto_connect/usage.rb
83
+ - lib/ibanity/api/ponto_connect/user_info.rb
90
84
  - lib/ibanity/api/sandbox/financial_institution_account.rb
91
85
  - lib/ibanity/api/sandbox/financial_institution_holding.rb
92
86
  - lib/ibanity/api/sandbox/financial_institution_transaction.rb
@@ -94,12 +88,15 @@ files:
94
88
  - lib/ibanity/api/xs2a/account.rb
95
89
  - lib/ibanity/api/xs2a/account_information_access_request.rb
96
90
  - lib/ibanity/api/xs2a/account_information_access_request_authorization.rb
91
+ - lib/ibanity/api/xs2a/bulk_payment_initiation_request.rb
97
92
  - lib/ibanity/api/xs2a/customer.rb
98
93
  - lib/ibanity/api/xs2a/customer_access_token.rb
99
94
  - lib/ibanity/api/xs2a/financial_institution.rb
95
+ - lib/ibanity/api/xs2a/financial_institution_country.rb
100
96
  - lib/ibanity/api/xs2a/holding.rb
101
97
  - lib/ibanity/api/xs2a/payment_initiation_request.rb
102
98
  - lib/ibanity/api/xs2a/payment_initiation_request_authorization.rb
99
+ - lib/ibanity/api/xs2a/periodic_payment_initiation_request.rb
103
100
  - lib/ibanity/api/xs2a/synchronization.rb
104
101
  - lib/ibanity/api/xs2a/transaction.rb
105
102
  - lib/ibanity/client.rb
@@ -108,6 +105,13 @@ files:
108
105
  - lib/ibanity/http_signature.rb
109
106
  - lib/ibanity/util.rb
110
107
  - lib/ibanity/version.rb
108
+ - spec/lib/ibanity/http_signature_spec.rb
109
+ - spec/lib/ibanity/util_spec.rb
110
+ - spec/spec_helper.rb
111
+ - spec/support/crypto_helper.rb
112
+ - spec/support/fixtures/signature/test-certificate.pem
113
+ - spec/support/fixtures/signature/test-private_key.pem
114
+ - spec/support/fixtures/signature/test-public_key.pem
111
115
  homepage: https://documentation.ibanity.com/api/ruby
112
116
  licenses:
113
117
  - MIT
@@ -127,9 +131,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
131
  - !ruby/object:Gem::Version
128
132
  version: '0'
129
133
  requirements: []
130
- rubyforge_project:
131
- rubygems_version: 2.7.7
134
+ rubygems_version: 3.0.3
132
135
  signing_key:
133
136
  specification_version: 4
134
137
  summary: Ibanity Ruby Client
135
- test_files: []
138
+ test_files:
139
+ - spec/lib/ibanity/http_signature_spec.rb
140
+ - spec/lib/ibanity/util_spec.rb
141
+ - spec/spec_helper.rb
142
+ - spec/support/crypto_helper.rb
143
+ - spec/support/fixtures/signature/test-certificate.pem
144
+ - spec/support/fixtures/signature/test-private_key.pem
145
+ - spec/support/fixtures/signature/test-public_key.pem
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- language: ruby
2
- script: bundle exec rspec
3
- deploy:
4
- provider: rubygems
5
- api_key:
6
- secure: pfXgGXH/AZEG3HMiaJPmJ7fck6Z3Hj0y7TU5TwvLAtKuBy6hlLT67ne/VfeBZQKa9d7eerr9PFP1hvLjZppScZMMOTtjBTvwpchkcUDwCxHx5GzS/jRnBF+uYHIza2p4Wq8yIPug7UrZ0qyq5VOG45R/nC/fPm2Ht2T7heqF5VgRaDGrN7Fq3zXn7duiYhTy02nDXorZ/kEAjnwdwDtXWyVFq8wr4inTExYrDP9/M57qx5TrkgWmcQ7JrvO2KfLDMJqAxI8lNoaPl5dAi7q1XWqqSVay7h9OAnP4UfvnvAc106lG6nHfTQig1krTfxRAvtHlPQjSlFkL+0qfBPBz1C/ex221O3NsNBYmI/mJ45lcNhqJbnkV2VEAEgUoe4ZFfKUUczLfnVxIPjoQmHMwLwfEO4g8/Hz/I3L7bvebgfzGGMDpmN6ERZRJmhutE6K5cL80ghoLs6ExJLoqHi1qvdBSkM2IyE4Yo+lob/hKU1IBL1w13T2h3EHapBh3kKn+jBzu/y5nXTEteBHbMP8j2zxFiihVBJEKPXhg/iU8WHLI6HZgWJkOc9ZH3hS7CN3VELK7fVZp9jaPAKaKihdvxQ0z3gCPFL+E6rYKsBPYqXE6qDsSQswhqTN15W0eVQqK8fDXkZmW0lSGvi2IJvL0CjIaahfB2GaapTtqOwar7sc=
7
- on:
8
- tags: true
9
- gem: ibanity
10
- skip_cleanup: true