Skip to content

Commit 635259f

Browse files
authored
Merge branch 'master' into ar2rsawseen/master2
2 parents 5bbe572 + 1f1e945 commit 635259f

File tree

11 files changed

+1527
-359
lines changed

11 files changed

+1527
-359
lines changed

CHANGELOG.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,28 @@ Fixes:
33
- [crashes] Fixed resolving audit log recording
44
- [location] Fixed updating none gps coordinate location after gps location was used
55

6+
Enterprise Fixes:
7+
- [ab-testing] Add script for fixing variant cohort
8+
- [groups] Fix user permission update after updating user group permission
9+
10+
11+
## Version 25.03.24
12+
Fixes:
13+
- [jobs] Fix condition for scheduling alert job
14+
615
Enterprise Fixes:
716
- [compliance-hub] Fixed query patterns
8-
- [data-manager] Fixed segment data deletion
917
- [data-manager] Fixed bug preventing transformation of events ending in a dot
18+
- [data-manager] Fixed segment data deletion
19+
- [license] Stop sending metric after license expired
1020
- [users] Fix add/remove user to profile group
1121
- [users] Remove link to profile group page after removing user from group
1222

1323
Dependencies
14-
- Bump lint-staged from 16.2.3 to 16.2.4
1524
- Bump @faker-js/faker from 10.0.0 to 10.1.0 in /ui-tests
16-
- Bump puppeteer from 24.23.0 to 24.24.1
1725
- Bump countly-sdk-nodejs from 24.10.2 to 24.10.3
26+
- Bump lint-staged from 16.2.3 to 16.2.4
27+
- Bump puppeteer from 24.23.0 to 24.24.1
1828

1929
## Version 25.03.23
2030
Fixes:

