Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f34312a
[fix] expiration time to the parameter
John-Weak Aug 1, 2024
058c901
[SER-1662] Cancel button not working
John-Weak Aug 1, 2024
3f37026
[remote-config] Update test files
widatama Jul 3, 2024
8c8c991
[remote-config] Add fetch_remote_config tests
widatama Jul 3, 2024
bbf24ce
[remote-config] Remove params from processFilter
widatama Jul 4, 2024
72d601d
[remote-config] Add tests for targetting
widatama Jul 4, 2024
cb2e41a
[remote-config] Add test cleanup
widatama Jul 5, 2024
ccae95c
[remote-config] Update test
widatama Jul 5, 2024
f0ccd12
[remote-config] Add tests for remote-config endpoint
widatama Jul 5, 2024
c8129f5
[remote-config] Update test
widatama Jul 8, 2024
1aba60f
[remote-config] Add condition endpoint tests
widatama Jul 5, 2024
a387c69
ab method test
John-Weak Jul 4, 2024
a89787b
update response
John-Weak Jul 4, 2024
c0bd8f4
check app_user
John-Weak Jul 4, 2024
bba0834
parameter crud test
John-Weak Jul 29, 2024
7abacd5
tests
John-Weak Jul 30, 2024
1b4509e
feedback
John-Weak Aug 1, 2024
f40ff04
[remote-config] Fix description displays
widatama Jul 31, 2024
99cd329
[remote-config] Limit parameter key length
widatama Jul 31, 2024
965d218
[SER-1625] addCompleteConfig is not a function
John-Weak Aug 2, 2024
ad77724
Merge pull request #5454 from Countly/SER-1663
John-Weak Aug 2, 2024
4d59e58
[SER-1653] prevent creation of parameter with default value as empty …
John-Weak Aug 5, 2024
1deed17
[SER-1653] allow empty strings as a default value
John-Weak Aug 5, 2024
4343ffc
default status of parameter should be "Running"
John-Weak Aug 5, 2024
f41cb00
Merge branch 'master' into remocon-master
kanwarujjaval Aug 6, 2024
afc6e19
Merge branch 'master' into remocon-master
kanwarujjaval Aug 9, 2024
6016a37
Merge branch 'master' into remocon-master
widatama Aug 13, 2024
e2ab262
Merge branch 'master' into remocon-master
widatama Aug 16, 2024
b43b267
Merge branch 'master' into remocon-master
kanwarujjaval Aug 20, 2024
4ebbfe1
[remote-config] Add expiration validation
widatama Aug 28, 2024
4920cd3
[remote-config] Update expiration validation
widatama Aug 28, 2024
d2342e5
[remote-config] Update expiration default value
widatama Aug 28, 2024
dcc2150
[remote-config] Update expiration validation
widatama Aug 28, 2024
20de4c8
Merge branch 'master' into remocon-master
kanwarujjaval Aug 28, 2024
e762eb3
Merge branch 'master' into remocon-master
kanwarujjaval Aug 30, 2024
70fe8c2
[SER-1653] refetch param status after update
John-Weak Sep 3, 2024
966519b
Merge branch 'master' into remocon-master
widatama Sep 4, 2024
ff67d73
[remote-config] Fix initialize action
widatama Sep 5, 2024
a561c1a
[remote-config] Use dispatch in initialize
widatama Sep 6, 2024
8afb9ee
Merge branch 'master' into remocon-master
kanwarujjaval Sep 9, 2024
e9448ed
Merge branch 'master' into remocon-master
kanwarujjaval Sep 10, 2024
957818a
Merge branch 'master' into remocon-master
kanwarujjaval Sep 10, 2024
5c55c10
Merge branch 'master' into remocon-master
kanwarujjaval Sep 12, 2024
045ce64
Merge branch 'master' into remocon-master
kanwarujjaval Sep 13, 2024
9dabe62
Merge branch 'master' into remocon-master
kanwarujjaval Sep 16, 2024
f77e14b
Merge branch 'master' into remocon-master
widatama Sep 17, 2024
d49d5f0
Merge branch 'master' into remocon-master
widatama Sep 18, 2024
56d957f
[remote-config] Update parameter actions
widatama Sep 19, 2024
b50bbd3
[remote-config] Update action buttons
widatama Sep 19, 2024
9ffcd96
Merge branch 'master' into remocon-master
ArtursKadikis Sep 23, 2024
a5fb5e0
Merge branch 'master' into remocon-master
ArtursKadikis Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,9 @@
},
methods: {
loadValue: function(value) {
if (!value) {
return;
}
var changes = this.valueToInputState(value),
self = this;
changes.label = getRangeLabel(changes, this.type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@
template: '<cly-dropdown class="cly-vue-more-options" ref="dropdown" :placement="placement" :disabled="disabled" v-on="$listeners">\
<template v-slot:trigger>\
<slot name="trigger">\
<el-button :data-test-id="testId + \'-more-option-button\'" :size="size" :icon="icon" :type="type">\
<el-button :data-test-id="testId + \'-more-option-button\'" :size="size" :icon="icon" :type="type" :disabled="disabledButton">\
<span :data-test-id="testId + \'-more-option-text\'" v-if="text">{{text}}</span>\
</el-button>\
</slot>\
Expand Down Expand Up @@ -560,6 +560,10 @@
type: Boolean,
default: false
},
disabledButton: {
type: Boolean,
default: false,
},
placement: {
type: String,
default: 'bottom-end'
Expand Down
170 changes: 165 additions & 5 deletions plugins/remote-config/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,37 @@ plugins.setConfigs("remote-config", {
ob.features.push(FEATURE_NAME);
});

/**
* @api {get} /o/sdk?method=rc Get remote configs in sdk
* @apiName GetRemoteConfigInSdk
* @apiGroup Remote Config
* @apiPermission user
* @apiDescription Fetch all remote config in sdk
*
* @apiQuery {String} app_key APP_KEY of an app for which to fetch remote config
* @apiQuery {String} device_id Your generated or device specific unique device ID to identify user
* @apiQuery {String} [timestamp] 10 digit UTC timestamp for recording past data
* @apiQuery {String} [city] Name of the user's city
* @apiQuery {String} [country_code] ISO Country code for the user's country
* @apiQuery {String} [location] Users lat, lng
* @apiQuery {String} [tz] Users timezone
* @apiQuery {String} [ip_address] IP address of user to determine user location, if not provided, countly will try to establish ip address based on connection data
* @apiQuery {String[]} [keys] Only the values mentioned in the array will be fetched
* @apiQuery {String[]} [omit_keys] Only the values mentioned in the array will not be fetched
* @apiQuery {Object} [metrics] JSON object with key value pairs
* @apiQuery {Number} [oi] To indicate that user will be enrolled in the returned keys if eligible
*
* @apiSuccessExample {json} Success-Response:
* {
"default_colors": {
"button": "#f77a22",
"buttonColor": "#ffffff",
"titleColor": "#2eb52b"
},
"display_onboarding": true,
"image_alt": "The image cannot be loaded"
}
*/
plugins.register("/o/sdk", function(ob) {
var params = ob.params;
if (params.qstring.method !== "rc") {
Expand All @@ -27,6 +58,30 @@ plugins.setConfigs("remote-config", {

});

/**
* @api {get} /o/sdk?method=ab Enrolls in ab tests for mentioned keys if user is eligible
* @apiName EnrollUserInABTests
* @apiGroup Remote Config
* @apiPermission user
* @apiDescription Enrolls in ab tests for mentioned keys if user is eligible
*
* @apiQuery {String} app_key APP_KEY of an app for which to fetch remote config
* @apiQuery {String} device_id Your generated or device specific unique device ID to identify user
* @apiQuery {String} [timestamp] 10 digit UTC timestamp for recording past data
* @apiQuery {String} [city] Name of the user's city
* @apiQuery {String} [country_code] ISO Country code for the user's country
* @apiQuery {String} [location] Users lat, lng
* @apiQuery {String} [tz] Users timezone
* @apiQuery {String} [ip_address] IP address of user to determine user location, if not provided, countly will try to establish ip address based on connection data
* @apiQuery {String[]} [keys] Only the values mentioned in the array will be fetched
* @apiQuery {Object} [metrics] JSON object with key value pairs
*
* @apiSuccessExample {body} Success-Response:
* HTTP/1.1 200 OK
* {
* "Successfully enrolled in ab tests"
* }
*/
plugins.register("/o/sdk", function(ob) {
var params = ob.params;
if (params.qstring.method !== "ab") {
Expand Down Expand Up @@ -295,6 +350,27 @@ plugins.setConfigs("remote-config", {
* @apiQuery {String} app_id Application id
* @apiQuery {Object} parameter Parameter information
*
* @apiQueryExample {json} Request-Example:
* {
* "app_id": "5da8c68cb1ce0e2f34c4f3e6",
* "parameter": "{\"parameter_key\":\"new_feature_enabled\",\"default_value\":false,\"conditions\":[]}"
* }
*
* @apiSuccess {Number} result Result code (200 for success)
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {}
*
* @apiError {Number} result Result code (400 or 500 for error)
* @apiError {String} message Error message
*
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 400 Bad Request
* {
* "result": 400,
* "message": "Invalid parameter: parameter_key"
* }
*/
/**
* Function to add a parameter
Expand All @@ -311,6 +387,9 @@ plugins.setConfigs("remote-config", {
catch (SyntaxError) {
console.log('Parse parameter failed: ', params.qstring.parameter);
}
if (!parameter.status) {
parameter.status = "Running";
}

var parameterKey = parameter.parameter_key;
var defaultValue = parameter.default_value;
Expand Down Expand Up @@ -352,7 +431,7 @@ plugins.setConfigs("remote-config", {

async.series(asyncTasks, function(err) {
if (err) {
var message = 'Failed to add parameter';
var message = err?.message || 'Failed to add parameter';
if (err.exists) {
message = 'The parameter already exists';
}
Expand All @@ -368,6 +447,39 @@ plugins.setConfigs("remote-config", {
});
}

/**
* @api {post} /i/remote-config/add_complete_config
* @apiName AddCompleteRemoteConfig
* @apiGroup Remote Config
* @apiPermission user
* @apiDescription Add a complete remote configuration including parameters and conditions, it is used to publish the experiment results,
* In summmary replace the default value of a parameter in remote config with the winning variant from AB Test
*
* @apiParam {String} app_id Application ID
* @apiParam {String} config JSON string representing the complete config object
*
* @apiParamExample {json} Request-Example:
* {
* "app_id": "5da8c68cb1ce0e2f34c4f3e6",
* "config": "{\"parameters\":[{\"parameter_key\":\"feature_enabled\",\"exp_value\":true,\"description\":\"Enable new feature\"}],\"condition\":{\"condition_name\":\"New Users\",\"condition\":{\"user_properties.is_new\":true}}}"
* }
*
* @apiSuccess {Number} result Result code (200 for success)
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {}
*
* @apiError {Number} result Result code (400 or 500 for error)
* @apiError {String} message Error message
*
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 400 Bad Request
* {
* "result": 400,
* "message": "Invalid config"
* }
*/
/**
* Function to add the complete config including parameter and condition
* @param {Object} params - params object
Expand Down Expand Up @@ -716,7 +828,7 @@ plugins.setConfigs("remote-config", {
var deviceId = params.qstring.device_id || "";
user.random_percentile = remoteConfig.randomPercentile(seed, deviceId);

var conditionStatus = remoteConfig.processFilter(params, user, conditionObj.condition);
var conditionStatus = remoteConfig.processFilter(user, conditionObj.condition);

if (conditionStatus) {
parameterValue = conditionObj.value;
Expand Down Expand Up @@ -768,7 +880,29 @@ plugins.setConfigs("remote-config", {
* @apiQuery {String} app_id Application id
* @apiQuery {Object} parameter Parameter information
* @apiQuery {String} parameter_id Id of the parameter which is to be updated
*
* @apiQueryExample {json} Request-Example:
* {
* "app_id": "5da8c68cb1ce0e2f34c4f3e6",
* "parameter_id": "60a7c1234b1ce0e2f34c4f3e7",
* "parameter": "{\"parameter_key\":\"feature_enabled\",\"default_value\":true,\"conditions\":[]}"
* }
*
* @apiSuccess {Number} result Result code (200 for success)
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {}
*
* @apiError {Number} result Result code (400 or 500 for error)
* @apiError {String} message Error message
*
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 400 Bad Request
* {
* "result": 400,
* "message": "Invalid parameter: parameter_key"
* }
*/
/**
* Function to update parameter
Expand All @@ -785,18 +919,25 @@ plugins.setConfigs("remote-config", {
catch (SyntaxError) {
console.log('Parse parameter failed: ', params.qstring.parameter);
}
if (!parameter.status) {
parameter.status = "Running";
}

var parameterId = params.qstring.parameter_id;
var parameterKey = parameter.parameter_key;
var defaultValue = parameter.default_value;

//var conditionName = parameter.conditions;
var pattern = new RegExp(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
if (!pattern.test(parameterKey)) {
common.returnMessage(params, 400, 'Invalid parameter: parameter_key');
return true;
}

if (!defaultValue && defaultValue !== false) {
// var conditionPattern = new RegExp(/^[a-zA-Z0-9 ]+$/);
// if (!conditionName || !conditionPattern.test(conditionName.trim())) {
// common.returnMessage(params, 400, 'Invalid parameter: condition_name');
// return true;
// }
if (defaultValue === undefined) {
common.returnMessage(params, 400, 'Invalid parameter: default_value');
return true;
}
Expand All @@ -808,9 +949,12 @@ plugins.setConfigs("remote-config", {

var collectionName = "remoteconfig_parameters" + appId;

//TODO:validations

var asyncTasks = [
checkMaximumConditionsLimit.bind(null, parameter.conditions, maximumConditionsAllowed),
checkIfParameterExists.bind(null, appId, parameterKey, parameterId),
//checkIfConditionExists.bind(null, appId, conditionName, null),
updateParameterInDb.bind(null, params, collectionName, parameterId, parameter)
];

Expand Down Expand Up @@ -1001,6 +1145,14 @@ plugins.setConfigs("remote-config", {
return true;
}

if (!condition.condition) {
if (params.internal) {
return 'Invalid parameter: condition';
}
common.returnMessage(params, 400, 'Invalid parameter: condition');
return true;
}

if (typeof condition.condition !== typeof '') {
condition.condition = JSON.stringify(condition.condition);
}
Expand Down Expand Up @@ -1177,6 +1329,14 @@ plugins.setConfigs("remote-config", {
return true;
}

if (!condition.condition) {
if (params.internal) {
return 'Invalid parameter: condition';
}
common.returnMessage(params, 400, 'Invalid parameter: condition');
return true;
}

condition.condition = JSON.stringify(condition.condition);

var asyncTasks = [
Expand Down
7 changes: 3 additions & 4 deletions plugins/remote-config/api/parts/rc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ var globalSeed = "Countly_is_awesome";
var remoteConfig = {};

/**
* Function to process condition filter
* @param {Object} params - params object
* Function to check if the given query would match the given user
* @param {Object} user - user
* @param {Object} query - query
* @returns {Boolean} query status
* @returns {Boolean} true if the query matches the user
*/
remoteConfig.processFilter = function(params, user, query) {
remoteConfig.processFilter = function(user, query) {
var queryStatus = false, isCohort = false, hasValue = false;

if (Object.keys(query).length) {
Expand Down
Loading
Loading