Skip to content

Commit 6fa1189

Browse files
committed
Merge branch 'QT-235v2' of github.com:Countly/countly-server into QT-235v2
2 parents 0ecf14b + 84b1de0 commit 6fa1189

File tree

30 files changed

+249
-128
lines changed

30 files changed

+249
-128
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ Enterprise fixes:
4747
- [nps] Fixed bug in the editor where the "internal name" field was not mandatory
4848
- [ratings] Fixed UI bug where "Internal name" was not a mandatory field
4949

50+
Security:
51+
- Fixing minor vulnerability that would allow for unauthorized file upload
52+
5053
## Version 24.05.16
5154
Fixes:
5255
- [core] Replaced "Users" with "Sessions" label on technology home widgets

api/utils/requestProcessor.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const Promise = require('bluebird');
77
const url = require('url');
88
const common = require('./common.js');
99
const countlyCommon = require('../lib/countly.common.js');
10-
const { validateAppAdmin, validateUser, validateRead, validateUserForRead, validateUserForWrite, validateGlobalAdmin, dbUserHasAccessToCollection, validateUpdate, validateDelete, validateCreate } = require('./rights.js');
10+
const { validateAppAdmin, validateUser, validateRead, validateUserForRead, validateUserForWrite, validateGlobalAdmin, dbUserHasAccessToCollection, validateUpdate, validateDelete, validateCreate, getBaseAppFilter } = require('./rights.js');
1111
const authorize = require('./authorizer.js');
1212
const taskmanager = require('./taskmanager.js');
1313
const plugins = require('../../plugins/pluginManager.js');
@@ -2131,7 +2131,7 @@ const processRequest = (params) => {
21312131
}
21322132

