Skip to content

Commit 6f016b9

Browse files
committed
Merge branch 'master' into next
2 parents 3a6fc70 + 27448eb commit 6f016b9

File tree

257 files changed

+1787
-1744
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

257 files changed

+1787
-1744
lines changed

CHANGELOG.md

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## Version 23.06.1
2+
Fixes:
3+
- [core] Added missing % in Session Analytics
4+
- [core] Added script for report migration to bookmarks.
5+
- [core] Fixes for mongodb configuration on install.
6+
- [dashboards] Localization and styling fixes for empty dasboards
7+
- [dependency] xml2js fix
8+
- [members] Set permission._ when editing member.
9+
10+
Enterprise fixes:
11+
- [cohorts] Fixes for dashboard widgets showing invalid % compared to previous period.
12+
- [core] Fix CE tag version update
13+
- [drill] Fix for 'Segmentation filters not showing up for cohorts'
14+
- [drill] Store visualization type in bookmark
15+
- [drill] default chart type is "bar" for byVal queries
16+
- [flows] Rights check for data requests.
17+
- [push] User Profiles querying by push tokens & messages
18+
- [users] Fix blank value formatting
19+
120
## Version 23.06
221

322
New Features:
@@ -22,6 +41,7 @@ Enterprise new features:
2241
- [drill] enhanced state url for drill
2342
- [drill] new drill meta structure
2443
- [events] add drill option to Events
44+
- [push] user profiles querying by push tokens & messages
2545
- [surveys] different logo types
2646
- [surveys] show always option
2747
- [users] download user debug information
@@ -42,6 +62,7 @@ Enterprise fixes:
4262
- [drill] hide no data text
4363
- [drill] standartizing ls/lac behavior
4464
- [performance-monitoring] splitting documents to be able to store more data
65+
- [retention] backward compatibility in retention widgets
4566

4667
## Version 23.03.9
4768
Fixes:

api/lib/countly.common.js

+31
Original file line numberDiff line numberDiff line change
@@ -2630,4 +2630,35 @@ countlyCommon.calculatePeriodObject = function(period) {
26302630
return getPeriodObject(period);
26312631
};
26322632

2633+
/**
2634+
* Function that increments strings alphabetically.
2635+
* @param {string} str - string that next character will be calculated
2636+
* @return {string} - calculated string
2637+
*/
2638+
countlyCommon.stringIncrement = function(str) {
2639+
let carry = 1;
2640+
let res = '';
2641+
2642+
for (let i = str.length - 1; i >= 0; i--) {
2643+
let char = str.toUpperCase().charCodeAt(i);
2644+
char += carry;
2645+
if (char > 90) {
2646+
char = 65;
2647+
carry = 1;
2648+
}
2649+
else {
2650+
carry = 0;
2651+
}
2652+
res = String.fromCharCode(char) + res;
2653+
if (!carry) {
2654+
res = str.substring(0, i) + res;
2655+
break;
2656+
}
2657+
}
2658+
if (carry) {
2659+
res = 'A' + res;
2660+
}
2661+
return res;
2662+
};
2663+
26332664
module.exports = countlyCommon;

