Skip to content

Commit 01a2bea

Browse files
committed
Merge branch 'master' into guidelines
# Conflicts: # Gruntfile.js # api/config.sample.js # api/configextender.js # frontend/express/app.js # frontend/express/config.sample.js # frontend/express/public/javascripts/countly/countly.views.js # package.json # plugins/browser/tests.js # plugins/crashes/api/api.js # plugins/crashes/tests.js # plugins/dbviewer/tests.js # plugins/density/tests.js # plugins/locale/tests.js # plugins/plugins/tests.js # plugins/push/api/jobs/process.js # plugins/push/api/parts/endpoints.js # plugins/push/api/parts/gcm/index.js # plugins/push/api/parts/res.js # plugins/push/api/parts/store.js # plugins/push/frontend/public/javascripts/component.emoji.js # plugins/push/frontend/public/javascripts/component.push.dash.js # plugins/push/frontend/public/javascripts/component.push.view.js # plugins/push/frontend/public/javascripts/component.singleselect.js # plugins/push/tests/tests-api-auto.js # plugins/sources/tests.js # plugins/star-rating/tests.js # plugins/system-utility/tests.js # plugins/systemlogs/api/api.js # plugins/times-of-day/tests.js # plugins/video-intelligence-monetization/tests.js # test/2.api/00.read.config.js # test/2.api/15.event.managment.js # test/3.api.write/2.write.app.sessions.js # test/3.api.write/3.reset.app.js # test/3.api.write/4.write.app.metrics.js # test/3.api.write/5.write.app.events.js # test/3.api.write/6.bulk.write.js # test/3.api.write/7.user.merge.js # test/testUtils.js
2 parents 2fde706 + 305c47d commit 01a2bea

Some content is hidden

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

66 files changed

+8659
-8756
lines changed

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## Version 18.08.1
2+
3+
**Fixes**
4+
5+
* [assistant] fixed browser side error with a empty server
6+
* [config] switch buttons resized
7+
* [core] fixed bug when admin can't edit apps in some cases
8+
* [docker] added countly-core docker image without mongodb
9+
* [docker] improved environment variable based configuration
10+
* [enterprise] make sure drill library loads before cohorts and funnels
11+
* [events] fixed padding on selectize items(omit segment)
12+
* [jsdoc] updated doc template
13+
* [plugins] use POST app config update instead of GET
14+
* [push] UI fixes
15+
* [push] fixed for p12 credentials upload resulting in unknown error
16+
* [push] improved geolocations support
17+
* [sdk] install udpated version of web sdk
18+
* [upgrade] improved checks in mongodb upgrade scripts
19+
120
## Version 18.08
221

322
**Fixes**

Dockerfile-core

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FROM phusion/baseimage:0.9.16
2+
3+
CMD ["/sbin/my_init"]
4+
5+
## Setup Countly
6+
ENV INSIDE_DOCKER 1
7+
ENV INSIDE_DOCKER_NOMONGO 1
8+
9+
COPY / /opt/countly
10+
RUN useradd -r -M -U -d /opt/countly -s /bin/false countly && \
11+
echo "countly ALL=(ALL) NOPASSWD: /usr/bin/sv restart countly-api countly-dashboard" >> /etc/sudoers.d/countly && \
12+
/opt/countly/bin/countly.install.sh
13+
14+
# Change MongoDB folder permissions and add services folders
15+
RUN mkdir /etc/service/nginx && \
16+
mkdir /etc/service/countly-api && \
17+
mkdir /etc/service/countly-dashboard && \
18+
echo "" >> /etc/nginx/nginx.conf && \
19+
echo "daemon off;" >> /etc/nginx/nginx.conf
20+
21+
# Add services' run scripts
22+
ADD ./bin/commands/docker/nginx.sh /etc/service/nginx/run
23+
ADD ./bin/commands/docker/countly-api.sh /etc/service/countly-api/run
24+
ADD ./bin/commands/docker/countly-dashboard.sh /etc/service/countly-dashboard/run
25+
26+
# Only root can change run scripts
27+
RUN chown root /etc/service/nginx/run && \
28+
chown -R countly:countly /opt/countly
29+
30+
EXPOSE 80
31+
32+
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Gruntfile.js

