evoleap-licensing 1.0.0.12

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 (31) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +480 -0
  3. data/lib/evoleap_licensing/configuration.rb +34 -0
  4. data/lib/evoleap_licensing/control_logic.rb +38 -0
  5. data/lib/evoleap_licensing/control_manager_helper.rb +230 -0
  6. data/lib/evoleap_licensing/control_strategy.rb +16 -0
  7. data/lib/evoleap_licensing/encryption_handler.rb +42 -0
  8. data/lib/evoleap_licensing/errors.rb +9 -0
  9. data/lib/evoleap_licensing/identity/instance_identity.rb +39 -0
  10. data/lib/evoleap_licensing/identity/user_identity.rb +32 -0
  11. data/lib/evoleap_licensing/platform_info.rb +75 -0
  12. data/lib/evoleap_licensing/results/component_checkin_result.rb +16 -0
  13. data/lib/evoleap_licensing/results/component_checkout_result.rb +18 -0
  14. data/lib/evoleap_licensing/results/components_status.rb +18 -0
  15. data/lib/evoleap_licensing/results/instance_validity.rb +46 -0
  16. data/lib/evoleap_licensing/results/license_info.rb +19 -0
  17. data/lib/evoleap_licensing/results/registration_result.rb +16 -0
  18. data/lib/evoleap_licensing/results/session_validity.rb +47 -0
  19. data/lib/evoleap_licensing/server_control_manager.rb +50 -0
  20. data/lib/evoleap_licensing/state/server_state.rb +78 -0
  21. data/lib/evoleap_licensing/state/session_state.rb +68 -0
  22. data/lib/evoleap_licensing/state/user_state.rb +78 -0
  23. data/lib/evoleap_licensing/types/component_license_model.rb +22 -0
  24. data/lib/evoleap_licensing/types/invalid_reason.rb +49 -0
  25. data/lib/evoleap_licensing/types/validation_status.rb +91 -0
  26. data/lib/evoleap_licensing/user_control_manager.rb +198 -0
  27. data/lib/evoleap_licensing/version.rb +6 -0
  28. data/lib/evoleap_licensing/web_client.rb +65 -0
  29. data/lib/evoleap_licensing/web_service.rb +168 -0
  30. data/lib/evoleap_licensing.rb +41 -0
  31. metadata +129 -0
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module EvoleapLicensing
6
+ class ServerState
7
+ attr_accessor :instance_guid, :first_launch_time, :registered_at,
8
+ :grace_period_for_validation_failures,
9
+ :last_successful_validation_time, :last_validation_status,
10
+ :number_of_failed_validation_attempts, :features
11
+
12
+ attr_reader :failed_registration_times, :failed_validation_times
13
+
14
+ def initialize(hash = nil)
15
+ hash = (hash || {}).transform_keys(&:to_s)
16
+ @instance_guid = hash["instance_guid"]
17
+ @first_launch_time = parse_time(hash["first_launch_time"])
18
+ @registered_at = parse_time(hash["registered_at"])
19
+ @grace_period_for_validation_failures = hash["grace_period_for_validation_failures"]
20
+ @last_successful_validation_time = parse_time(hash["last_successful_validation_time"])
21
+ @last_validation_status = hash["last_validation_status"]
22
+ @number_of_failed_validation_attempts = hash["number_of_failed_validation_attempts"] || 0
23
+ @features = hash["features"] || []
24
+ @failed_registration_times = (hash["failed_registration_times"] || []).map { |t| parse_time(t) }.compact
25
+ @failed_validation_times = (hash["failed_validation_times"] || []).map { |t| parse_time(t) }.compact
26
+ end
27
+
28
+ def registered?
29
+ !@registered_at.nil?
30
+ end
31
+
32
+ def add_registration_failure(time = Time.now.utc)
33
+ @failed_registration_times.unshift(time)
34
+ end
35
+
36
+ def reset_registration_failures
37
+ @failed_registration_times = []
38
+ end
39
+
40
+ def add_validation_failure(time = Time.now.utc)
41
+ @failed_validation_times.unshift(time)
42
+ end
43
+
44
+ def reset_validation_failures
45
+ @failed_validation_times = []
46
+ @number_of_failed_validation_attempts = 0
47
+ end
48
+
49
+ def take_registration_params(response)
50
+ @instance_guid = response["instance_guid"]
51
+ end
52
+
53
+ def to_h
54
+ {
55
+ "instance_guid" => @instance_guid,
56
+ "first_launch_time" => @first_launch_time&.iso8601,
57
+ "registered_at" => @registered_at&.iso8601,
58
+ "grace_period_for_validation_failures" => @grace_period_for_validation_failures,
59
+ "last_successful_validation_time" => @last_successful_validation_time&.iso8601,
60
+ "last_validation_status" => @last_validation_status,
61
+ "number_of_failed_validation_attempts" => @number_of_failed_validation_attempts,
62
+ "features" => @features,
63
+ "failed_registration_times" => @failed_registration_times.map(&:iso8601),
64
+ "failed_validation_times" => @failed_validation_times.map(&:iso8601)
65
+ }
66
+ end
67
+
68
+ private
69
+
70
+ def parse_time(value)
71
+ return nil if value.nil?
72
+ return value if value.is_a?(Time)
73
+ Time.parse(value.to_s)
74
+ rescue ArgumentError
75
+ nil
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ class SessionState
5
+ attr_accessor :auth_token, :session_key, :session_duration,
6
+ :features, :feature_groups,
7
+ :components, :component_entitlements
8
+
9
+ def initialize(hash = nil)
10
+ hash = (hash || {}).transform_keys(&:to_s)
11
+ @auth_token = hash["auth_token"]
12
+ @session_key = hash["session_key"]
13
+ @session_duration = hash["session_duration"]
14
+ @features = hash["features"] || []
15
+ @feature_groups = hash["feature_groups"] || []
16
+ @components = hash["components"] || []
17
+ @component_entitlements = hash["component_entitlements"] || []
18
+ end
19
+
20
+ def active?
21
+ !@auth_token.nil? && !@session_key.nil?
22
+ end
23
+
24
+ def clear!
25
+ @auth_token = nil
26
+ @session_key = nil
27
+ @session_duration = nil
28
+ @features = []
29
+ @feature_groups = []
30
+ @components = []
31
+ @component_entitlements = []
32
+ end
33
+
34
+ def update_from_session_response(response)
35
+ @auth_token = response["token"] if response["token"]
36
+ @session_key = response["session_key"] if response["session_key"]
37
+ @session_duration = response["session_duration"] if response["session_duration"]
38
+ @features = response["features"] if response["features"]
39
+ @feature_groups = response["feature_groups"] if response["feature_groups"]
40
+ update_components_from_response(response)
41
+ end
42
+
43
+ def update_from_extend_response(response)
44
+ @auth_token = response["token"] if response["token"]
45
+ @session_duration = response["session_duration"] if response["session_duration"]
46
+ @features = response["features"] if response["features"]
47
+ @feature_groups = response["feature_groups"] if response["feature_groups"]
48
+ update_components_from_response(response)
49
+ end
50
+
51
+ def update_components_from_response(response)
52
+ @components = response["components"] if response["components"]
53
+ @component_entitlements = response["component_entitlements"] if response["component_entitlements"]
54
+ end
55
+
56
+ def to_h
57
+ {
58
+ "auth_token" => @auth_token,
59
+ "session_key" => @session_key,
60
+ "session_duration" => @session_duration,
61
+ "features" => @features,
62
+ "feature_groups" => @feature_groups,
63
+ "components" => @components,
64
+ "component_entitlements" => @component_entitlements
65
+ }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module EvoleapLicensing
6
+ class UserState
7
+ attr_accessor :user_guid, :first_launch_time, :registered_at,
8
+ :grace_period_for_validation_failures,
9
+ :last_successful_validation_time, :last_validation_status,
10
+ :number_of_failed_validation_attempts, :features
11
+
12
+ attr_reader :failed_registration_times, :failed_validation_times
13
+
14
+ def initialize(hash = nil)
15
+ hash = (hash || {}).transform_keys(&:to_s)
16
+ @user_guid = hash["user_guid"]
17
+ @first_launch_time = parse_time(hash["first_launch_time"])
18
+ @registered_at = parse_time(hash["registered_at"])
19
+ @grace_period_for_validation_failures = hash["grace_period_for_validation_failures"]
20
+ @last_successful_validation_time = parse_time(hash["last_successful_validation_time"])
21
+ @last_validation_status = hash["last_validation_status"]
22
+ @number_of_failed_validation_attempts = hash["number_of_failed_validation_attempts"] || 0
23
+ @features = hash["features"] || []
24
+ @failed_registration_times = (hash["failed_registration_times"] || []).map { |t| parse_time(t) }.compact
25
+ @failed_validation_times = (hash["failed_validation_times"] || []).map { |t| parse_time(t) }.compact
26
+ end
27
+
28
+ def registered?
29
+ !@registered_at.nil?
30
+ end
31
+
32
+ def add_registration_failure(time = Time.now.utc)
33
+ @failed_registration_times.unshift(time)
34
+ end
35
+
36
+ def reset_registration_failures
37
+ @failed_registration_times = []
38
+ end
39
+
40
+ def add_validation_failure(time = Time.now.utc)
41
+ @failed_validation_times.unshift(time)
42
+ end
43
+
44
+ def reset_validation_failures
45
+ @failed_validation_times = []
46
+ @number_of_failed_validation_attempts = 0
47
+ end
48
+
49
+ def take_registration_params(response)
50
+ @user_guid = response["user_guid"]
51
+ end
52
+
53
+ def to_h
54
+ {
55
+ "user_guid" => @user_guid,
56
+ "first_launch_time" => @first_launch_time&.iso8601,
57
+ "registered_at" => @registered_at&.iso8601,
58
+ "grace_period_for_validation_failures" => @grace_period_for_validation_failures,
59
+ "last_successful_validation_time" => @last_successful_validation_time&.iso8601,
60
+ "last_validation_status" => @last_validation_status,
61
+ "number_of_failed_validation_attempts" => @number_of_failed_validation_attempts,
62
+ "features" => @features,
63
+ "failed_registration_times" => @failed_registration_times.map(&:iso8601),
64
+ "failed_validation_times" => @failed_validation_times.map(&:iso8601)
65
+ }
66
+ end
67
+
68
+ private
69
+
70
+ def parse_time(value)
71
+ return nil if value.nil?
72
+ return value if value.is_a?(Time)
73
+ Time.parse(value.to_s)
74
+ rescue ArgumentError
75
+ nil
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ module ComponentLicenseModel
5
+ NONE = :none
6
+ TOKEN = :token
7
+ SESSION = :session
8
+ CONSUMABLE_TOKEN = :consumable_token
9
+ UNKNOWN = :unknown
10
+
11
+ FROM_STRING = {
12
+ "None" => NONE,
13
+ "Token" => TOKEN,
14
+ "Session" => SESSION,
15
+ "ConsumableToken" => CONSUMABLE_TOKEN
16
+ }.freeze
17
+
18
+ def self.from_string(str)
19
+ FROM_STRING[str] || UNKNOWN
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ module InvalidReason
5
+ REGISTRATION_REQUIRED = :registration_required
6
+ USER_TAMPERING_DETECTED = :user_tampering_detected
7
+ SERVICE_UNREACHABLE = :service_unreachable
8
+ LICENSE_EXPIRED = :license_expired
9
+ INSTANCE_DISABLED = :instance_disabled
10
+ USER_DISABLED = :user_disabled
11
+ INVALID_LICENSE_KEY = :invalid_license_key
12
+ INVALID_PRODUCT_ID = :invalid_product_id
13
+ INSTANCE_NOT_REGISTERED = :instance_not_registered
14
+ USER_NOT_REGISTERED = :user_not_registered
15
+ INCONSISTENT_REGISTRATION = :inconsistent_registration
16
+ INCONSISTENT_USER = :inconsistent_user
17
+ NO_SEATS_AVAILABLE = :no_seats_available
18
+ SESSION_REVOKED = :session_revoked
19
+ ACTIVATION_PENDING = :activation_pending
20
+ INSUFFICIENT_TOKENS = :insufficient_tokens
21
+ INVALID_COMPONENT = :invalid_component
22
+
23
+ # Map ValidationStatus integers to InvalidReason symbols
24
+ FROM_VALIDATION_STATUS = {
25
+ ValidationStatus::REGISTRATION_REQUIRED => REGISTRATION_REQUIRED,
26
+ ValidationStatus::USER_TAMPERING_DETECTED => USER_TAMPERING_DETECTED,
27
+ ValidationStatus::SERVICE_UNREACHABLE => SERVICE_UNREACHABLE,
28
+ ValidationStatus::LICENSE_EXPIRED => LICENSE_EXPIRED,
29
+ ValidationStatus::INSTANCE_DISABLED => INSTANCE_DISABLED,
30
+ ValidationStatus::USER_DISABLED => USER_DISABLED,
31
+ ValidationStatus::INVALID_LICENSE_KEY => INVALID_LICENSE_KEY,
32
+ ValidationStatus::INVALID_PRODUCT_ID => INVALID_PRODUCT_ID,
33
+ ValidationStatus::INSTANCE_NOT_REGISTERED => INSTANCE_NOT_REGISTERED,
34
+ ValidationStatus::USER_NOT_REGISTERED => USER_NOT_REGISTERED,
35
+ ValidationStatus::INCONSISTENT_REGISTRATION => INCONSISTENT_REGISTRATION,
36
+ ValidationStatus::INCONSISTENT_USER => INCONSISTENT_USER,
37
+ ValidationStatus::NO_SEATS_AVAILABLE => NO_SEATS_AVAILABLE,
38
+ ValidationStatus::SESSION_REVOKED => SESSION_REVOKED,
39
+ ValidationStatus::ACTIVATION_PENDING => ACTIVATION_PENDING,
40
+ ValidationStatus::INSUFFICIENT_TOKENS => INSUFFICIENT_TOKENS,
41
+ ValidationStatus::INVALID_COMPONENT => INVALID_COMPONENT,
42
+ ValidationStatus::GENERAL_ERROR => SERVICE_UNREACHABLE
43
+ }.freeze
44
+
45
+ def self.from_validation_status(status)
46
+ FROM_VALIDATION_STATUS[status] || SERVICE_UNREACHABLE
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ module ValidationStatus
5
+ # Client-only statuses
6
+ REGISTRATION_REQUIRED = -101
7
+ USER_TAMPERING_DETECTED = -100
8
+ SERVICE_UNREACHABLE = -99
9
+
10
+ # Server-provided statuses
11
+ FULL_LICENSE_ALREADY_CHECKED_OUT = -17
12
+ OFFLINE_CHECKOUT_NOT_SUPPORTED = -16
13
+ INVALID_COMPONENT = -15
14
+ INSUFFICIENT_TOKENS = -14
15
+ ACTIVATION_PENDING = -13
16
+ SESSION_REVOKED = -12
17
+ NO_SEATS_AVAILABLE = -11
18
+ INCONSISTENT_REGISTRATION = -10
19
+ INCONSISTENT_USER = -9
20
+ INSTANCE_NOT_REGISTERED = -8
21
+ USER_NOT_REGISTERED = -7
22
+ INVALID_LICENSE_KEY = -6
23
+ INVALID_PRODUCT_ID = -5
24
+ INSTANCE_DISABLED = -4
25
+ USER_DISABLED = -3
26
+ LICENSE_EXPIRED = -2
27
+ GENERAL_ERROR = -1
28
+ SUCCESS = 0
29
+
30
+ ALL = {
31
+ registration_required: REGISTRATION_REQUIRED,
32
+ user_tampering_detected: USER_TAMPERING_DETECTED,
33
+ service_unreachable: SERVICE_UNREACHABLE,
34
+ full_license_already_checked_out: FULL_LICENSE_ALREADY_CHECKED_OUT,
35
+ offline_checkout_not_supported: OFFLINE_CHECKOUT_NOT_SUPPORTED,
36
+ invalid_component: INVALID_COMPONENT,
37
+ insufficient_tokens: INSUFFICIENT_TOKENS,
38
+ activation_pending: ACTIVATION_PENDING,
39
+ session_revoked: SESSION_REVOKED,
40
+ no_seats_available: NO_SEATS_AVAILABLE,
41
+ inconsistent_registration: INCONSISTENT_REGISTRATION,
42
+ inconsistent_user: INCONSISTENT_USER,
43
+ instance_not_registered: INSTANCE_NOT_REGISTERED,
44
+ user_not_registered: USER_NOT_REGISTERED,
45
+ invalid_license_key: INVALID_LICENSE_KEY,
46
+ invalid_product_id: INVALID_PRODUCT_ID,
47
+ instance_disabled: INSTANCE_DISABLED,
48
+ user_disabled: USER_DISABLED,
49
+ license_expired: LICENSE_EXPIRED,
50
+ general_error: GENERAL_ERROR,
51
+ success: SUCCESS
52
+ }.freeze
53
+
54
+ BY_VALUE = ALL.invert.freeze
55
+
56
+ def self.name_for(value)
57
+ BY_VALUE[value]
58
+ end
59
+
60
+ # Convenience class methods matching old Enum API
61
+ def self.registration_required; REGISTRATION_REQUIRED; end
62
+ def self.user_tampering_detected; USER_TAMPERING_DETECTED; end
63
+ def self.service_unreachable; SERVICE_UNREACHABLE; end
64
+ def self.activation_pending; ACTIVATION_PENDING; end
65
+ def self.session_revoked; SESSION_REVOKED; end
66
+ def self.no_seats_available; NO_SEATS_AVAILABLE; end
67
+ def self.inconsistent_registration; INCONSISTENT_REGISTRATION; end
68
+ def self.inconsistent_user; INCONSISTENT_USER; end
69
+ def self.instance_not_registered; INSTANCE_NOT_REGISTERED; end
70
+ def self.user_not_registered; USER_NOT_REGISTERED; end
71
+ def self.invalid_license_key; INVALID_LICENSE_KEY; end
72
+ def self.invalid_product_id; INVALID_PRODUCT_ID; end
73
+ def self.instance_disabled; INSTANCE_DISABLED; end
74
+ def self.user_disabled; USER_DISABLED; end
75
+ def self.license_expired; LICENSE_EXPIRED; end
76
+ def self.general_error; GENERAL_ERROR; end
77
+ def self.success; SUCCESS; end
78
+ def self.insufficient_tokens; INSUFFICIENT_TOKENS; end
79
+ def self.invalid_component; INVALID_COMPONENT; end
80
+ def self.offline_checkout_not_supported; OFFLINE_CHECKOUT_NOT_SUPPORTED; end
81
+ def self.full_license_already_checked_out; FULL_LICENSE_ALREADY_CHECKED_OUT; end
82
+
83
+ def self.success?(value)
84
+ value == SUCCESS
85
+ end
86
+
87
+ def self.client_only?(value)
88
+ value <= SERVICE_UNREACHABLE
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ class UserControlManager
5
+ attr_reader :product_id, :version, :instance_id, :public_key,
6
+ :strategy, :user_state, :session_state
7
+
8
+ def initialize(product_id:, version:, instance_id:, public_key:,
9
+ strategy: nil, user_state: nil, session_state: nil)
10
+ @product_id = product_id
11
+ @version = version
12
+ @instance_id = instance_id
13
+ @public_key = public_key
14
+ @strategy = strategy || ControlStrategy.default
15
+ @user_state = user_state || UserState.new
16
+ @session_state = session_state || SessionState.new
17
+ @client = WebClient.new
18
+ end
19
+
20
+ # Register a user against the server instance.
21
+ # Returns a RegistrationResult.
22
+ def register(user_info:, user_identity:)
23
+ ControlManagerHelper.register(@user_state) do
24
+ WebService.register_user(
25
+ product_id: @product_id,
26
+ instance_id: @instance_id,
27
+ user_info: user_info,
28
+ user_identity: user_identity.to_api_format,
29
+ public_key: @public_key,
30
+ client: @client
31
+ )
32
+ end
33
+ end
34
+
35
+ # Begin or extend a user session.
36
+ # Returns a SessionValidity.
37
+ def validate_session(user_identity:, requested_duration: nil)
38
+ ControlManagerHelper.validate_session(@strategy, @user_state, @session_state,
39
+ -> { make_session_call(user_identity, requested_duration) })
40
+ end
41
+
42
+ # End the active session.
43
+ def end_session
44
+ raise NoActiveSessionError, "No active session to end" unless @session_state.active?
45
+
46
+ response = WebService.end_session(
47
+ product_id: @product_id,
48
+ auth_token: @session_state.auth_token,
49
+ session_key: @session_state.session_key,
50
+ public_key: @public_key,
51
+ client: @client
52
+ )
53
+
54
+ @session_state.clear!
55
+ !response.key?("error")
56
+ end
57
+
58
+ # Check out named components for the active session.
59
+ # Returns a ComponentCheckoutResult.
60
+ def check_out_components(*component_names)
61
+ raise NoActiveSessionError, "No active session" unless @session_state.active?
62
+
63
+ response = WebService.check_out_components(
64
+ product_id: @product_id,
65
+ auth_token: @session_state.auth_token,
66
+ session_key: @session_state.session_key,
67
+ component_names: component_names.flatten,
68
+ public_key: @public_key,
69
+ client: @client
70
+ )
71
+
72
+ if response["status"] == ValidationStatus::SUCCESS
73
+ @session_state.update_components_from_response(response)
74
+ ComponentCheckoutResult.new(
75
+ success: true,
76
+ components: response["components"] || [],
77
+ component_entitlements: response["component_entitlements"] || []
78
+ )
79
+ else
80
+ ComponentCheckoutResult.new(
81
+ success: false,
82
+ failure_reason: InvalidReason.from_validation_status(response["status"])
83
+ )
84
+ end
85
+ end
86
+
87
+ # Check in named components.
88
+ # Returns a ComponentCheckinResult.
89
+ def check_in_components(*component_names)
90
+ raise NoActiveSessionError, "No active session" unless @session_state.active?
91
+
92
+ response = WebService.check_in_components(
93
+ product_id: @product_id,
94
+ auth_token: @session_state.auth_token,
95
+ session_key: @session_state.session_key,
96
+ component_names: component_names.flatten,
97
+ public_key: @public_key,
98
+ client: @client
99
+ )
100
+
101
+ if response["status"] == ValidationStatus::SUCCESS
102
+ @session_state.update_components_from_response(response)
103
+ ComponentCheckinResult.new(success: true)
104
+ else
105
+ ComponentCheckinResult.new(
106
+ success: false,
107
+ failure_reason: InvalidReason.from_validation_status(response["status"])
108
+ )
109
+ end
110
+ end
111
+
112
+ # Get status of all components.
113
+ # Returns a ComponentsStatus.
114
+ def components_status
115
+ raise NoActiveSessionError, "No active session" unless @session_state.active?
116
+
117
+ response = WebService.components_status(
118
+ product_id: @product_id,
119
+ auth_token: @session_state.auth_token,
120
+ session_key: @session_state.session_key,
121
+ public_key: @public_key,
122
+ client: @client
123
+ )
124
+
125
+ if response["status"] == ValidationStatus::SUCCESS
126
+ ComponentsStatus.new(
127
+ success: true,
128
+ components: response["components"] || [],
129
+ component_entitlements: response["component_entitlements"] || []
130
+ )
131
+ else
132
+ ComponentsStatus.new(
133
+ success: false,
134
+ error_message: response["error"]
135
+ )
136
+ end
137
+ end
138
+
139
+ # Get license info for the active session.
140
+ # Returns a LicenseInfo.
141
+ def license_info
142
+ raise NoActiveSessionError, "No active session" unless @session_state.active?
143
+
144
+ response = WebService.get_license_info(
145
+ product_id: @product_id,
146
+ auth_token: @session_state.auth_token,
147
+ session_key: @session_state.session_key,
148
+ public_key: @public_key,
149
+ client: @client
150
+ )
151
+
152
+ if response["status"] == ValidationStatus::SUCCESS
153
+ LicenseInfo.new(
154
+ success: true,
155
+ owner_name: response["owner_name"],
156
+ owner_logo_url: response["owner_logo_url"],
157
+ expiry: response["expiry"]
158
+ )
159
+ else
160
+ LicenseInfo.new(
161
+ success: false,
162
+ error_message: response["error"]
163
+ )
164
+ end
165
+ end
166
+
167
+ # For testing: allow injecting a custom web client
168
+ def web_client=(client)
169
+ @client = client
170
+ end
171
+
172
+ private
173
+
174
+ def make_session_call(user_identity, requested_duration)
175
+ if @session_state.active?
176
+ # Extend existing session
177
+ WebService.extend_session(
178
+ product_id: @product_id,
179
+ auth_token: @session_state.auth_token,
180
+ session_key: @session_state.session_key,
181
+ public_key: @public_key,
182
+ client: @client,
183
+ session_duration: requested_duration
184
+ )
185
+ else
186
+ # Begin new session
187
+ WebService.begin_user_session(
188
+ product_id: @product_id,
189
+ instance_id: @instance_id,
190
+ user_identity: user_identity.to_api_format,
191
+ public_key: @public_key,
192
+ client: @client,
193
+ session_duration: requested_duration
194
+ )
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EvoleapLicensing
4
+ VERSION = "1.0.0.12"
5
+ end
6
+
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module EvoleapLicensing
8
+ class WebClient
9
+ ENDPOINTS = {
10
+ register_instance: "register_instance",
11
+ validate_instance: "validate_instance",
12
+ register_user: "register_user",
13
+ begin_user_session: "begin_user_session",
14
+ extend_session: "extend_session",
15
+ end_session: "end_session",
16
+ check_out_components: "check_out_components",
17
+ check_in_components: "check_in_components",
18
+ components_status: "components_status",
19
+ get_license_info: "get_license_info"
20
+ }.freeze
21
+
22
+ attr_accessor :base_url, :timeout
23
+
24
+ def initialize(base_url: nil, timeout: nil)
25
+ config = EvoleapLicensing.configuration
26
+ @base_url = base_url || config.api_base_url
27
+ @timeout = timeout || config.timeout
28
+ end
29
+
30
+ ENDPOINTS.each do |method_name, _endpoint|
31
+ define_method(method_name) do |key, encrypted_params|
32
+ post(method_name, key, encrypted_params)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def post(action, key, encrypted_params)
39
+ url = URI("#{@base_url}/#{ENDPOINTS[action]}")
40
+ http = Net::HTTP.new(url.host, url.port)
41
+ http.use_ssl = url.scheme == "https"
42
+ http.open_timeout = @timeout
43
+ http.read_timeout = @timeout
44
+
45
+ request = Net::HTTP::Post.new(url)
46
+ request["Content-Type"] = "application/json"
47
+ request["User-Agent"] = EvoleapLicensing.configuration.user_agent
48
+ request.body = { key: key, data: encrypted_params }.to_json
49
+
50
+ response = http.request(request)
51
+
52
+ case response
53
+ when Net::HTTPSuccess
54
+ response.body
55
+ when Net::HTTPInternalServerError
56
+ raise ServerError, "Server error: #{response.code} #{response.message}"
57
+ else
58
+ raise ApiError, "API error: #{response.code} #{response.message}"
59
+ end
60
+ end
61
+
62
+ class ServerError < EvoleapLicensing::Error; end
63
+ class ApiError < EvoleapLicensing::Error; end
64
+ end
65
+ end