idnow 1.0.0 → 2.3.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 (48) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +67 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +7 -14
  5. data/.travis.yml +4 -2
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Dockerfile +9 -0
  8. data/Gemfile +2 -0
  9. data/LICENSE.txt +1 -1
  10. data/Makefile +12 -1
  11. data/README.md +57 -12
  12. data/examples/idnow_automated_testing.rb +3 -1
  13. data/examples/idnow_download_identification.rb +3 -1
  14. data/examples/idnow_get_identification.rb +3 -1
  15. data/examples/idnow_upload_download_default_document.rb +3 -1
  16. data/idnow-client.gemspec +12 -10
  17. data/lib/idnow.rb +28 -9
  18. data/lib/idnow/API/authentication.rb +2 -0
  19. data/lib/idnow/API/automated_testing.rb +5 -3
  20. data/lib/idnow/API/document_definitions.rb +10 -7
  21. data/lib/idnow/API/download_documents.rb +4 -2
  22. data/lib/idnow/API/request_identifications.rb +3 -1
  23. data/lib/idnow/API/retrieve_identifications.rb +9 -6
  24. data/lib/idnow/API/upload_documents.rb +5 -2
  25. data/lib/idnow/client.rb +14 -9
  26. data/lib/idnow/configuration.rb +5 -8
  27. data/lib/idnow/exception.rb +2 -0
  28. data/lib/idnow/get_request.rb +2 -0
  29. data/lib/idnow/helpers.rb +3 -1
  30. data/lib/idnow/http_client.rb +12 -9
  31. data/lib/idnow/json_response.rb +3 -1
  32. data/lib/idnow/models/contact_data.rb +2 -0
  33. data/lib/idnow/models/document_definition.rb +2 -0
  34. data/lib/idnow/models/identification.rb +5 -2
  35. data/lib/idnow/models/identification_data.rb +20 -13
  36. data/lib/idnow/models/identification_document.rb +11 -18
  37. data/lib/idnow/models/identification_process.rb +4 -2
  38. data/lib/idnow/models/identification_request.rb +2 -0
  39. data/lib/idnow/models/login.rb +2 -0
  40. data/lib/idnow/models/login_data.rb +3 -1
  41. data/lib/idnow/models/user_data.rb +7 -0
  42. data/lib/idnow/modules/jsonable.rb +4 -1
  43. data/lib/idnow/post_binary_request.rb +2 -0
  44. data/lib/idnow/post_json_request.rb +2 -0
  45. data/lib/idnow/raw_response.rb +5 -3
  46. data/lib/idnow/sftp_client.rb +15 -3
  47. metadata +41 -37
  48. data/circle.yml +0 -7
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module Authentication
@@ -1,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module AutomatedTesting
4
- HOST = 'https://api.test.idnow.de'.freeze
6
+ HOST = 'https://api.test.idnow.de'
5
7
 
6
8
  def testing_start(transaction_number:)
7
9
  path = full_path_for("identifications/#{transaction_number}/start")
8
10
  request = Idnow::PostJsonRequest.new(path, {})
9
- execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
11
+ execute(request, { 'X-API_KEY' => @api_key }, http_client: automated_testing_http_client)
10
12
  end
11
13
 
12
14
  def testing_request_video_chat(transaction_number:)
13
15
  path = full_path_for("identifications/#{transaction_number}/requestVideoChat")
14
16
  request = Idnow::PostJsonRequest.new(path, {})
15
- execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
17
+ execute(request, { 'X-API_KEY' => @api_key }, http_client: automated_testing_http_client)
16
18
  end
17
19
  end
18
20
  end
@@ -1,28 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module DocumentDefinitions
4
6
  def create_document_definition(document_data)
5
- fail Idnow::AuthenticationException if @auth_token.nil?
7
+ raise Idnow::AuthenticationException if @auth_token.nil?
6
8
 
7
9
  path = full_path_for('documentdefinitions')
8
10
  request = Idnow::PostJsonRequest.new(path, document_data)
9
- execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
11
+ execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
10
12
  end
11
13
 
12
14
  def list_document_definitions
13
- fail Idnow::AuthenticationException if @auth_token.nil?
15
+ raise Idnow::AuthenticationException if @auth_token.nil?
14
16
 
15
17
  path = full_path_for('documentdefinitions')
16
18
  request = Idnow::GetRequest.new(path)
17
- response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
19
+ response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
18
20
  response.data.map do |data|
19
21
  Idnow::DocumentDefinition.new(data)
20
22
  end
21
23
  end
22
24
 