api/parts/mgmt/users.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ usersApi.updateUser = async function(params) {
503503
if (updatedMember.admin_of) {
504504
if (Array.isArray(updatedMember.admin_of) && updatedMember.admin_of.length) {
505505
updatedMember.permission = updatedMember.permission || {};
506+
if (!updatedMember.permission._) {
507+
updatedMember.permission._ = {};
508+
}
509+
updatedMember.permission._.a = updatedMember.admin_of;
506510
updatedMember.permission.c = updatedMember.permission.c || {};
507511
updatedMember.permission.r = updatedMember.permission.r || {};
508512
updatedMember.permission.u = updatedMember.permission.u || {};
@@ -520,6 +524,10 @@ usersApi.updateUser = async function(params) {
520524
if (updatedMember.user_of) {
521525
if (Array.isArray(updatedMember.user_of) && updatedMember.user_of.length) {
522526
updatedMember.permission = updatedMember.permission || {};
527+
if (!updatedMember.permission._) {
528+
updatedMember.permission._ = {};
529+
}
530+
updatedMember.permission._.u = [updatedMember.user_of];
523531
updatedMember.permission.r = updatedMember.permission.r || {};
524532
for (let i = 0; i < updatedMember.user_of.length; i++) {
525533
updatedMember.permission.r[updatedMember.user_of[i]] = updatedMember.permission.r[updatedMember.user_of[i]] || {all: true, allowed: {}};
@@ -837,10 +845,6 @@ usersApi.saveNote = async function(params) {
837845
'category': {
838846
'required': false,
839847
'type': 'Boolean'
840-
},
841-
"indicator": {
842-
'required': false,
843-
'type': 'String'
844848
}
845849
};
846850
const args = params.qstring.args;
@@ -878,12 +882,24 @@ usersApi.saveNote = async function(params) {
878882
}
879883
}
880884
else {
881-
note.indicator = args.indicator;
882-
common.db.collection('notes').insert(note, (err) => {
885+
common.db.collection('notes').find({ "app_id": args.app_id }).sort({ "created_at": -1 }).limit(1).project({ "indicator": 1 }).toArray(function(err, res) {
883886
if (err) {
884-
common.returnMessage(params, 503, 'Insert Note failed.');
887+
common.returnMessage(params, 503, 'Save note failed');
888+
}
889+
else {
890+
if (res && res.length) {
891+
note.indicator = countlyCommon.stringIncrement(res[0].indicator);
892+
}
893+
else {
894+
note.indicator = "A";
895+
}
896+
common.db.collection('notes').insert(note, (_err) => {
897+
if (_err) {
898+
common.returnMessage(params, 503, 'Insert Note failed.');
899+
}
900+
common.returnMessage(params, 200, 'Success');
901+
});
885902
}
886-
common.returnMessage(params, 200, 'Success');
887903
});
888904
}
889905
}

api/utils/common.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1918,7 +1918,7 @@ common.recordCustomMetric = function(params, collection, id, metrics, value, seg
19181918
*/
19191919
common.setCustomMetric = function(params, collection, id, metrics, value, segments, uniques, lastTimestamp) {
19201920
value = value || 0;
1921-
params.defaultValue = 0;
1921+
params.defaultValue = value || 0;
19221922
var updateUsersZero = {},
19231923
updateUsersMonth = {},
19241924
tmpSet = {};

api/utils/requestProcessor.js

+57-3
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,33 @@ const processRequest = (params) => {
11861186
});
11871187
break;
11881188
}
1189+
/**
1190+
* @api {get} /i/events/delete_events Delete event
1191+
* @apiName Delete Event
1192+
* @apiGroup Events Management
1193+
*
1194+
* @apiDescription Deletes one or multiple events. Params can be send as POST and also as GET.
1195+
* @apiQuery {String} app_id Application id
1196+
* @apiQuery {String} events JSON array of event keys to delete. For example: ["event1", "event2"]. Value must be passed as string. (Array must be stringified before passing to API)
1197+
*
1198+
* @apiSuccessExample {json} Success-Response:
1199+
* HTTP/1.1 200 OK
1200+
* {
1201+
* "result":"Success"
1202+
* }
1203+
*
1204+
* @apiErrorExample {json} Error-Response:
1205+
* HTTP/1.1 400 Bad Request
1206+
* {
1207+
* "result":"Missing parameter \"api_key\" or \"auth_token\""
1208+
* }
1209+
*
1210+
* @apiErrorExample {json} Error-Response:
1211+
* HTTP/1.1 400 Bad Request
1212+
* {
1213+
* "result":"Could not find event"
1214+
* }
1215+
*/
11891216
case 'delete_events':
11901217
{
11911218
validateDelete(params, 'events', function() {
@@ -1205,6 +1232,7 @@ const processRequest = (params) => {
12051232
var updateThese = {"$unset": {}};
12061233
if (idss.length > 0) {
12071234
for (let i = 0; i < idss.length; i++) {
1235+
idss[i] = idss[i] + ""; //make sure it is string to do not fail.
12081236
if (idss[i].indexOf('.') !== -1) {
12091237
updateThese.$unset["map." + idss[i].replace(/\./g, '\\u002e')] = 1;
12101238
updateThese.$unset["omitted_segments." + idss[i].replace(/\./g, '\\u002e')] = 1;
@@ -2009,6 +2037,32 @@ const processRequest = (params) => {
20092037
params.qstring.data = {};
20102038
}
20112039
}
2040+
2041+
if (params.qstring.projection) {
2042+
try {
2043+
params.qstring.projection = JSON.parse(params.qstring.projection);
2044+
}
2045+
catch (ex) {
2046+
params.qstring.projection = {};
2047+
}
2048+
}
2049+
2050+
if (params.qstring.columnNames) {
2051+
try {
2052+
params.qstring.columnNames = JSON.parse(params.qstring.columnNames);
2053+
}
2054+
catch (ex) {
2055+
params.qstring.columnNames = {};
2056+
}
2057+
}
2058+
if (params.qstring.mapper) {
2059+
try {
2060+
params.qstring.mapper = JSON.parse(params.qstring.mapper);
2061+
}
2062+
catch (ex) {
2063+
params.qstring.mapper = {};
2064+
}
2065+
}
20122066
countlyApi.data.exports.fromRequest({
20132067
params: params,
20142068
path: params.qstring.path,
@@ -2017,9 +2071,9 @@ const processRequest = (params) => {
20172071
prop: params.qstring.prop,
20182072
type: params.qstring.type,
20192073
filename: params.qstring.filename,
2020-
projection: JSON.parse(params.qstring.projection),
2021-
columnNames: JSON.parse(params.qstring.columnNames),
2022-
mapper: JSON.parse(params.qstring.mapper),
2074+
projection: params.qstring.projection,
2075+
columnNames: params.qstring.columnNames,
2076+
mapper: params.qstring.mapper,
20232077
});
20242078
}, params);
20252079
break;

bin/scripts/mongodb.install.sh

+18-10
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ function mongodb_configure () {
77
INDENT_LEVEL=$(grep dbPath ${MONGODB_CONFIG_FILE} | awk -F"[ ]" '{for(i=1;i<=NF && ($i=="");i++);print i-1}')
88
INDENT_STRING=$(printf ' %.0s' $(seq 1 "$INDENT_LEVEL"))
99

10-
sed -i "/directoryPerDB/d" ${MONGODB_CONFIG_FILE}
11-
sed -i "s#storage:#storage:\n${INDENT_STRING}directoryPerDB: true#g" ${MONGODB_CONFIG_FILE}
12-
1310
#enable IPv6 support
1411
if ping -c 1 -6 localhost >> /dev/null 2>&1; then
1512
sed -i "/ipv6/d" ${MONGODB_CONFIG_FILE}
@@ -35,8 +32,18 @@ function mongodb_configure () {
3532
sed -i "\$aoperationProfiling:\n${INDENT_STRING}slowOpThresholdMs: 10000" ${MONGODB_CONFIG_FILE}
3633
fi
3734

38-
if ! grep -q "directoryForIndexes" "$MONGODB_CONFIG_FILE"; then
39-
sed -i "s#storage:#storage:\n${INDENT_STRING}wiredTiger:\n${INDENT_STRING}${INDENT_STRING}engineConfig:\n${INDENT_STRING}${INDENT_STRING}${INDENT_STRING}directoryForIndexes: true#g" ${MONGODB_CONFIG_FILE}
35+
if [ "$1" == "fresh" ]; then
36+
MONGODB_DATA_PATH=$(grep "dbPath" "${MONGODB_CONFIG_FILE}" | awk -F' ' '{print $2}')
37+
38+
sed -i "/directoryPerDB/d" ${MONGODB_CONFIG_FILE}
39+
sed -i "s#storage:#storage:\n${INDENT_STRING}directoryPerDB: true#g" ${MONGODB_CONFIG_FILE}
40+
41+
if ! grep -q "directoryForIndexes" "$MONGODB_CONFIG_FILE"; then
42+
sed -i "s#storage:#storage:\n${INDENT_STRING}wiredTiger:\n${INDENT_STRING}${INDENT_STRING}engineConfig:\n${INDENT_STRING}${INDENT_STRING}${INDENT_STRING}directoryForIndexes: true#g" ${MONGODB_CONFIG_FILE}
43+
fi
44+
45+
rm -rf "${MONGODB_DATA_PATH:?}"/*
46+
systemctl restart mongod > /dev/null || echo "mongodb systemctl job does not exist"
4047
fi
4148
}
4249

@@ -362,14 +369,15 @@ gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc" > /etc/yum.repos.d/mon
362369
fi
363370

364371
#backup config and remove configuration to prevent duplicates
365-
mongodb_configure
366-
367-
#mongodb might need to be restarted
368-
systemctl restart mongod > /dev/null || echo "mongodb systemctl job does not exist"
372+
mongodb_configure "fresh"
369373

370374
mongodb_check
371375
elif [ "$1" == "check" ]; then
372376
mongodb_check
373377
elif [ "$1" == "configure" ]; then
374-
mongodb_configure
378+
if [ "$2" == "fresh" ]; then
379+
mongodb_configure "fresh"
380+
else
381+
mongodb_configure
382+
fi
375383
fi

bin/upgrade/23.03/scripts/rebuild_member_permission.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pluginManager.dbConnection().then(async (countlyDb) => {
1010
// Get all members that belong to one or more group
1111
const membersToUpdate = await countlyDb.collection('members')
1212
.find({ group_id: { $exists: true, $type: 'array', $ne: [] } }) // find member that has 'group_id' property that is an array and not empty
13-
.project({ _id: 1, group_id: 1 })
13+
.project({ _id: 1, group_id: 1, global_admin: 1 })
1414
.toArray();
1515
let memberUpdates = [];
1616

@@ -41,7 +41,7 @@ pluginManager.dbConnection().then(async (countlyDb) => {
4141
}
4242

4343
return acc;
44-
}, { permission: defaultPermission, restrict: [], global_admin: false });
44+
}, { permission: defaultPermission, restrict: [], global_admin: membersToUpdate[idx].global_admin });
4545

4646
// Collect the updates for each member in an array
4747
memberUpdates.push({

0 commit comments

Comments
 (0)