+45-1
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,42 @@ module.exports = function(grunt) {
202202
},
203203
src: ['test/*/*.js']
204204
}
205+
},
206+
mocha_nyc: {
207+
coverage: {
208+
src: ['test/*/*.js'], // a folder works nicely
209+
options: {
210+
coverage:true, // this will make the grunt.event.on('coverage') event listener to be triggered
211+
mask: '*.js',
212+
excludes: ['bin/*', 'frontend/*', 'extend/*', 'Gruntfile.js', 'test/*'],
213+
mochaOptions: ['--harmony', '--async-only', '--reporter', 'spec', '--timeout', '50000', '--exit'],
214+
nycOptions: ['--harmony', '--clean', 'false'],//,'--include-all-sources' '--all'
215+
reportFormats: ['none']
216+
}
217+
}
218+
},
219+
istanbul_check_coverage: {
220+
default: {
221+
options: {
222+
coverageFolder: 'coverage*', // will check both coverage folders and merge the coverage results
223+
check: {
224+
lines: 80,
225+
statements: 80
226+
}
227+
}
228+
}
205229
}
206230
});
207231

232+
//code coverage
233+
grunt.event.on('coverage', function(lcovFileContents, done){
234+
// Check below on the section "The coverage event"
235+
done();
236+
});
237+
grunt.loadNpmTasks('grunt-mocha-nyc');
238+
grunt.registerTask('coverage', ['mocha_nyc:coverage']);
239+
//-----------code coverage-----------
240+
208241
grunt.loadNpmTasks('grunt-contrib-jshint');
209242
grunt.loadNpmTasks('grunt-contrib-concat');
210243
grunt.loadNpmTasks('grunt-contrib-uglify');
@@ -231,6 +264,17 @@ module.exports = function(grunt) {
231264
plugins.push('push_approver');
232265
}
233266
}
267+
268+
if (plugins.indexOf('drill') !== -1) {
269+
if (plugins.indexOf('cohorts') !== -1) {
270+
plugins.splice(plugins.indexOf('cohorts'), 1);
271+
plugins.push('cohorts');
272+
}
273+
if (plugins.indexOf('funnels') !== -1) {
274+
plugins.splice(plugins.indexOf('funnels'), 1);
275+
plugins.push('funnels');
276+
}
277+
}
234278

