kameleoon-client-ruby 3.18.0 → 3.19.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 +4 -4
- data/lib/kameleoon/configuration/data_file.rb +9 -4
- data/lib/kameleoon/configuration/variable.rb +12 -0
- data/lib/kameleoon/configuration/variation.rb +1 -1
- data/lib/kameleoon/data/manager/visitor_manager.rb +10 -0
- data/lib/kameleoon/kameleoon_client.rb +18 -71
- data/lib/kameleoon/managers/data/data_manager.rb +16 -2
- data/lib/kameleoon/managers/tracking/tracking_builder.rb +1 -1
- data/lib/kameleoon/network/access_token_source.rb +9 -1
- data/lib/kameleoon/network/net_provider.rb +4 -1
- data/lib/kameleoon/network/network_manager.rb +2 -3
- data/lib/kameleoon/network/request.rb +6 -3
- data/lib/kameleoon/network/url_provider.rb +21 -3
- data/lib/kameleoon/targeting/conditions/unknown_condition.rb +1 -0
- data/lib/kameleoon/types/data_file.rb +14 -3
- data/lib/kameleoon/types/feature_flag.rb +22 -0
- data/lib/kameleoon/types/rule.rb +21 -0
- data/lib/kameleoon/types/variable.rb +8 -0
- data/lib/kameleoon/types/variation.rb +12 -0
- data/lib/kameleoon/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dde5f6ebb9e6779b9bf8d4edbdded4e11b82aa642ec046bd2493306e0b2a7ad8
|
|
4
|
+
data.tar.gz: 5a15f627b2832ec10f001ef7ee061fa31c6dbd618b02ec55ff9d1d66ee17d5a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 91d3f34ab6855ed62d571fa5d40b85a04504926f2d38650c9b62f052bd9f0b79b0ce95ece6636fa37ecc5062020f2361bc5e0e8af80383b0d2b377dffd5919e7
|
|
7
|
+
data.tar.gz: c2e5efd80b73d5f8ce9c48a6f069aadda0fc7d1a6bc390a2d98af4a8a69b36928bac0188c77406bd793d8db6c4701df24838c67efc89b98d4d0e6b7e425b9c68
|
|
@@ -13,12 +13,13 @@ module Kameleoon
|
|
|
13
13
|
class DataFile
|
|
14
14
|
attr_reader :last_modified, :settings, :segments, :audience_tracking_segments, :feature_flags, :me_groups,
|
|
15
15
|
:has_any_targeted_delivery_rule, :feature_flag_by_id, :rule_info_by_exp_id, :variation_by_id,
|
|
16
|
-
:custom_data_info, :experiment_ids_with_js_css_variable, :holdout
|
|
16
|
+
:custom_data_info, :experiment_ids_with_js_css_variable, :holdout, :date_modified
|
|
17
17
|
|
|
18
18
|
def to_s
|
|
19
19
|
'DataFile{' \
|
|
20
20
|
"environment:#{@environment}," \
|
|
21
21
|
"last_modified:#{@last_modified}," \
|
|
22
|
+
"date_modified:#{@date_modified}," \
|
|
22
23
|
"feature_flags:#{@feature_flags.size}," \
|
|
23
24
|
"settings:#{@settings}" \
|
|
24
25
|
'}'
|
|
@@ -46,13 +47,15 @@ module Kameleoon
|
|
|
46
47
|
def get_feature_flag(feature_key)
|
|
47
48
|
ff = @feature_flags[feature_key]
|
|
48
49
|
raise Exception::FeatureNotFound, feature_key if ff.nil?
|
|
50
|
+
ff
|
|
51
|
+
end
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
def ensure_environment_enabled(feature_flag)
|
|
54
|
+
unless feature_flag.environment_enabled
|
|
51
55
|
env = @environment.nil? ? 'default' : "'#{@environment}'"
|
|
52
|
-
msg = "Feature '#{feature_key}' is disabled for #{env} environment'"
|
|
56
|
+
msg = "Feature '#{feature_flag.feature_key}' is disabled for #{env} environment'"
|
|
53
57
|
raise Exception::FeatureEnvironmentDisabled, msg
|
|
54
58
|
end
|
|
55
|
-
ff
|
|
56
59
|
end
|
|
57
60
|
|
|
58
61
|
def experiment_js_css_variable?(experiment_id)
|
|
@@ -63,6 +66,7 @@ module Kameleoon
|
|
|
63
66
|
|
|
64
67
|
def init_default
|
|
65
68
|
Logging::KameleoonLogger.debug('CALL: DataFile.init_default')
|
|
69
|
+
@date_modified = 0
|
|
66
70
|
@settings = Settings.new
|
|
67
71
|
@feature_flags = {}
|
|
68
72
|
@me_groups = {}
|
|
@@ -73,6 +77,7 @@ module Kameleoon
|
|
|
73
77
|
|
|
74
78
|
def init(configuration)
|
|
75
79
|
Logging::KameleoonLogger.debug('CALL: DataFile.init(configuration: %s)', configuration)
|
|
80
|
+
@date_modified = configuration['dateModified'] || 0
|
|
76
81
|
@settings = Settings.new(configuration['configuration'])
|
|
77
82
|
@segments, @audience_tracking_segments = parse_segments(configuration)
|
|
78
83
|
@custom_data_info = CustomDataInfo.new(configuration['customData'])
|
|
@@ -16,6 +16,18 @@ module Kameleoon
|
|
|
16
16
|
@type = hash['type']
|
|
17
17
|
@value = hash['value']
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
def get_value
|
|
21
|
+
case @type
|
|
22
|
+
when 'BOOLEAN', 'STRING', 'NUMBER', 'JS', 'CSS'
|
|
23
|
+
@value
|
|
24
|
+
when 'JSON'
|
|
25
|
+
JSON.parse(@value)
|
|
26
|
+
else
|
|
27
|
+
Logging::KameleoonLogger.error("Unknown type '#{@type}' for feature variable")
|
|
28
|
+
@value
|
|
29
|
+
end
|
|
30
|
+
end
|
|
19
31
|
end
|
|
20
32
|
end
|
|
21
33
|
end
|
|
@@ -64,6 +64,16 @@ module Kameleoon
|
|
|
64
64
|
visitor
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
def peek_visitor(visitor_code)
|
|
68
|
+
Logging::KameleoonLogger.debug("CALL: VisitorManager.peek_visitor(visitor_code: '%s')", visitor_code)
|
|
69
|
+
|
|
70
|
+
visitor = @visitors[visitor_code]
|
|
71
|
+
|
|
72
|
+
Logging::KameleoonLogger.debug("RETURN: VisitorManager.peek_visitor(visitor_code: '%s') -> (visitor: %s)",
|
|
73
|
+
visitor_code, visitor)
|
|
74
|
+
visitor
|
|
75
|
+
end
|
|
76
|
+
|
|
67
77
|
def enumerate(&blk)
|
|
68
78
|
@visitors.each_pair { |vc, v| blk.call(vc, v) }
|
|
69
79
|
end
|
|
@@ -369,8 +369,6 @@ module Kameleoon
|
|
|
369
369
|
Utils::VisitorCode.validate(visitor_code)
|
|
370
370
|
variations = {}
|
|
371
371
|
@data_manager.data_file.feature_flags.each_value do |feature_flag|
|
|
372
|
-
next unless feature_flag.environment_enabled
|
|
373
|
-
|
|
374
372
|
begin
|
|
375
373
|
variation_key, eval_exp = get_variation_info(visitor_code, feature_flag, track)
|
|
376
374
|
rescue Exception::FeatureEnvironmentDisabled
|
|
@@ -468,7 +466,7 @@ module Kameleoon
|
|
|
468
466
|
raise Exception::FeatureVariableNotFound.new(variable_name),
|
|
469
467
|
"Feature variable #{variable_name} not found"
|
|
470
468
|
end
|
|
471
|
-
value =
|
|
469
|
+
value = variable.get_value
|
|
472
470
|
Logging::KameleoonLogger.info(
|
|
473
471
|
"RETURN: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
|
|
474
472
|
'is_unique_identifier: %s) -> (variable: %s)',
|
|
@@ -503,12 +501,13 @@ module Kameleoon
|
|
|
503
501
|
)
|
|
504
502
|
feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
|
|
505
503
|
variation = feature_flag.get_variation_by_key(variation_key)
|
|
504
|
+
@data_manager.data_file.ensure_environment_enabled(feature_flag)
|
|
506
505
|
if variation.nil?
|
|
507
506
|
raise Exception::FeatureVariationNotFound.new(variation_key),
|
|
508
507
|
"Variation key #{variation_key} not found"
|
|
509
508
|
end
|
|
510
509
|
variables = {}
|
|
511
|
-
variation.variables.each { |var| variables[var.key] =
|
|
510
|
+
variation.variables.each { |var| variables[var.key] = var.get_value }
|
|
512
511
|
Logging::KameleoonLogger.info(
|
|
513
512
|
"RETURN: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s') " \
|
|
514
513
|
'-> (variables: %s)', feature_key, variation_key, variables
|
|
@@ -607,12 +606,16 @@ module Kameleoon
|
|
|
607
606
|
)
|
|
608
607
|
warehouse_audience
|
|
609
608
|
end
|
|
610
|
-
|
|
611
609
|
##
|
|
612
|
-
# Returns a list of all feature flag keys
|
|
610
|
+
# Returns a list of all feature flag keys.
|
|
613
611
|
#
|
|
614
612
|
# @return [Array] array of all feature flag keys
|
|
613
|
+
#
|
|
614
|
+
# DEPRECATED. Please use `get_data_file` instead.
|
|
615
615
|
def get_feature_list # rubocop:disable Naming/AccessorMethodName
|
|
616
|
+
Logging::KameleoonLogger.info(
|
|
617
|
+
'[DEPRECATION] `get_feature_list` is deprecated. Please use `get_data_file` instead.'
|
|
618
|
+
)
|
|
616
619
|
Logging::KameleoonLogger.info('CALL: KameleoonClient.get_feature_list')
|
|
617
620
|
features = @data_manager.data_file.feature_flags.keys
|
|
618
621
|
Logging::KameleoonLogger.info('RETURN: KameleoonClient.get_feature_list -> (features: %s)', features)
|
|
@@ -638,8 +641,6 @@ module Kameleoon
|
|
|
638
641
|
visitor = @visitor_manager.get_visitor(visitor_code)
|
|
639
642
|
list_keys = []
|
|
640
643
|
@data_manager.data_file.feature_flags.each do |feature_key, feature_flag|
|
|
641
|
-
next unless feature_flag.environment_enabled
|
|
642
|
-
|
|
643
644
|
begin
|
|
644
645
|
eval_exp = evaluate(visitor, visitor_code, feature_flag, false, false)
|
|
645
646
|
rescue Exception::FeatureEnvironmentDisabled
|
|
@@ -677,8 +678,6 @@ module Kameleoon
|
|
|
677
678
|
map_active_features = {}
|
|
678
679
|
|
|
679
680
|
@data_manager.data_file.feature_flags.each_value do |feature_flag|
|
|
680
|
-
next unless feature_flag.environment_enabled
|
|
681
|
-
|
|
682
681
|
begin
|
|
683
682
|
eval_exp = evaluate(visitor, visitor_code, feature_flag, false, false)
|
|
684
683
|
rescue Exception::FeatureEnvironmentDisabled
|
|
@@ -803,41 +802,7 @@ module Kameleoon
|
|
|
803
802
|
# @return [Kameleoon::Types::DataFile] The current DataFile instance.
|
|
804
803
|
def get_data_file
|
|
805
804
|
Logging::KameleoonLogger.info('CALL: KameleoonClient.get_data_file')
|
|
806
|
-
|
|
807
|
-
feature_flags_map = @data_manager.data_file.feature_flags.transform_values do |source_feature_flag|
|
|
808
|
-
# Collect variations
|
|
809
|
-
variations_map = source_feature_flag.variations.each_with_object({}) do |variation, variations_map|
|
|
810
|
-
variables_map = variation.variables.each_with_object({}) do |var, variables_map|
|
|
811
|
-
variables_map[var.key] = Types::Variable.new(var.key, var.type, _parse_feature_variable(var))
|
|
812
|
-
end
|
|
813
|
-
variations_map[variation.key] = Types::Variation.new(variation.key, nil, nil, variables_map, variation.name)
|
|
814
|
-
end
|
|
815
|
-
|
|
816
|
-
# Collect rules
|
|
817
|
-
rules = source_feature_flag.rules.map do |rule|
|
|
818
|
-
rule_variations = rule.experiment.variations_by_exposition.each_with_object({}) do |var_by_exp, rule_variations|
|
|
819
|
-
base_variation = variations_map[var_by_exp.variation_key]
|
|
820
|
-
next unless base_variation
|
|
821
|
-
rule_variations[base_variation.key] = Types::Variation.new(
|
|
822
|
-
base_variation.key,
|
|
823
|
-
var_by_exp.variation_id,
|
|
824
|
-
rule.experiment.id,
|
|
825
|
-
base_variation.variables,
|
|
826
|
-
base_variation.name
|
|
827
|
-
)
|
|
828
|
-
end
|
|
829
|
-
Types::Rule.new(rule_variations)
|
|
830
|
-
end
|
|
831
|
-
|
|
832
|
-
Types::FeatureFlag.new(
|
|
833
|
-
variations_map,
|
|
834
|
-
source_feature_flag.environment_enabled,
|
|
835
|
-
rules,
|
|
836
|
-
source_feature_flag.default_variation_key
|
|
837
|
-
)
|
|
838
|
-
end
|
|
839
|
-
|
|
840
|
-
data_file = Types::DataFile.new(feature_flags_map)
|
|
805
|
+
data_file = @data_manager.external_data_file
|
|
841
806
|
Logging::KameleoonLogger.info('RETURN: KameleoonClient.get_data_file -> (data_file: %s)', data_file)
|
|
842
807
|
data_file
|
|
843
808
|
end
|
|
@@ -1015,6 +980,11 @@ module Kameleoon
|
|
|
1015
980
|
)
|
|
1016
981
|
eval_exp = nil
|
|
1017
982
|
forced_variation = visitor&.get_forced_feature_variation(feature_flag.feature_key)
|
|
983
|
+
|
|
984
|
+
unless forced_variation&.simulated
|
|
985
|
+
@data_manager.data_file.ensure_environment_enabled(feature_flag)
|
|
986
|
+
end
|
|
987
|
+
|
|
1018
988
|
if forced_variation
|
|
1019
989
|
eval_exp = EvaluatedExperiment.from_forced_variation(forced_variation)
|
|
1020
990
|
elsif visitor_not_in_holdout?(visitor, visitor_code, track, save, feature_flag.bucketing_custom_data_index) && \
|
|
@@ -1276,21 +1246,10 @@ module Kameleoon
|
|
|
1276
1246
|
Logging::KameleoonLogger.debug(
|
|
1277
1247
|
'CALL: KameleoonClient.create_external_variation(variation: %s, eval_exp: %s)', variation, eval_exp
|
|
1278
1248
|
)
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
ext_variables[variable.key] = Types::Variable.new(
|
|
1282
|
-
variable.key,
|
|
1283
|
-
variable.type,
|
|
1284
|
-
_parse_feature_variable(variable)
|
|
1285
|
-
)
|
|
1286
|
-
end
|
|
1287
|
-
ext_variables.freeze
|
|
1288
|
-
ext_variation = Types::Variation.new(
|
|
1289
|
-
variation&.key || '',
|
|
1249
|
+
ext_variation = Types::Variation._build_from_internal(
|
|
1250
|
+
variation,
|
|
1290
1251
|
eval_exp&.var_by_exp&.variation_id,
|
|
1291
|
-
eval_exp&.experiment&.id
|
|
1292
|
-
ext_variables,
|
|
1293
|
-
variation&.name || ''
|
|
1252
|
+
eval_exp&.experiment&.id
|
|
1294
1253
|
)
|
|
1295
1254
|
Logging::KameleoonLogger.debug(
|
|
1296
1255
|
'RETURN: KameleoonClient.create_external_variation(variation: %s, eval_exp: %s) -> (ext_variation: %s)',
|
|
@@ -1301,18 +1260,6 @@ module Kameleoon
|
|
|
1301
1260
|
|
|
1302
1261
|
##
|
|
1303
1262
|
# helper method for fetching values from a Variable
|
|
1304
|
-
def _parse_feature_variable(variable)
|
|
1305
|
-
case variable.type
|
|
1306
|
-
when 'BOOLEAN', 'STRING', 'NUMBER', 'JS', 'CSS'
|
|
1307
|
-
variable.value
|
|
1308
|
-
when 'JSON'
|
|
1309
|
-
JSON.parse(variable.value)
|
|
1310
|
-
else
|
|
1311
|
-
Logging::KameleoonLogger.error("Unknown type '#{variable.type}' for feature variable")
|
|
1312
|
-
variable.value
|
|
1313
|
-
end
|
|
1314
|
-
end
|
|
1315
|
-
|
|
1316
1263
|
def set_unique_identifier(visitor_code, is_unique_identifier)
|
|
1317
1264
|
Logging::KameleoonLogger.info(
|
|
1318
1265
|
"The 'isUniqueIdentifier' parameter is deprecated. Please, add 'UniqueIdentifier' to a visitor instead."
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/types/data_file'
|
|
4
|
+
|
|
3
5
|
module Kameleoon
|
|
4
6
|
module Managers
|
|
5
7
|
module Data
|
|
@@ -13,7 +15,11 @@ module Kameleoon
|
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def data_file=(value)
|
|
16
|
-
@container = Container.new(value)
|
|
18
|
+
@container = Container.new(value, create_external_data_file(value))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def external_data_file
|
|
22
|
+
@container.external_data_file
|
|
17
23
|
end
|
|
18
24
|
|
|
19
25
|
def visitor_code_managed?
|
|
@@ -22,14 +28,22 @@ module Kameleoon
|
|
|
22
28
|
|
|
23
29
|
class Container
|
|
24
30
|
attr_reader :data_file, :visitor_code_managed
|
|
31
|
+
attr_reader :external_data_file
|
|
25
32
|
|
|
26
|
-
def initialize(data_file)
|
|
33
|
+
def initialize(data_file, external_data_file)
|
|
27
34
|
@data_file = data_file
|
|
35
|
+
@external_data_file = external_data_file
|
|
28
36
|
# Regarding GDPR policy we should set visitorCode if legal consent isn't required or we have at
|
|
29
37
|
# least one Targeted Delivery rule in datafile
|
|
30
38
|
@visitor_code_managed = data_file.settings.is_consent_required && !data_file.has_any_targeted_delivery_rule
|
|
31
39
|
end
|
|
32
40
|
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def create_external_data_file(source_data_file)
|
|
45
|
+
Types::DataFile._build_from_internal(source_data_file)
|
|
46
|
+
end
|
|
33
47
|
end
|
|
34
48
|
end
|
|
35
49
|
end
|
|
@@ -32,7 +32,7 @@ module Kameleoon
|
|
|
32
32
|
|
|
33
33
|
@visitor_codes.each do |visitor_code|
|
|
34
34
|
if @total_size <= @request_size_limit
|
|
35
|
-
visitor = @visitor_manager.
|
|
35
|
+
visitor = @visitor_manager.peek_visitor(visitor_code)
|
|
36
36
|
is_consent_given = consent_given?(visitor)
|
|
37
37
|
data = collect_tracking_data(visitor_code, visitor, is_consent_given)
|
|
38
38
|
if !data.empty?
|
|
@@ -5,6 +5,7 @@ require 'net/http'
|
|
|
5
5
|
require 'time'
|
|
6
6
|
require 'kameleoon/utils'
|
|
7
7
|
require 'kameleoon/logging/kameleoon_logger'
|
|
8
|
+
require 'base64'
|
|
8
9
|
|
|
9
10
|
module Kameleoon
|
|
10
11
|
module Network
|
|
@@ -13,6 +14,7 @@ module Kameleoon
|
|
|
13
14
|
TOKEN_OBSOLESCENCE_GAP = 1800 # in seconds
|
|
14
15
|
JWT_ACCESS_TOKEN_FIELD = 'access_token'
|
|
15
16
|
JWT_EXPIRES_IN_FIELD = 'expires_in'
|
|
17
|
+
BASIC_AUTHORIZATION_PREFIX = 'Basic '
|
|
16
18
|
|
|
17
19
|
def initialize(network_manager, client_id, client_secret)
|
|
18
20
|
Logging::KameleoonLogger.debug(lambda {
|
|
@@ -23,12 +25,18 @@ module Kameleoon
|
|
|
23
25
|
@client_id = client_id
|
|
24
26
|
@client_secret = client_secret
|
|
25
27
|
@fetching = false
|
|
28
|
+
@basic_auth_token = AccessTokenSource.construct_basic_token(client_id, client_secret)
|
|
26
29
|
Logging::KameleoonLogger.debug(lambda {
|
|
27
30
|
format("RETURN: AccessTokenSource.new(network_manager, client_id: '%s', client_secret: '%s')",
|
|
28
31
|
Utils::Strval.secret(client_id), Utils::Strval.secret(client_secret))
|
|
29
32
|
})
|
|
30
33
|
end
|
|
31
34
|
|
|
35
|
+
def self.construct_basic_token(client_id, client_secret)
|
|
36
|
+
basic_token_content = "#{client_id}:#{client_secret}"
|
|
37
|
+
"#{BASIC_AUTHORIZATION_PREFIX}#{Base64.strict_encode64(basic_token_content)}"
|
|
38
|
+
end
|
|
39
|
+
|
|
32
40
|
def get_token(timeout = nil)
|
|
33
41
|
Logging::KameleoonLogger.debug('CALL: AccessTokenSource.getToken(timeout: %s)', timeout)
|
|
34
42
|
now = Time.new.to_i
|
|
@@ -70,7 +78,7 @@ module Kameleoon
|
|
|
70
78
|
|
|
71
79
|
def fetch_token(timeout = nil)
|
|
72
80
|
Logging::KameleoonLogger.debug('CALL: AccessTokenSource.fetch_token(timeout: %s)', timeout)
|
|
73
|
-
response_content = @network_manager.fetch_access_jwtoken(@
|
|
81
|
+
response_content = @network_manager.fetch_access_jwtoken(@basic_auth_token, timeout)
|
|
74
82
|
unless response_content
|
|
75
83
|
Logging::KameleoonLogger.error('Failed to fetch access JWT')
|
|
76
84
|
return nil
|
|
@@ -17,7 +17,10 @@ module Kameleoon
|
|
|
17
17
|
def collect_headers(request)
|
|
18
18
|
headers = { 'Content-Type' => request.content_type }
|
|
19
19
|
headers.merge!(request.extra_headers) unless request.extra_headers.nil?
|
|
20
|
-
|
|
20
|
+
unless request.access_token.nil? || request.access_token.empty?
|
|
21
|
+
token_prefix = request.access_token.start_with?('Basic') ? '' : 'Bearer '
|
|
22
|
+
headers['Authorization'] = "#{token_prefix}#{request.access_token}"
|
|
23
|
+
end
|
|
21
24
|
headers
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -70,16 +70,15 @@ module Kameleoon
|
|
|
70
70
|
unwrap_response(*make_call(request, true, TRACKING_CALL_ATTEMPT_NUMBER - 1, TRACKING_CALL_RETRY_DELAY))
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def fetch_access_jwtoken(
|
|
73
|
+
def fetch_access_jwtoken(basic_auth_token, timeout = nil)
|
|
74
74
|
url = @url_provider.make_access_token_url
|
|
75
75
|
timeout = ensure_timeout(timeout)
|
|
76
76
|
data_map = {
|
|
77
77
|
grant_type: ACCESS_TOKEN_GRANT_TYPE,
|
|
78
|
-
client_id: client_id,
|
|
79
|
-
client_secret: client_secret
|
|
80
78
|
}
|
|
81
79
|
data = UriHelper.encode_query(data_map).encode('UTF-8')
|
|
82
80
|
request = Request.new(Method::POST, url, ContentType::FORM, timeout, data: data)
|
|
81
|
+
request.authorize(basic_auth_token)
|
|
83
82
|
unwrap_response(*make_call(request, false))
|
|
84
83
|
end
|
|
85
84
|
|
|
@@ -11,12 +11,15 @@ module Kameleoon
|
|
|
11
11
|
body = 'null'
|
|
12
12
|
unless @data.nil?
|
|
13
13
|
if @data.is_a?(String)
|
|
14
|
-
body = @data.start_with?('grant_type=client_credentials') ? '****' : @data
|
|
15
|
-
else
|
|
16
14
|
body = @data
|
|
17
15
|
end
|
|
18
16
|
end
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
headers = ''
|
|
19
|
+
headers += 'Authorization: ***' unless access_token.nil?
|
|
20
|
+
headers += @extra_headers.to_s unless @extra_headers.nil?
|
|
21
|
+
|
|
22
|
+
"Request{method:'#{@method}',url:'#{@url}',headers:#{headers},body:'#{body}'}"
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
def initialize(method, url, content_type, timeout, extra_headers: nil, data: nil)
|
|
@@ -22,7 +22,7 @@ module Kameleoon
|
|
|
22
22
|
CONFIGURATION_API_URL_FORMAT = 'https://%s/v3/%s'
|
|
23
23
|
DATA_API_URL_FORMAT = 'https://%s%s?%s'
|
|
24
24
|
RT_CONFIGURATION_URL_FORMAT = 'https://%s:8110/sse?%s'
|
|
25
|
-
ACCESS_TOKEN_URL_FORMAT = 'https://%s/oauth/token'
|
|
25
|
+
ACCESS_TOKEN_URL_FORMAT = 'https://%s/oauth/token?%s'
|
|
26
26
|
|
|
27
27
|
TEST_DATA_API_DOMAIN = 'data.kameleoon.net'
|
|
28
28
|
TEST_AUTOMATION_API_DOMAIN = 'api.kameleoon.net'
|
|
@@ -39,6 +39,15 @@ module Kameleoon
|
|
|
39
39
|
@configuration_domain = DEFAULT_CONFIGURATION_DOMAIN
|
|
40
40
|
@access_token_domain = DEFAULT_ACCESS_TOKEN_DOMAIN
|
|
41
41
|
@is_custom_domain = false
|
|
42
|
+
|
|
43
|
+
url_params = {
|
|
44
|
+
sdkName: SDK_NAME,
|
|
45
|
+
sdkVersion: SDK_VERSION,
|
|
46
|
+
siteCode: @site_code
|
|
47
|
+
}
|
|
48
|
+
@access_token_url_params = UriHelper.encode_query(url_params)
|
|
49
|
+
url_params[:bodyUa] = true
|
|
50
|
+
@tracking_url_params = UriHelper.encode_query(url_params)
|
|
42
51
|
update_domains(network_domain)
|
|
43
52
|
end
|
|
44
53
|
|
|
@@ -60,7 +69,7 @@ module Kameleoon
|
|
|
60
69
|
siteCode: @site_code,
|
|
61
70
|
bodyUa: true
|
|
62
71
|
}
|
|
63
|
-
format(DATA_API_URL_FORMAT, @data_api_domain, TRACKING_PATH,
|
|
72
|
+
format(DATA_API_URL_FORMAT, @data_api_domain, TRACKING_PATH, @tracking_url_params)
|
|
64
73
|
end
|
|
65
74
|
|
|
66
75
|
def make_visitor_data_get_url(visitor_code, filter, is_unique_identifier = false)
|
|
@@ -104,11 +113,20 @@ module Kameleoon
|
|
|
104
113
|
end
|
|
105
114
|
|
|
106
115
|
def make_access_token_url
|
|
107
|
-
format(ACCESS_TOKEN_URL_FORMAT, @access_token_domain)
|
|
116
|
+
format(ACCESS_TOKEN_URL_FORMAT, @access_token_domain, @access_token_url_params)
|
|
108
117
|
end
|
|
109
118
|
|
|
110
119
|
private
|
|
111
120
|
|
|
121
|
+
def make_post_query_base(site_code)
|
|
122
|
+
data_map = {
|
|
123
|
+
"sdkName": Kameleoon::SDK_NAME,
|
|
124
|
+
"sdkVersion": Kameleoon::SDK_VERSION,
|
|
125
|
+
"siteCode": site_code
|
|
126
|
+
}
|
|
127
|
+
data = UriHelper.encode_query(data_map).encode('UTF-8')
|
|
128
|
+
end
|
|
129
|
+
|
|
112
130
|
def update_domains(network_domain)
|
|
113
131
|
return if network_domain.nil? || network_domain.empty?
|
|
114
132
|
|
|
@@ -8,6 +8,7 @@ module Kameleoon
|
|
|
8
8
|
# UnknownCondition represents not defined condition, always returns that visitor is targeted (true)
|
|
9
9
|
class UnknownCondition < Condition
|
|
10
10
|
def check(_data)
|
|
11
|
+
Logging::KameleoonLogger.warning('Condition of unknown type \'%s\' evaluated as true', type)
|
|
11
12
|
true
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/types/feature_flag'
|
|
4
|
+
|
|
3
5
|
module Kameleoon
|
|
4
6
|
module Types
|
|
5
7
|
# DataFile
|
|
6
8
|
class DataFile
|
|
7
|
-
attr_reader :feature_flags
|
|
9
|
+
attr_reader :feature_flags, :date_modified
|
|
8
10
|
|
|
9
11
|
# @api private
|
|
10
|
-
def initialize(feature_flags)
|
|
12
|
+
def initialize(feature_flags, date_modified)
|
|
11
13
|
@feature_flags = feature_flags
|
|
14
|
+
@date_modified = date_modified
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @api private
|
|
18
|
+
def self._build_from_internal(source_data_file)
|
|
19
|
+
feature_flags = (source_data_file.feature_flags || {}).transform_values do |feature_flag|
|
|
20
|
+
FeatureFlag._build_from_internal(feature_flag)
|
|
21
|
+
end
|
|
22
|
+
DataFile.new(feature_flags, source_data_file.date_modified)
|
|
12
23
|
end
|
|
13
24
|
|
|
14
25
|
def to_s
|
|
15
|
-
"DataFile{feature_flags:#{@feature_flags}}"
|
|
26
|
+
"DataFile{feature_flags:#{@feature_flags},date_modified:#{@date_modified}}"
|
|
16
27
|
end
|
|
17
28
|
end
|
|
18
29
|
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/types/rule'
|
|
4
|
+
require 'kameleoon/types/variation'
|
|
5
|
+
|
|
3
6
|
module Kameleoon
|
|
4
7
|
module Types
|
|
5
8
|
# FeatureFlag
|
|
@@ -18,6 +21,25 @@ module Kameleoon
|
|
|
18
21
|
@variations[@default_variation_key]
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
# @api private
|
|
25
|
+
def self._build_from_internal(source_feature_flag)
|
|
26
|
+
variations = (source_feature_flag.variations || []).each_with_object({}) do |variation, result|
|
|
27
|
+
ext_variation = Variation._build_from_internal(variation)
|
|
28
|
+
result[ext_variation.key] = ext_variation
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
rules = (source_feature_flag.rules || []).map do |rule|
|
|
32
|
+
Rule._build_from_internal(rule, variations)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
FeatureFlag.new(
|
|
36
|
+
variations,
|
|
37
|
+
source_feature_flag.environment_enabled,
|
|
38
|
+
rules,
|
|
39
|
+
source_feature_flag.default_variation_key
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
21
43
|
def to_s
|
|
22
44
|
"FeatureFlag{variations:#{@variations},environment_enabled:#{@environment_enabled},rules:#{@rules},default_variation_key:#{@default_variation_key}}"
|
|
23
45
|
end
|
data/lib/kameleoon/types/rule.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/types/variation'
|
|
4
|
+
|
|
3
5
|
module Kameleoon
|
|
4
6
|
module Types
|
|
5
7
|
# Rule
|
|
@@ -11,6 +13,25 @@ module Kameleoon
|
|
|
11
13
|
@variations = variations
|
|
12
14
|
end
|
|
13
15
|
|
|
16
|
+
# @api private
|
|
17
|
+
def self._build_from_internal(internal_rule, variations)
|
|
18
|
+
rule_variations = {}
|
|
19
|
+
vars_by_exposition = internal_rule.experiment&.variations_by_exposition || []
|
|
20
|
+
vars_by_exposition.each do |var_by_exp|
|
|
21
|
+
base_variation = variations[var_by_exp.variation_key]
|
|
22
|
+
next if base_variation.nil?
|
|
23
|
+
|
|
24
|
+
rule_variations[base_variation.key] = Variation.new(
|
|
25
|
+
base_variation.key,
|
|
26
|
+
var_by_exp.variation_id,
|
|
27
|
+
internal_rule.experiment&.id,
|
|
28
|
+
base_variation.variables,
|
|
29
|
+
base_variation.name
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
Rule.new(rule_variations)
|
|
33
|
+
end
|
|
34
|
+
|
|
14
35
|
def to_s
|
|
15
36
|
"Rule{variations:#{@variations}}"
|
|
16
37
|
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
5
|
+
|
|
3
6
|
module Kameleoon
|
|
4
7
|
module Types
|
|
5
8
|
# Variable
|
|
@@ -16,6 +19,11 @@ module Kameleoon
|
|
|
16
19
|
@type = type
|
|
17
20
|
@value = value
|
|
18
21
|
end
|
|
22
|
+
|
|
23
|
+
# @api private
|
|
24
|
+
def self._build_from_internal(source_variable)
|
|
25
|
+
Variable.new(source_variable.key, source_variable.type, source_variable.get_value)
|
|
26
|
+
end
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'kameleoon/configuration/variation'
|
|
4
|
+
require 'kameleoon/types/variable'
|
|
4
5
|
|
|
5
6
|
module Kameleoon
|
|
6
7
|
module Types
|
|
@@ -21,6 +22,17 @@ module Kameleoon
|
|
|
21
22
|
@name = name
|
|
22
23
|
end
|
|
23
24
|
|
|
25
|
+
# @api private
|
|
26
|
+
def self._build_from_internal(source_variation, variation_id = nil, experiment_id = nil)
|
|
27
|
+
variables = (source_variation&.variables || []).each_with_object({}) do |variable, result|
|
|
28
|
+
ext_variable = Variable._build_from_internal(variable)
|
|
29
|
+
result[ext_variable.key] = ext_variable
|
|
30
|
+
end
|
|
31
|
+
key = source_variation&.key || ''
|
|
32
|
+
name = source_variation&.name || ''
|
|
33
|
+
Variation.new(key, variation_id, experiment_id, variables, name)
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
def active?
|
|
25
37
|
@key != Configuration::VariationType::VARIATION_OFF
|
|
26
38
|
end
|
data/lib/kameleoon/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kameleoon-client-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kameleoon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: em-http-request
|