23
- def list_cached_document_definitions(refresh = false)
24
- return @document_definitions = list_document_definitions if refresh
25
- @document_definitions ||= list_document_definitions
25
+ def list_cached_document_definitions(refresh = false) # rubocop:disable Style/OptionalBooleanParameter
26
+ return @list_cached_document_definitions = list_document_definitions if refresh
27
+
28
+ @list_cached_document_definitions ||= list_document_definitions
26
29
  end
27
30
  end
28
31
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module DownloadDocuments
4
6
  def download_default_document(document_definition_identifier)
5
- fail Idnow::AuthenticationException if @auth_token.nil?
7
+ raise Idnow::AuthenticationException if @auth_token.nil?
6
8
 
7
9
  path = full_path_for("documentdefinitions/#{document_definition_identifier}/data")
8
10
  request = Idnow::GetRequest.new(path, '')
9
- execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
11
+ execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
10
12
  end
11
13
  end
12
14
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module RequestIdentifications
4
6
  def request_identification(transaction_number:, identification_data:)
5
7
  path = full_path_for("identifications/#{transaction_number}/start")
6
8
  request = Idnow::PostJsonRequest.new(path, identification_data)
7
- response = execute(request, 'X-API-KEY' => @api_key)
9
+ response = execute(request, { 'X-API-KEY' => @api_key })
8
10
  Idnow::IdentificationRequest.new(response.data, transaction_number, @target_host, @company_id)
9
11
  end
10
12
  end
@@ -1,29 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module RetrieveIdentifications
4
- IDENTIFICATION_STATUSES = %w(pending failed).freeze
6
+ IDENTIFICATION_STATUSES = %w[pending failed].freeze
5
7
 
6
8
  def list_identifications(status: nil)
7
- fail Idnow::AuthenticationException if @auth_token.nil?
9
+ raise Idnow::AuthenticationException if @auth_token.nil?
8
10
 
9
11
  unless status.nil? || IDENTIFICATION_STATUSES.include?(status)
10
- fail Idnow::InvalidArguments, "Status #{status} not defined, possible options are: #{IDENTIFICATION_STATUSES.join(',')}"
12
+ raise Idnow::InvalidArguments, "Status #{status} not defined, possible options are: #{IDENTIFICATION_STATUSES.join(',')}"
11
13
  end
14
+
12
15
  partial_path = status.nil? ? 'identifications' : "identifications?#{status}=true"
13
16
  path = full_path_for(partial_path)
14
17
  request = Idnow::GetRequest.new(path)
15
- response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
18
+ response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
16
19
  response.data['identifications'].map do |data|
17
20
  Idnow::Identification.new(data)
18
21
  end
19
22
  end
20
23
 
21
24
  def get_identification(transaction_number:)
22
- fail Idnow::AuthenticationException if @auth_token.nil?
25
+ raise Idnow::AuthenticationException if @auth_token.nil?
23
26
 
24
27
  path = full_path_for("identifications/#{transaction_number}")
25
28
  request = Idnow::GetRequest.new(path)
26
- response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
29
+ response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
27
30
  Idnow::Identification.new(response.data)
28
31
  end
29
32
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module API
3
5
  module UploadDocuments
@@ -14,9 +16,10 @@ module Idnow
14
16
  private
15
17
 
16
18
  def upload_document(file_data, request_path)
17
- fail Idnow::AuthenticationException if @auth_token.nil?
19
+ raise Idnow::AuthenticationException if @auth_token.nil?
20
+
18
21
  request = Idnow::PostBinaryRequest.new(request_path, file_data)
19
- execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
22
+ execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
20
23
  end
21
24
  end
22
25
  end
data/lib/idnow/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'idnow/API/authentication'
2
4
  require 'idnow/API/automated_testing' # shouldn't be included by default
3
5
  require 'idnow/API/request_identifications'
@@ -16,21 +18,24 @@ module Idnow
16
18
  include Idnow::API::UploadDocuments
17
19
  include Idnow::API::DownloadDocuments
18
20
 
19
- API_VERSION = 'v1'.freeze
21
+ API_VERSION = 'v1'
20
22
 
21
23
  attr_reader :host
22
24
 
23
- def initialize(env:, company_id:, api_key:)
24
- fail 'Please set env to :test or :live' unless Idnow::ENVIRONMENTS.keys.include?(env)
25
- fail 'Please set your company_id' if company_id.nil?
26
- fail 'Please set your api_key' if api_key.nil?
27
- @host = Idnow::ENVIRONMENTS[env][:host]
28
- @target_host = Idnow::ENVIRONMENTS[env][:target_host]
25
+ def initialize(env:, company_id:, api_key:, timeout: nil, sftp_options: {})
26
+ raise 'Please set env to :test or :live' unless Idnow::ENVIRONMENTS.keys.include?(env)
27
+ raise 'Please set your company_id' if company_id.nil?
28
+ raise 'Please set your api_key' if api_key.nil?
29
+
30
+ @host = Idnow.endpoint(env, :host)
31
+ @target_host = Idnow.endpoint(env, :target_host)
29
32
  @company_id = company_id