21332133
dbUserHasAccessToCollection(params, params.qstring.collection, (hasAccess) => {
2134-
if (hasAccess) {
2134+
if (hasAccess || (params.qstring.db === "countly_drill" && params.qstring.collection === "drill_events") || (params.qstring.db === "countly" && params.qstring.collection === "events_data")) {
21352135
var dbs = { countly: common.db, countly_drill: common.drillDb, countly_out: common.outDb, countly_fs: countlyFs.gridfs.getHandler() };
21362136
var db = "";
21372137
if (params.qstring.db && dbs[params.qstring.db]) {
@@ -2140,6 +2140,23 @@ const processRequest = (params) => {
21402140
else {
21412141
db = common.db;
21422142
}
2143+
if (!params.member.global_admin && params.qstring.collection === "drill_events" || params.qstring.collection === "events_data") {
2144+
var base_filter = getBaseAppFilter(params.member, params.qstring.db, params.qstring.collection);
2145+
if (base_filter && Object.keys(base_filter).length > 0) {
2146+
params.qstring.query = params.qstring.query || {};
2147+
for (var key in base_filter) {
2148+
if (params.qstring.query[key]) {
2149+
params.qstring.query.$and = params.qstring.query.$and || [];
2150+
params.qstring.query.$and.push({[key]: base_filter[key]});
2151+
params.qstring.query.$and.push({[key]: params.qstring.query[key]});
2152+
delete params.qstring.query[key];
2153+
}
2154+
else {
2155+
params.qstring.query[key] = base_filter[key];
2156+
}
2157+
}
2158+
}
2159+
}
21432160
countlyApi.data.exports.fromDatabase({
21442161
db: db,
21452162
params: params,

api/utils/rights.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,32 @@ function validateWrite(params, feature, accessType, callback, callbackParam) {
10831083
});
10841084
});
10851085
}
1086-
1086+
/**
1087+
* Creates filter object to filter by member allowed collections
1088+
* @param {object} member - members object from params
1089+
* @param {string} dbName - database name as string
1090+
* @param {string} collectionName - collection Name
1091+
* @returns {object} filter object
1092+
*/
1093+
exports.getBaseAppFilter = function(member, dbName, collectionName) {
1094+
var base_filter = {};
1095+
var apps = exports.getUserApps(member);
1096+
if (dbName === "countly_drill" && collectionName === "drill_events") {
1097+
if (Array.isArray(apps) && apps.length > 0) {
1098+
base_filter.a = {"$in": apps};
1099+
}
1100+
}
1101+
else if (dbName === "countly" && collectionName === "events_data") {
1102+
var in_array = [];
1103+
if (Array.isArray(apps) && apps.length > 0) {
1104+
for (var i = 0; i < apps.length; i++) {
1105+
in_array.push(new RegExp("^" + apps[i] + "_.*"));
1106+
}
1107+
base_filter = {"_id": {"$in": in_array}};
1108+
}
1109+
}
1110+
return base_filter;
1111+
};
10871112
/**
10881113
* Validate user for create access by api_key for provided app_id (both required parameters for the request).
10891114
* @param {params} params - {@link params} object

frontend/express/app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,10 @@ Promise.all([plugins.dbConnection(countlyConfig), plugins.dbConnection("countly_
603603
app.use(function(req, res, next) {
604604
var contentType = req.headers['content-type'];
605605
if (req.method.toLowerCase() === 'post' && contentType && contentType.indexOf('multipart/form-data') >= 0) {
606+
if (!req.session?.uid || Date.now() > req.session?.expires) {
607+
res.status(401).send('Unauthorized');
608+
return;
609+
}
606610
var form = new formidable.IncomingForm();
607611
form.uploadDir = __dirname + '/uploads';
608612
form.parse(req, function(err, fields, files) {

frontend/express/public/core/app-resolution/templates/app-resolution.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
>
66
<template v-slot:header-right>
77
<cly-more-options v-if="topDropdown" size="small">
8-
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown">
9-
<!--<span :class="item.icon"></span>-->
10-
<a :href="item.value" class="bu-ml-1">{{item.label}}</a>
11-
</el-dropdown-item>
8+
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown" :command="{url: item.value}">{{item.label}}</el-dropdown-item>
129
</cly-more-options>
1310
</template>
1411
</cly-header>

frontend/express/public/core/app-version/templates/app-version.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
>
66
<template v-slot:header-right>
77
<cly-more-options v-if="topDropdown" size="small">
8-
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown">
9-
<!--<span :class="item.icon"></span>-->
10-
<a :href="item.value" class="bu-ml-1">{{item.label}}</a>
11-
</el-dropdown-item>
8+
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown" :command="{url: item.value}">{{item.label}}</el-dropdown-item>
129
</cly-more-options>
1310
</template>
1411
</cly-header>

frontend/express/public/core/carrier/templates/carrier.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
>
77
<template v-slot:header-right>
88
<cly-more-options v-if="topDropdown" size="small">
9-
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown">
10-
<!--<span :class="item.icon"></span>-->
11-
<a :href="item.value" class="bu-ml-1">{{item.label}}</a>
12-
</el-dropdown-item>
9+
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown" :command="{url: item.value}">{{item.label}}</el-dropdown-item>
1310
</cly-more-options>
1411
</template>
1512
</cly-header>

frontend/express/public/core/device-and-type/javascripts/countly.views.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,20 @@ var GridComponent = countlyVue.views.create({
443443
}
444444
return val;
445445
},
446+
onWidgetCommand: function(event) {
447+
if (event === 'add' || event === 'manage' || event === 'show') {
448+
this.graphNotesHandleCommand(event);
449+
return;
450+
}
451+
else if (event === 'zoom') {
452+
this.triggerZoom();
453+
return;
454+
}
455+
else {
456+
this.$emit('command', event);
457+
return;
458+
}
459+
},
446460
}
447461
});
448462

frontend/express/public/core/device-and-type/templates/devices-and-types.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
>
66
<template v-slot:header-right>
77
<cly-more-options v-if="topDropdown" size="small">
8-
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown">
9-
<!--<span :class="item.icon"></span>-->
10-
<a :href="item.value" class="bu-ml-1">{{item.label}}</a>
11-
</el-dropdown-item>
8+
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown" :command="{url: item.value}">{{item.label}}</el-dropdown-item>
129
</cly-more-options>
1310
</template>
1411
<template v-slot:header-tabs>

frontend/express/public/core/geo-countries/templates/countries.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
>
66
<template v-slot:header-right>
77
<cly-more-options v-if="topDropdown" size="small">
8-
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown">
9-
<!--<span :class="item.icon"></span>-->
10-
<a :href="item.value" class="bu-ml-1">{{item.label}}</a>
11-
</el-dropdown-item>
8+
<el-dropdown-item :key="idx" v-for="(item, idx) in topDropdown" :command="{url: item.value}">{{item.label}}</el-dropdown-item>
129
</cly-more-options>
1310
</template>
1411
</cly-header>

0 commit comments

Comments
 (0)