api/parts/jobs/job.js

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -254,32 +254,33 @@ class Job extends EventEmitter {
254254

255255
this._json.next = next.getTime();
256256
}
257-
if (this.name !== "alerts:monitor") {
258-
//check if any job already scheduled or running
259-
let query = {
260-
status: {"$in": [STATUS.SCHEDULED, STATUS.RUNNING]},
261-
name: this.name,
262-
};
263-
if (this._id) {
264-
query._id = {$ne: this._id};
265-
}
266-
var self = this;
267-
return new Promise((resolve, reject) => {
268-
Job.findMany(this.db(), query).then(existing => {
269-
if (existing && existing.length) {
270-
log.d('Job already scheduled or running: %j', existing);
271-
this._json.status = STATUS.CANCELLED; //set this as cancelled now as we have other scheduled
272-
}
273-
else {
274-
self._save().then(resolve, reject);
275-
}
276257

277-
});
278-
});
258+
//check if any job already scheduled or running
259+
let query = {
260+
status: {"$in": [STATUS.SCHEDULED, STATUS.RUNNING]},
261+
name: this.name,
262+
};
263+
264+
if (this.name === 'alerts:monitor' && this.data && Object.keys(this.data).length) {
265+
query.data = this.data;
279266
}
280-
else {
281-
return this._save();
267+
268+
if (this._id) {
269+
query._id = {$ne: this._id};
282270
}
271+
272+
var self = this;
273+
return new Promise((resolve, reject) => {
274+
Job.findMany(this.db(), query).then(existing => {
275+
if (existing && existing.length) {
276+
log.d('Job already scheduled or running: %j', existing);
277+
this._json.status = STATUS.CANCELLED; //set this as cancelled now as we have other scheduled
278+
}
279+
else {
280+
self._save().then(resolve, reject);
281+
}
282+
});
283+
});
283284
}
284285

285286
/**
@@ -1142,4 +1143,4 @@ module.exports = {
11421143
STATUS: STATUS,
11431144
STATUS_MAP: STATUS_MAP,
11441145
debounce: debounce
1145-
};
1146+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Sends recalculate request for all ab testing experiment variant cohorts
3+
* Server: countly
4+
* Path: $(countly dir)/bin/scripts/fix-data
5+
* Command: node recalculate_ab_test_cohorts.js
6+
*/
7+
8+
// API key here with permission to update cohorts
9+
const API_KEY = '';
10+
// Countly app id, if not specified will do nothing
11+
const APP_ID = '';
12+
// ab test experiment id, will do nothing if not specified
13+
const EXPERIMENT_ID = '';
14+
// countly instance public url, something like 'https://name.count.ly'
15+
const SERVER_URL = '';
16+
17+
const pluginManager = require('../../../plugins/pluginManager.js');
18+
const request = require('countly-request')(pluginManager.getConfig('security'));
19+
20+
if (API_KEY.length === 0) {
21+
console.warn('Please provide an API_KEY');
22+
process.exit(1);
23+
}
24+
25+
pluginManager.dbConnection('countly_out').then(async(db) => {
26+
let urlObj = {};
27+
try {
28+
urlObj = new URL(SERVER_URL);
29+
}
30+
catch (err) {
31+
urlObj = new URL((process.env.COUNTLY_CONFIG_PROTOCOL || "http") + "://" + (process.env.COUNTLY_CONFIG_HOSTNAME || "localhost"));
32+
}
33+
urlObj.pathname = 'i/cohorts/recalculate';
34+
urlObj.searchParams.append('api_key', API_KEY);
35+
urlObj.searchParams.append('app_id', APP_ID);
36+
37+
console.log(`Finding ab test experiment ${EXPERIMENT_ID} in app ${APP_ID}`);
38+
39+
const experimentCollectionName = `ab_testing_experiments${APP_ID}`;
40+
const experiment = await db.collection(experimentCollectionName).findOne({ _id: db.ObjectID(EXPERIMENT_ID) });
41+
42+
if (experiment?.variants?.length > 0) {
43+
for (let varIdx = 0; varIdx < experiment.variants.length; varIdx += 1) {
44+
const variant = experiment.variants[varIdx];
45+
46+
if (variant?.cohorts && Object.keys(variant.cohorts).length > 0) {
47+
for (let cohIdx = 0; cohIdx < Object.keys(variant.cohorts).length; cohIdx += 1) {
48+
const cohortId = variant.cohorts[Object.keys(variant.cohorts)[cohIdx]];
49+
console.log(`Sending recalculate request for variant ${variant.name}, cohort ${cohortId}`);
50+
51+
urlObj.searchParams.delete('cohort_id');
52+
urlObj.searchParams.append('cohort_id', cohortId);
53+
54+
await new Promise((resolve) => {
55+
request.get(urlObj.href, (err, _, body) => {
56+
if (err) {
57+
console.warn('Request failed ', JSON.stringify(cohortId), err);
58+
}
59+
else {
60+
console.log('Request finished ', JSON.stringify(cohortId), body);
61+
}
62+
resolve();
63+
});
64+
});
65+
}
66+
}
67+
}
68+
}
69+
else {
70+
console.warn(`Experiments ${EXPERIMENT_ID} not found in app ${APP_ID}`);
71+
}
72+
73+
db.close();
74+
});

frontend/express/public/core/user-management/javascripts/countly.views.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@
866866
}
867867
},
868868
onOpen: function() {
869+
this.patchUserPermission();
869870
this.changePasswordFlag = false;
870871
// types
871872
var types = ['c', 'r', 'u', 'd'];
@@ -879,7 +880,7 @@
879880
// if it's in edit mode
880881
if (this.settings.editMode) {
881882
// is user member of a group?
882-
if (this.user.group_id && countlyGlobal.plugins.indexOf('groups') > -1) {
883+
if (this.user.group_id && this.user.group_id.length && countlyGlobal.plugins.indexOf('groups') > -1) {
883884
// set groups state
884885
if (Array.isArray(this.user.group_id)) {
885886
this.groups = this.user.group_id;
@@ -982,7 +983,31 @@
982983
},
983984
onRoleChange: function(role) {
984985
this.roles[role.name] = role;
985-
}
986+
},
987+
patchUserPermission: function() {
988+
if (this.user && this.user.permission && this.user.permission._ && this.user.permission._.u) {
989+
var appIdReducer = function(acc, curr) {
990+
if (curr.length > 0) {
991+
acc.push(curr);
992+
}
993+
return acc;
994+
};
995+
996+
var _u = this.user.permission._.u.reduce(function(acc, curr) {
997+
if (curr.length > 0) {
998+
var appIds = curr.reduce(appIdReducer, []);
999+
1000+
if (appIds.length > 0) {
1001+
acc.push(appIds);
1002+
}
1003+
}
1004+
return acc;
1005+
}, []);
1006+
1007+
this.user.permission._.u = _u;
1008+
this.$refs.userDrawer.editedObject.permission._.u = _u;
1009+
}
1010+
},
9861011
},
9871012
watch: {
9881013
'groups': function() {

0 commit comments

Comments
 (0)