30
33
  @api_key = api_key
31
34
 
32
35
  @http_client = HttpClient.new(host: @host)
33
- @sftp_client = SftpClient.new(host: @host, username: @company_id, password: @api_key)
36
+
37
+ sftp_options[:timeout] = timeout if timeout
38
+ @sftp_client = SftpClient.new(host: @host, username: @company_id, password: @api_key, options: sftp_options)
34
39
  end
35
40
 
36
41
  private
@@ -45,7 +50,7 @@ module Idnow
45
50
  end
46
51
 
47
52
  response.tap do |r|
48
- fail Idnow::ResponseException, r.errors if r.errors?
53
+ raise Idnow::ResponseException, r.errors if r.errors?
49
54
  end
50
55
  end
51
56
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class Configuration
3
5
  # TODO: This class is not being used right now, but its aim is to be able for the developers
@@ -8,18 +10,13 @@ module Idnow
8
10
  # config.company_id = company_id
9
11
  # end
10
12
 
11
- attr_accessor :api_key
12
-
13
- attr_accessor :company_id
13
+ attr_accessor :api_key, :company_id, :host, :api_version
14
14
 
15
15
  module Idnow
16
16
  module Host
17
- TEST = 'https://gateway.test.idnow.de'.freeze
18
- PRODUCTION = 'https://gateway.idnow.de'.freeze
17
+ TEST = 'https://gateway.test.idnow.de'
18
+ PRODUCTION = 'https://gateway.idnow.de'
19
19
  end
20
20
  end
21
- attr_accessor :host
22
-
23
- attr_accessor :api_version
24
21
  end
25
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class Exception < StandardError
3
5
  def initialize(message)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'net/http'
2
4
 
3
5
  module Idnow
data/lib/idnow/helpers.rb CHANGED
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  module Helpers
3
5
  PROJECT_ROOT = File.dirname(File.dirname(File.dirname(__FILE__)))
4
6
 
5
7
  module Factories
6
- Dir[File.join(PROJECT_ROOT, 'spec', 'support', 'factories', '*.rb')].each { |file| require(file) }
8
+ Dir[File.join(PROJECT_ROOT, 'spec', 'support', 'factories', '*.rb')].sort.each { |file| require(file) }
7
9
  end
8
10
  end
9
11
  end
@@ -1,26 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class HttpClient
3
- def initialize(host:)
4
- @uri = URI.parse(host)
5
+ def initialize(host:, read_timout_sec: 30)
6
+ @uri = URI.parse(host)
7
+ @read_timeout = read_timout_sec
5
8
  end
6
9
 
7
10
  def execute(request, headers = {})
8
11
  headers.each do |k, v|
9
12
  request[k] = v
10
13
  end
11
- begin
12
- client.request(request)
13
- rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
14
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
15
- raise Idnow::ConnectionException, e
16
- end
14
+
15
+ client.request(request)
16
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
17
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
18
+ raise Idnow::ConnectionException, e
17
19
  end
18
20
 
19
21
  private
20
22
 
21
23
  def client
22
24
  Net::HTTP.new(@uri.host, @uri.port).tap do |http|
23
- http.use_ssl = true
25
+ http.read_timeout = @read_timeout
26
+ http.use_ssl = @uri.scheme == 'https'
24
27
  end
25
28
  end
26
29
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class JsonResponse < RawResponse
3
5
  attr_reader :data
4
6
 
5
7
  def initialize(raw_response)
6
8
  super
7
- raw_response = (raw_response == '') ? '{}' : raw_response
9
+ raw_response = raw_response == '' ? '{}' : raw_response
8
10
  @data = JSON.parse(raw_response)
9
11
  end
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class ContactData
3
5
  include Idnow::Jsonable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class DocumentDefinition
3
5
  include Idnow::Jsonable
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
- require 'pry'
4
+
3
5
  module Idnow
4
6
  class Identification
5
7
  extend Forwardable
6
8
  include Idnow::Jsonable
7
9
 
8
10
  attr_accessor :identification_process, :contact_data, :user_data,
9
- :identification_document, :attachments, :esigning
11
+ :identification_document, :attachments, :esigning, :raw_data
10
12
 
11
13
  def initialize(data)
12
14
  @identification_process = IdentificationProcess.new(data['identificationprocess'])
@@ -15,6 +17,7 @@ module Idnow
15
17
  @identification_document = IdentificationDocument.new(data.fetch('identificationdocument', {}))
16
18
  @attachments = data['attachments']
17
19
  @esigning = data['esigning']
20
+ @raw_data = data
18
21
  end
19
22
 
20
23
  def esigning?
