smart-id-ruby-client 0.1.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +436 -0
- data/Rakefile +12 -0
- data/lib/smart-id-ruby-client.rb +3 -0
- data/lib/smart_id_ruby/callback_url.rb +18 -0
- data/lib/smart_id_ruby/callback_url_util.rb +54 -0
- data/lib/smart_id_ruby/client.rb +124 -0
- data/lib/smart_id_ruby/configuration.rb +184 -0
- data/lib/smart_id_ruby/device_link_builder.rb +301 -0
- data/lib/smart_id_ruby/device_link_interaction.rb +67 -0
- data/lib/smart_id_ruby/errors/certificate_level_mismatch_error.rb +8 -0
- data/lib/smart_id_ruby/errors/document_unusable_error.rb +12 -0
- data/lib/smart_id_ruby/errors/error.rb +8 -0
- data/lib/smart_id_ruby/errors/expected_linked_session_error.rb +15 -0
- data/lib/smart_id_ruby/errors/no_suitable_account_of_requested_type_found_error.rb +10 -0
- data/lib/smart_id_ruby/errors/person_should_view_smart_id_portal_error.rb +8 -0
- data/lib/smart_id_ruby/errors/protocol_failure_error.rb +13 -0
- data/lib/smart_id_ruby/errors/relying_party_account_configuration_error.rb +10 -0
- data/lib/smart_id_ruby/errors/request_setup_error.rb +10 -0
- data/lib/smart_id_ruby/errors/request_validation_error.rb +8 -0
- data/lib/smart_id_ruby/errors/required_interaction_not_supported_by_app_error.rb +13 -0
- data/lib/smart_id_ruby/errors/response_error.rb +8 -0
- data/lib/smart_id_ruby/errors/server_maintenance_error.rb +8 -0
- data/lib/smart_id_ruby/errors/session_end_result_error.rb +15 -0
- data/lib/smart_id_ruby/errors/session_not_complete_error.rb +8 -0
- data/lib/smart_id_ruby/errors/session_not_found_error.rb +8 -0
- data/lib/smart_id_ruby/errors/session_secret_mismatch_error.rb +8 -0
- data/lib/smart_id_ruby/errors/session_timeout_error.rb +12 -0
- data/lib/smart_id_ruby/errors/smart_id_server_error.rb +12 -0
- data/lib/smart_id_ruby/errors/unprocessable_response_error.rb +9 -0
- data/lib/smart_id_ruby/errors/unsupported_client_api_version_error.rb +8 -0
- data/lib/smart_id_ruby/errors/user_account_not_found_error.rb +8 -0
- data/lib/smart_id_ruby/errors/user_account_unusable_error.rb +12 -0
- data/lib/smart_id_ruby/errors/user_refused_cert_choice_error.rb +14 -0
- data/lib/smart_id_ruby/errors/user_refused_confirmation_message_error.rb +13 -0
- data/lib/smart_id_ruby/errors/user_refused_confirmation_message_with_verification_choice_error.rb +13 -0
- data/lib/smart_id_ruby/errors/user_refused_display_text_and_pin_error.rb +13 -0
- data/lib/smart_id_ruby/errors/user_refused_error.rb +12 -0
- data/lib/smart_id_ruby/errors/user_selected_wrong_verification_code_error.rb +13 -0
- data/lib/smart_id_ruby/errors.rb +31 -0
- data/lib/smart_id_ruby/flows/base_builder.rb +90 -0
- data/lib/smart_id_ruby/flows/certificate_by_document_number_request_builder.rb +130 -0
- data/lib/smart_id_ruby/flows/device_link_authentication_session_request_builder.rb +208 -0
- data/lib/smart_id_ruby/flows/device_link_certificate_choice_session_request_builder.rb +112 -0
- data/lib/smart_id_ruby/flows/device_link_signature_session_request_builder.rb +286 -0
- data/lib/smart_id_ruby/flows/linked_notification_signature_session_request_builder.rb +235 -0
- data/lib/smart_id_ruby/flows/notification_authentication_session_request_builder.rb +184 -0
- data/lib/smart_id_ruby/flows/notification_certificate_choice_session_request_builder.rb +96 -0
- data/lib/smart_id_ruby/flows/notification_signature_session_request_builder.rb +272 -0
- data/lib/smart_id_ruby/models/authentication_identity.rb +19 -0
- data/lib/smart_id_ruby/models/authentication_response.rb +38 -0
- data/lib/smart_id_ruby/models/certificate_choice_response.rb +19 -0
- data/lib/smart_id_ruby/models/device_link_session_response.rb +34 -0
- data/lib/smart_id_ruby/models/notification_authentication_session_response.rb +25 -0
- data/lib/smart_id_ruby/models/notification_certificate_choice_session_response.rb +25 -0
- data/lib/smart_id_ruby/models/notification_signature_session_response.rb +29 -0
- data/lib/smart_id_ruby/models/session_status.rb +261 -0
- data/lib/smart_id_ruby/models/signature_response.rb +38 -0
- data/lib/smart_id_ruby/notification_interaction.rb +70 -0
- data/lib/smart_id_ruby/qr_code_generator.rb +65 -0
- data/lib/smart_id_ruby/rest/connector.rb +364 -0
- data/lib/smart_id_ruby/rest/session_status_poller.rb +125 -0
- data/lib/smart_id_ruby/rp_challenge.rb +37 -0
- data/lib/smart_id_ruby/rp_challenge_generator.rb +28 -0
- data/lib/smart_id_ruby/semantics_identifier.rb +35 -0
- data/lib/smart_id_ruby/validation/authentication_certificate_validator.rb +90 -0
- data/lib/smart_id_ruby/validation/authentication_identity_mapper.rb +227 -0
- data/lib/smart_id_ruby/validation/base_authentication_response_validator.rb +304 -0
- data/lib/smart_id_ruby/validation/certificate_choice_response_validator.rb +104 -0
- data/lib/smart_id_ruby/validation/certificate_validator.rb +170 -0
- data/lib/smart_id_ruby/validation/device_link_authentication_response_validator.rb +76 -0
- data/lib/smart_id_ruby/validation/error_result_handler.rb +88 -0
- data/lib/smart_id_ruby/validation/notification_authentication_response_validator.rb +16 -0
- data/lib/smart_id_ruby/validation/signature_payload_builder.rb +62 -0
- data/lib/smart_id_ruby/validation/signature_response_validator.rb +345 -0
- data/lib/smart_id_ruby/validation/signature_value_validator.rb +76 -0
- data/lib/smart_id_ruby/validation/trusted_ca_cert_store.rb +20 -0
- data/lib/smart_id_ruby/verification_code_calculator.rb +31 -0
- data/lib/smart_id_ruby/version.rb +5 -0
- data/lib/smart_id_ruby.rb +76 -0
- metadata +173 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
# Represents interaction payload used in device-link-based flows.
|
|
5
|
+
class DeviceLinkInteraction
|
|
6
|
+
DISPLAY_TEXT_AND_PIN = "displayTextAndPIN"
|
|
7
|
+
CONFIRMATION_MESSAGE = "confirmationMessage"
|
|
8
|
+
|
|
9
|
+
DISPLAY_TEXT_60_MAX_LENGTH = 60
|
|
10
|
+
DISPLAY_TEXT_200_MAX_LENGTH = 200
|
|
11
|
+
|
|
12
|
+
attr_reader :type, :display_text60, :display_text200
|
|
13
|
+
|
|
14
|
+
def initialize(type:, display_text60: nil, display_text200: nil)
|
|
15
|
+
@type = type&.to_s
|
|
16
|
+
@display_text60 = display_text60
|
|
17
|
+
@display_text200 = display_text200
|
|
18
|
+
|
|
19
|
+
validate!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_h
|
|
23
|
+
{
|
|
24
|
+
type: type,
|
|
25
|
+
displayText60: display_text60,
|
|
26
|
+
displayText200: display_text200
|
|
27
|
+
}.compact
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.display_text_and_pin(display_text60)
|
|
31
|
+
new(type: DISPLAY_TEXT_AND_PIN, display_text60: display_text60)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.confirmation_message(display_text200)
|
|
35
|
+
new(type: CONFIRMATION_MESSAGE, display_text200: display_text200)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def validate!
|
|
41
|
+
raise SmartIdRuby::Errors::RequestSetupError, "Value for 'type' must be set" if blank?(type)
|
|
42
|
+
|
|
43
|
+
case type
|
|
44
|
+
when DISPLAY_TEXT_AND_PIN
|
|
45
|
+
validate_display_text!(display_text60, "displayText60", DISPLAY_TEXT_60_MAX_LENGTH)
|
|
46
|
+
when CONFIRMATION_MESSAGE
|
|
47
|
+
validate_display_text!(display_text200, "displayText200", DISPLAY_TEXT_200_MAX_LENGTH)
|
|
48
|
+
else
|
|
49
|
+
raise SmartIdRuby::Errors::RequestSetupError, "Unsupported interaction type: #{type}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def validate_display_text!(value, field_name, max_length)
|
|
54
|
+
if blank?(value)
|
|
55
|
+
raise SmartIdRuby::Errors::RequestSetupError, "Value for '#{field_name}' cannot be empty"
|
|
56
|
+
end
|
|
57
|
+
return if value.to_s.length <= max_length
|
|
58
|
+
|
|
59
|
+
raise SmartIdRuby::Errors::RequestSetupError,
|
|
60
|
+
"Value for '#{field_name}' cannot be longer than #{max_length} characters"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def blank?(value)
|
|
64
|
+
value.nil? || value.to_s.strip.empty?
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is DOCUMENT_UNUSABLE.
|
|
6
|
+
class DocumentUnusableError < Error
|
|
7
|
+
def initialize(message = "Document is unusable. User must either check his/her Smart-ID mobile application or turn to customer support for getting the exact reason.")
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Linked signature flow consists of two sessions - device link-based certificate choice session followed by the linked signature session.
|
|
6
|
+
# Exception will be thrown when linked signature session is not received after the device link-based certificate choice session,
|
|
7
|
+
# but some other session with the same document number is received instead.
|
|
8
|
+
class ExpectedLinkedSessionError < SessionEndResultError
|
|
9
|
+
def initialize
|
|
10
|
+
super("EXPECTED_LINKED_SESSION",
|
|
11
|
+
"The app received a different transaction while waiting for the linked session that follows the device-link based cert-choice session")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when user does not have a suitable account for the requested operation.
|
|
6
|
+
# F.e. user has non-qualified account with ADVANCED certificate level,
|
|
7
|
+
# but QUALIFIED certificate level is required for the operation.
|
|
8
|
+
class NoSuitableAccountOfRequestedTypeFoundError < Error; end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Exception thrown when the session status end result is PROTOCOL_FAILURE, indicating logical error in the signing protocol.
|
|
6
|
+
# F.e. Constructed device link that user can interact with contains invalid schema.
|
|
7
|
+
class ProtocolFailureError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("PROTOCOL_FAILURE", "A logical error occurred in the signing protocol.")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Exception will be thrown when there are problems with relying party account and access configuration
|
|
6
|
+
# or when relying party does not have access to the requested service.
|
|
7
|
+
# F.e. Request is made with relying party UUID and incorrect relying party name.
|
|
8
|
+
class RelyingPartyAccountConfigurationError < Error; end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Exception thrown when there is an issue setting up a Smart-ID request.
|
|
6
|
+
# This could be due to invalid parameters, configuration issues, or other
|
|
7
|
+
# problems that prevent from successfully preparing the request.
|
|
8
|
+
class RequestSetupError < Error; end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when the user's app version does not support any of the provided interactions.
|
|
6
|
+
class RequiredInteractionNotSupportedByAppError < SessionEndResultError
|
|
7
|
+
def initialize
|
|
8
|
+
super("REQUIRED_INTERACTION_NOT_SUPPORTED_BY_APP",
|
|
9
|
+
"User app version does not support any of the provided interactions.")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Represents session end result error condition.
|
|
6
|
+
class SessionEndResultError < Error
|
|
7
|
+
attr_reader :end_result
|
|
8
|
+
|
|
9
|
+
def initialize(end_result, message = nil)
|
|
10
|
+
@end_result = end_result
|
|
11
|
+
super(message || "Session ended with result '#{end_result}'")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is TIMEOUT.
|
|
6
|
+
class SessionTimeoutError < SessionEndResultError
|
|
7
|
+
def initialize
|
|
8
|
+
super("TIMEOUT", "Session timed out without getting any response from user")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is SERVER_ERROR, indicating a server-side technical error.
|
|
6
|
+
class SmartIdServerError < SessionEndResultError
|
|
7
|
+
def initialize
|
|
8
|
+
super("SERVER_ERROR", "Process was terminated due to server-side technical error")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when validation of any Smart-ID API responses fail.
|
|
6
|
+
# This includes responses for session initialization requests and session status responses.
|
|
7
|
+
class UnprocessableResponseError < Error; end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is ACCOUNT_UNUSABLE.
|
|
6
|
+
class UserAccountUnusableError < SessionEndResultError
|
|
7
|
+
def initialize
|
|
8
|
+
super("ACCOUNT_UNUSABLE", "The account is currently unusable")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is USER_REFUSED_CERT_CHOICE.
|
|
6
|
+
# This happens when user has multiple accounts and presses Cancel on device choice screen on any device.
|
|
7
|
+
class UserRefusedCertChoiceError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("USER_REFUSED_CERT_CHOICE",
|
|
10
|
+
"User has multiple accounts and pressed Cancel on device choice screen on any device.")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is USER_REFUSED_INTERACTION.
|
|
6
|
+
# This happens when user presses Cancel on confirmation message screen.
|
|
7
|
+
class UserRefusedConfirmationMessageError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("USER_REFUSED_INTERACTION", "User cancelled on confirmationMessage screen")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/smart_id_ruby/errors/user_refused_confirmation_message_with_verification_choice_error.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is USER_REFUSED_INTERACTION.
|
|
6
|
+
# This happens when user presses Cancel on confirmation and verification code choice screen.
|
|
7
|
+
class UserRefusedConfirmationMessageWithVerificationChoiceError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("USER_REFUSED_INTERACTION", "User cancelled on confirmationMessageAndVerificationCodeChoice screen")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is USER_REFUSED_INTERACTION.
|
|
6
|
+
# This happens when user presses Cancel on display text and PIN screen.
|
|
7
|
+
class UserRefusedDisplayTextAndPinError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("USER_REFUSED_INTERACTION", "User pressed Cancel on PIN screen.")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is USER_REFUSED.
|
|
6
|
+
class UserRefusedError < SessionEndResultError
|
|
7
|
+
def initialize
|
|
8
|
+
super("USER_REFUSED", "User pressed cancel in app")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SmartIdRuby
|
|
4
|
+
module Errors
|
|
5
|
+
# Thrown when session status end result is WRONG_VC.
|
|
6
|
+
# This happens when user selects wrong verification code in the app.
|
|
7
|
+
class UserSelectedWrongVerificationCodeError < SessionEndResultError
|
|
8
|
+
def initialize
|
|
9
|
+
super("WRONG_VC", "User selected wrong verification code")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "errors/error"
|
|
4
|
+
require_relative "errors/session_not_found_error"
|
|
5
|
+
require_relative "errors/relying_party_account_configuration_error"
|
|
6
|
+
require_relative "errors/user_account_not_found_error"
|
|
7
|
+
require_relative "errors/server_maintenance_error"
|
|
8
|
+
require_relative "errors/person_should_view_smart_id_portal_error"
|
|
9
|
+
require_relative "errors/no_suitable_account_of_requested_type_found_error"
|
|
10
|
+
require_relative "errors/unsupported_client_api_version_error"
|
|
11
|
+
require_relative "errors/request_validation_error"
|
|
12
|
+
require_relative "errors/request_setup_error"
|
|
13
|
+
require_relative "errors/response_error"
|
|
14
|
+
require_relative "errors/unprocessable_response_error"
|
|
15
|
+
require_relative "errors/document_unusable_error"
|
|
16
|
+
require_relative "errors/certificate_level_mismatch_error"
|
|
17
|
+
require_relative "errors/session_not_complete_error"
|
|
18
|
+
require_relative "errors/session_end_result_error"
|
|
19
|
+
require_relative "errors/session_secret_mismatch_error"
|
|
20
|
+
require_relative "errors/user_refused_error"
|
|
21
|
+
require_relative "errors/session_timeout_error"
|
|
22
|
+
require_relative "errors/user_selected_wrong_verification_code_error"
|
|
23
|
+
require_relative "errors/required_interaction_not_supported_by_app_error"
|
|
24
|
+
require_relative "errors/user_refused_cert_choice_error"
|
|
25
|
+
require_relative "errors/protocol_failure_error"
|
|
26
|
+
require_relative "errors/expected_linked_session_error"
|
|
27
|
+
require_relative "errors/smart_id_server_error"
|
|
28
|
+
require_relative "errors/user_account_unusable_error"
|
|
29
|
+
require_relative "errors/user_refused_display_text_and_pin_error"
|
|
30
|
+
require_relative "errors/user_refused_confirmation_message_error"
|
|
31
|
+
require_relative "errors/user_refused_confirmation_message_with_verification_choice_error"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
module SmartIdRuby
|
|
7
|
+
module Flows
|
|
8
|
+
# Base builder with shared helper methods for request builders.
|
|
9
|
+
class BaseBuilder
|
|
10
|
+
attr_reader :connector, :relying_party_uuid, :relying_party_name
|
|
11
|
+
|
|
12
|
+
def initialize(connector)
|
|
13
|
+
@connector = connector
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def with_relying_party_uuid(value)
|
|
17
|
+
@relying_party_uuid = value
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def with_relying_party_name(value)
|
|
22
|
+
@relying_party_name = value
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def blank?(value)
|
|
29
|
+
value.nil? || value.to_s.strip.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def fetch_value(container, key)
|
|
33
|
+
return nil if container.nil?
|
|
34
|
+
|
|
35
|
+
key_str = key.to_s
|
|
36
|
+
snake_key = underscore_key(key_str)
|
|
37
|
+
candidates = [key, key_str, snake_key.to_sym, snake_key].uniq
|
|
38
|
+
|
|
39
|
+
if container.respond_to?(:[])
|
|
40
|
+
candidates.each do |candidate|
|
|
41
|
+
value = container[candidate]
|
|
42
|
+
return value unless value.nil?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
candidates.each do |candidate|
|
|
47
|
+
method_name = candidate.is_a?(Symbol) ? candidate : candidate.to_s
|
|
48
|
+
return container.public_send(method_name) if container.respond_to?(method_name)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def normalize_interactions(interactions)
|
|
55
|
+
Array(interactions).compact.map { |interaction| normalize_interaction(interaction) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def normalize_interaction(interaction)
|
|
59
|
+
if interaction.respond_to?(:to_h)
|
|
60
|
+
interaction.to_h.transform_keys(&:to_sym)
|
|
61
|
+
elsif interaction.is_a?(Hash)
|
|
62
|
+
interaction.transform_keys(&:to_sym)
|
|
63
|
+
else
|
|
64
|
+
raise SmartIdRuby::Errors::RequestSetupError, "Unsupported interaction object type: #{interaction.class}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def encode_interactions(interactions)
|
|
69
|
+
Base64.strict_encode64(JSON.generate(normalize_interactions(interactions)))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def normalize_capabilities(capabilities, strip: true, reject_empty: true)
|
|
73
|
+
values = Array(capabilities).flatten.compact.map(&:to_s)
|
|
74
|
+
values = values.map(&:strip) if strip
|
|
75
|
+
values = values.reject(&:empty?) if reject_empty
|
|
76
|
+
values.uniq
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def request_properties_for_share_md(share_md_client_ip_address)
|
|
80
|
+
return nil if share_md_client_ip_address.nil?
|
|
81
|
+
|
|
82
|
+
{ shareMdClientIpAddress: share_md_client_ip_address }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def underscore_key(value)
|
|
86
|
+
value.to_s.gsub(/([A-Z])/, "_\\1").downcase.sub(/\A_/, "")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|