235279
plugins.forEach(function(plugin) {
236280
var files, pluginPath = path.join(__dirname, 'plugins', plugin),
@@ -363,4 +407,4 @@ module.exports = function(grunt) {
363407

364408
grunt.registerTask('dist-all', ['dist', 'plugins', 'locales']);
365409

366-
};
410+
};

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Plus lots of [open source libraries](http://resources.count.ly/docs/list-of-open
5353

5454
## Security
5555

56-
We take security very seriously at Countly. Community Edition code is 100% open source and peer reviewed, to ensure nobody's Countly instance is ever compromised or hacked. If you wish to report a security issue, please email [email protected]
56+
Security is very important to us. If you discover any issue regarding security, please disclose the information responsibly by sending an email to [email protected] and **not by creating a GitHub issue**.
5757

5858
## What makes Countly unique?
5959

api/config.sample.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,4 @@ var countlyConfig = {
131131
// Set your host IP or domain to be used in the emails sent
132132
// countlyConfig.host = "YOUR_IP_OR_DOMAIN";
133133

134-
module.exports = require('./configextender')(countlyConfig);
134+
module.exports = require('./configextender')('API', countlyConfig, process.env);

api/configextender.js

+108-42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
var traverse = require('traverse');
2-
31
/**
42
* Try to parse provided value as JSON, or some other value
53
* @param {string} val - value to parse
@@ -17,6 +15,8 @@ var defaultParser = function(val) {
1715
}
1816
else if (Array.isArray(parsedVal)) {
1917
val = parsedVal;
18+
} else if (typeof parsedVal === 'object') {
19+
val = parsedVal;
2020
}
2121
}
2222
catch (error) {
@@ -25,56 +25,122 @@ var defaultParser = function(val) {
2525
return val;
2626
};
2727

28+
const OVERRIDES = {
29+
MONGODB: {
30+
REPLSETSERVERS: 'replSetServers',
31+
REPLICANAME: 'replicaName',
32+
MAX_POOL_SIZE: 'max_pool_size',
33+
DBOPTIONS: 'dbOptions',
34+
SERVEROPTIONS: 'serverOptions'
35+
},
36+
37+
API: {
38+
MAX_SOCKETS: 'max_sockets',
39+
},
40+
41+
WEB: {
42+
USE_INTERCOM: 'use_intercom',
43+
SECURE_COOKIES: 'secure_cookies'
44+
},
45+
46+
IGNOREPROXIES: 'ignoreProxies',
47+
FILESTORAGE: 'fileStorage',
48+
RELOADCONFIGAFTER: 'reloadConfigAfter'
49+
};
50+
2851
/**
29-
* Try to process configuration
30-
* @param {object} config - configuration to process
31-
* @param {function} parser - parser to use on each property
32-
**/
33-
var read = function(config, parser) {
34-
var tc = traverse(config);
35-
var tcKeyMap = {};
36-
37-
// make paths case-insensitive. Useful while converting from uppercase env
38-
// vars to camelCase variables.
39-
tc.paths().forEach(function(path) {
40-
// store paths as lowercase with their corresponding actual paths. will be
41-
// used while updating the value
42-
tcKeyMap[path.join('_').toLowerCase()] = path;
43-
});
52+
* Digs one level down in config document
53+
*
54+
* @param {[type]} config [description]
55+
* @param {[type]} over [description]
56+
* @param {[type]} name [description]
57+
* @param {[type]} value [description]
58+
* @return {[type]} [description]
59+
*/
60+
function dig (config, over, name, value) {
61+
let comps = name.split('_');
62+
63+
for (let i = comps.length; i > 0; i--) {
64+
let n = comps.slice(0, i).join('_');
65+
66+
if (n in over) {
67+
let sub;
4468

45-
var ref = process.env;
46-
var env;
47-
for (env in ref) {
48-
var val = ref[env];
69+
if (typeof over[n] === 'string') {
70+
sub = over[n];
71+
over[n] = {};
72+
} else {
73+
sub = Object.keys(config).filter(k => k.toUpperCase() === n)[0];
74+
}
4975

50-
// we only care about env vars starting with "countly"
51-
if (!env.startsWith('COUNTLY_')) {
52-
continue;
76+
name = comps.slice(i).join('_');
77+
78+
if (!name || comps.length === 1) {
79+
config[sub] = value;
80+
return true;
81+
}
82+
83+
if (typeof config[sub] === 'object') {
84+
return dig(config[sub], over[n], name, value);
85+
} else if (sub) {
86+
config[sub] = {};
87+
return dig(config[sub], over[n], name, value);
88+
} else {
89+
config[n] = {};
90+
return dig(config[n], over[n], name, value);
91+
}
92+
} else if (n === over) {
93+
name = over;
94+
config[name] = value;
95+
return true;
5396
}
54-
var path = env.split('_');
55-
if (path.length < 2) {
56-
continue;
97+
}
98+
99+
for (let i = 1; i <= comps.length; i++) {
100+
let n = comps.slice(0, i).join('_'),
101+
sub = Object.keys(config).filter(k => k.toUpperCase() === n)[0],
102+
name = comps.slice(i).join('_');
103+
104+
if (sub) {
105+
if (comps.length === 1) {
106+
config[sub] = value;
107+
return true;
108+
} else {
109+
config[sub] = typeof config[sub] === 'object' ? config[sub] : {};
110+
return dig(config[sub], {}, name, value);
111+
}
57112
}
113+
}
58114

59-
// get the underlying value of env var
60-
val = parser(val);
61-
if (!val) {
62-
continue;
115+
comps.forEach((c, i) => {
116+
if (i === comps.length - 1) {
117+
config[c.toLowerCase()] = value;
118+
} else {
119+
config = config[c.toLowerCase()] = {};
63120
}
121+
})
64122

65-
// generate path from env vars, while removing the first COUNTLY_ part
66-
var newPath = path.slice(1).map(function(node) {
67-
return parser(node.toLowerCase());
68-
});
123+
return true;
124+
}
69125

70-
// if we dont have the new path defined in config, we might be creating a
71-
// new node
72-
var location = tcKeyMap[newPath.join('_')] || newPath;
73-
tc.set(location, val);
126+
module.exports = function (mode, config, opts) {
127+
// back compatibility
128+
if (typeof mode === 'object') {
129+
config = mode;
130+
mode = 'API';
131+
opts = process.env;
74132
}
75-
};
133+
134+
if (['API', 'FRONTEND'].indexOf(mode) === -1) {
135+
throw new Error('Invalid config mode ' + mode);
136+
}
137+
138+
config = JSON.parse(JSON.stringify(config));
139+
140+
Object.keys(opts).filter(n => n.indexOf(`COUNTLY_CONFIG_${mode}_`) === 0).forEach(n => {
141+
let comps = n.split('_').slice(3);
142+
dig(config, OVERRIDES, comps.join('_'), parser(opts[n]));
143+
});
76144

77-
module.exports = function(config) {
78-
read(config, defaultParser);
79145
return config;
80146
};

bin/commands/docker/countly-api.sh

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#!/usr/bin/env bash
22

3-
until mongo localhost --eval "db.stats()" | grep "collections"
4-
do
5-
echo
6-
echo "[api] waiting for MongoDB to allocate files ..."
7-
sleep 1
8-
done
9-
sleep 3
10-
echo "[api] MongoDB started"
3+
if [ "$INSIDE_DOCKER_NOMONGO" != "1" ]
4+
then
5+
until mongo localhost --eval "db.stats()" | grep "collections"
6+
do
7+
echo
8+
echo "[api] waiting for MongoDB to allocate files ..."
9+
sleep 1
10+
done
11+
sleep 3
12+
echo "[api] MongoDB started"
13+
fi
1114

1215
exec /sbin/setuser countly /usr/bin/nodejs /opt/countly/api/api.js
+11-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#!/usr/bin/env bash
22

3-
until mongo localhost --eval "db.stats()" | grep "collections"
4-
do
5-
echo
6-
echo "[dashboard] waiting for MongoDB to allocate files ..."
7-
sleep 1
8-
done
9-
sleep 3
10-
echo "[dashboard] MongoDB started"
3+
if [ "$INSIDE_DOCKER_NOMONGO" != "1" ]
4+
then
5+
until mongo localhost --eval "db.stats()" | grep "collections"
6+
do
7+
echo
8+
echo "[dashboard] waiting for MongoDB to allocate files ..."
9+
sleep 1
10+
done
11+
sleep 3
12+
echo "[dashboard] MongoDB started"
13+
fi
1114

1215
exec /sbin/setuser countly /usr/bin/nodejs /opt/countly/frontend/express/app.js

bin/config/supervisord.conf

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ programs=countly-dashboard, countly-api
2222
[program:countly-dashboard]
2323
environment=NODE_ENV=production
2424
command=node %(here)s/../../frontend/express/app.js
25+
;command=nyc node %(here)s/../../frontend/express/app.js ;replace previous line with this in case you want to run nyc
2526
directory=.
2627
autorestart=true
2728
redirect_stderr=true
@@ -35,6 +36,7 @@ loglevel=warn
3536
[program:countly-api]
3637
environment=NODE_ENV=production
3738
command=node %(here)s/../../api/api.js
39+
;command=nyc --nycrc-path nyc.config node %(here)s/../../api/api.js ;replace previous line with this in case you want to run nyc
3840
directory=%(here)s
3941
autorestart=true
4042
redirect_stderr=true

bin/countly.install.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22
totalm=$(free -m | awk '/^Mem:/{print $2}')
3-
if [ "$totalm" -lt "2000" ]; then
3+
if [ "$totalm" -lt "1800" ]; then
44
echo "Countly requires at least 2Gb of RAM"
55
exit 1
66
fi
@@ -12,4 +12,4 @@ elif [ -f /etc/lsb-release ]; then
1212
bash $DIR/countly.install_ubuntu.sh 2>&1 | tee $DIR/../log/countly-install-$DATE.log
1313
elif [ -f /etc/redhat-release ]; then
1414
bash $DIR/countly.install_rhel.sh 2>&1 | tee $DIR/../log/countly-install-$DATE.log
15-
fi
15+
fi

0 commit comments

Comments
 (0)