@@ -1,25 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module Idnow
4
6
  class IdentificationData
5
7
  module Gender
6
- MALE = 'MALE'.freeze
7
- FEMALE = 'FEMALE'.freeze
8
+ MALE = 'MALE'
9
+ FEMALE = 'FEMALE'
8
10
  end
9
11
 
10
- attr_accessor :birthplace, :birthname, :city, :country, :custom1,
11
- :custom2, :custom3, :custom4, :custom5, :trackingid, :email, :firstname, :gender,
12
- :lastname, :mobilephone, :nationality, :street, :streetnumber, :title, :zipcode
12
+ # rubocop:disable Naming/MethodName
13
+ attr_accessor :birthplace, :birthname, :city, :custom1,
14
+ :custom2, :custom3, :custom4, :custom5, :trackingid, :email, :firstname,
15
+ :lastname, :mobilephone, :nationality, :street, :streetnumber, :title, :zipcode,
16
+ :preferredLang
17
+ # rubocop:enable Naming/MethodName
18
+
19
+ attr_reader :country, :gender
13
20
 
14
21
  def initialize(params = {})
15
- params.keys.each do |key|
16
- fail ArgumentError, "Attribute #{key} is not supported!" unless respond_to?(key.to_sym)
22
+ params.each_key do |key|
23
+ raise ArgumentError, "Attribute #{key} is not supported!" unless respond_to?(key.to_sym)
17
24
 
18
25
  send("#{key}=", params[key])
19
26
  end
20
27
  end
21
28
 
22
- def to_json
29
+ def to_json(*_args)
23
30
  result = {}
24
31
  instance_variables.each do |attribute|
25
32
  result[attribute.to_s.delete('@')] = instance_variable_get(attribute)
@@ -30,7 +37,7 @@ module Idnow
30
37
  ########### Getter / Setter ############
31
38
 
32
39
  def birthday
33
- @birthday.strftime('%Y-%m-%d') if @birthday
40
+ @birthday&.strftime('%Y-%m-%d')
34
41
  end
35
42
 
36
43
  def birthday=(birthday)
@@ -42,18 +49,18 @@ module Idnow
42
49
  end
43
50
 
44
51
  def country=(country)
45
- fail ArgumentError, 'Country must be ISO 3166 two letter country code' unless country.instance_of?(String) && country.size == 2
52
+ raise ArgumentError, 'Country must be ISO 3166 two letter country code' unless country.instance_of?(String) && country.size == 2
46
53
 
47
54
  @country = country.upcase
48
55
  end
49
56
 
50
57
  def gender=(gender)
51
- if %w(M MALE).include?(gender.to_s.strip.upcase)
58
+ if %w[M MALE].include?(gender.to_s.strip.upcase)
52
59
  @gender = Gender::MALE
53
- elsif %w(F FEMALE).include?(gender.to_s.strip.upcase)
60
+ elsif %w[F FEMALE].include?(gender.to_s.strip.upcase)
54
61
  @gender = Gender::FEMALE
55
62
  else
56
- fail ArgumentError, 'Provide valid value for gender: MALE or FEMALE'
63
+ raise ArgumentError, 'Provide valid value for gender: MALE or FEMALE'
57
64
  end
58
65
  end
59
66
  end
@@ -1,15 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Idnow
2
4
  class IdentificationDocument
3
5
  include Idnow::Jsonable
4
6
 
5
- attr_accessor :country, :number, :issued_by, :date_issued, :type, :valid_until
7
+ attr_accessor :country, :number, :issued_by, :type
8
+ attr_writer :date_issued, :valid_until
9
+
6
10
  def initialize(data)
7
- @country = dig_value('country', data)
8
- @number = dig_value('number', data)
9
- @issued_by = dig_value('issuedby', data)
10
- @date_issued = dig_value('dateissued', data)
11
- @type = dig_value('type', data)
12
- @valid_until = dig_value('validuntil', data)
11
+ @country = data.dig('country', 'value')
12
+ @number = data.dig('number', 'value')
13
+ @issued_by = data.dig('issuedby', 'value')
14
+ @date_issued = data.dig('dateissued', 'value')
15
+ @type = data.dig('type', 'value')
16
+ @valid_until = data.dig('validuntil', 'value')
13
17
  end
14
18
 
15
19
  def date_issued
@@ -19,16 +23,5 @@ module Idnow
19
23
  def valid_until
20
24
  Date.parse(@valid_until) if @valid_until
21
25
  end
22
-
23
- private
24
-
25
- def dig_value(*keys, data)
26
- # TODO: use ruby 2.3 and dig
27
- result = data
28
- keys.each do |key|
29
- result = result.fetch(key, {})
30
- end
31
- result['value']
32
- end
33
26
  end
34
27
  end