Refactoring organisation, bundling and security improvements (#6765)

* * Simplified bundling to just one bundle
* Removed cache invalidation token from bundling
* Generate strong persistent random string on deploy to use for JWT signing
* WIP: moving api-secret and JWT signing to a separate centralized security component
* Moved some server components away from project root
* Fix issues reported by linter

* Ignore detect-object-injection everywhere but the client

* Make admin message button red

* Remove alarms for some security alerts on code

* api_secret is now fully contained in the enclave
This commit is contained in:
Sulka Haro
2021-02-02 19:53:30 +02:00
committed by GitHub
parent 3ab718ca37
commit d7e011d8f5
64 changed files with 362 additions and 249 deletions
+26 -17
View File
@@ -1,26 +1,35 @@
module.exports = {
"plugins": [
"security"
'plugins': [
'security'
],
"extends": [
"eslint:recommended",
"plugin:security/recommended"
'extends': [
'eslint:recommended',
'plugin:security/recommended'
],
"parser": "babel-eslint",
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true,
"mocha": true,
"jquery": true
'parser': 'babel-eslint',
'env': {
'browser': true,
'commonjs': true,
'es6': true,
'node': true,
'mocha': true,
'jquery': true
},
"rules": {
"no-unused-vars": [
"error",
'rules': {
'security/detect-object-injection' : 0,
'no-unused-vars': [
'error',
{
"varsIgnorePattern": "should|expect"
'varsIgnorePattern': 'should|expect'
}
]
},
'overrides': [
{
'files': ['lib/client/*.js'],
'rules': {
'security/detect-object-injection': 1
}
}
],
};
+1
View File
@@ -9,6 +9,7 @@ bundle/bundle.out.js
*.iml
my.env
my.*.env
*.pem
static/bower_components/
.*.sw?
+5
View File
@@ -0,0 +1,5 @@
require('crypto').randomBytes(1024, function(err, buffer) {
var token = buffer.toString('hex');
console.log(token);
});
+6
View File
@@ -28,6 +28,12 @@ window.Nightscout = {
admin_plugins: require('../lib/admin_plugins/')()
};
window.Nightscout.report_plugins_preinit = require('../lib/report_plugins/');
window.Nightscout.predictions = require('../lib/report/predictions');
window.Nightscout.reportclient = require('../lib/report/reportclient');
window.Nightscout.profileclient = require('../lib/profile/profileeditor');
window.Nightscout.foodclient = require('../lib/food/food');
console.info('Nightscout bundle ready');
// Needed for Hot Module Replacement
+4 -4
View File
@@ -13,13 +13,13 @@ function create (env, ctx) {
app.set('version', env.version);
app.set('units', env.DISPLAY_UNITS);
// Only allow access to the API if API_SECRET is set on the server.
// Only allow access to the API if API KEY is set on the server.
app.disable('api');
if (env.api_secret) {
console.log('API_SECRET present, enabling API');
if (env.enclave.isApiKeySet()) {
console.log('API KEY present, enabling API');
app.enable('api');
} else {
console.log('API_SECRET not found, API disabled');
console.log('API KEY has not been set, API disabled');
}
if (env.settings.enable) {
+8 -11
View File
@@ -96,7 +96,7 @@ function init (env, ctx) {
}
function authorizeAdminSecret (secret) {
return (env.api_secret && env.api_secret.length > 12) ? (secret === env.api_secret) : false;
return env.enclave.isApiKey(secret);
}
authorization.seenPermissions = [];
@@ -185,7 +185,7 @@ function init (env, ctx) {
// Tokens have to be well formed JWTs
try {
const verified = await jwt.verify(data.token, env.api_secret);
const verified = env.enclave.verifyJWT(data.token);
token = verified.accessToken;
} catch (err) {}
@@ -237,7 +237,7 @@ function init (env, ctx) {
/**
* Check if the client has a permission execute an action,
* based on an API_SECRET or JWT in the request.
* based on an API KEY or JWT in the request.
*
* Used to authorize API calls
*
@@ -281,8 +281,9 @@ function init (env, ctx) {
*/
authorization.authorize = function authorize (accessToken) {
let userToken = accessToken
const decodedToken = jwt.decode(accessToken);
let userToken = accessToken;
const decodedToken = env.enclave.verifyJWT(accessToken);
if (decodedToken && decodedToken.accessToken) {
userToken = decodedToken.accessToken;
@@ -292,18 +293,14 @@ function init (env, ctx) {
var authorized = null;
if (subject) {
var token = jwt.sign({ accessToken: subject.accessToken }, env.api_secret, { expiresIn: '8h' });
//decode so we can tell the client the issued and expired times
var decoded = jwt.decode(token);
const token = env.enclave.signJWT({ accessToken: subject.accessToken });
const decoded = env.enclave.verifyJWT(token);
var roles = _.uniq(subject.roles.concat(defaultRoles));
authorized = {
token
, sub: subject.name
// not sending roles to client to prevent us from treating them as magic
// instead group permissions by role so the we can create correct shiros on the client
, permissionGroups: _.map(roles, storage.roleToPermissions)
, iat: decoded.iat
, exp: decoded.exp
+2 -5
View File
@@ -151,12 +151,9 @@ function init (env, ctx) {
}
storage.subjects = _.map(results, function eachSubject (subject) {
if (env.api_secret) {
var shasum = crypto.createHash('sha1');
shasum.update(env.api_secret);
shasum.update(subject._id.toString());
if (env.enclave.isApiKeySet()) {
subject.digest = env.enclave.getSubjectHash(subject._id.toString());
var abbrev = subject.name.toLowerCase().replace(/[\W]/g, '').substring(0, 10);
subject.digest = shasum.digest('hex');
subject.accessToken = abbrev + '-' + subject.digest.substring(0, 16);
subject.accessTokenDigest = storage.getSHA1(subject.accessToken);
}
+10 -8
View File
@@ -593,14 +593,16 @@ function init (client, $) {
if (qp.hideafteruse) {
qp.hidden = true;
var apisecrethash = localStorage.getItem('apisecrethash');
var dataJson = JSON.stringify(qp, null, ' ');
var xhr = new XMLHttpRequest();
xhr.open('PUT', '/api/v1/food/', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.setRequestHeader('api-secret', apisecrethash);
xhr.send(dataJson);
$.ajax({
method: 'PUT'
, url: '/api/v1/food/'
, headers: client.headers()
, data: qp
}).done(function treatmentSaved (response) {
console.info('quick pick saved', response);
}).fail(function treatmentSaveFail (response) {
console.info('quick pick failed to save', response);
});
}
}
+4 -4
View File
@@ -146,7 +146,7 @@ client.init(function loaded () {
$('#fe_filter_subcategory').empty().append(new Option(translate('(none)'),''));
if (filter.category !== '') {
for (s in categories[filter.category]) {
if (categories[filter.category].hasOwnProperty(s)) {
if (Object.prototype.hasOwnProperty.call(categories[filter.category],s)) {
$('#fe_filter_subcategory').append(new Option(s,s));
}
}
@@ -162,7 +162,7 @@ client.init(function loaded () {
$('#fe_subcategory_list').empty().append(new Option(translate('(none)'),''));
if (foodrec.category !== '') {
for (s in categories[foodrec.category]) {
if (categories[foodrec.category].hasOwnProperty(s)) {
if (Object.prototype.hasOwnProperty.call(categories[foodrec.category],s)) {
$('#fe_subcategory_list').append(new Option(s,s));
}
}
@@ -198,7 +198,7 @@ client.init(function loaded () {
$('#fe_filter_category').empty().append(new Option(translate('(none)'),''));
$('#fe_category_list').empty().append(new Option(translate('(none)'),''));
for (var s in categories) {
if (categories.hasOwnProperty(s)) {
if (Object.prototype.hasOwnProperty.call(categories,s)) {
$('#fe_filter_category').append(new Option(s,s));
$('#fe_category_list').append(new Option(s,s));
}
@@ -398,7 +398,7 @@ client.init(function loaded () {
function savePortions(event) {
var index = $(this).attr('index');
var findex = $(this).attr('findex');
var val = parseFloat($(this).val().replace(/\,/g,'.'));
var val = parseFloat($(this).val().replace(/,/g,'.'));
foodquickpick[index].foods[findex].portions=val;
calculateCarbs(index);
drawQuickpick();
+11 -7
View File
@@ -78,28 +78,32 @@ function init (fs) {
translated = language.translateCS(text);
}
let keys = null;
var hasCI = false;
var hasParams = false;
if (options && options.params) {
keys = options.params;
if (options) {
hasCI = Object.prototype.hasOwnProperty.call(options,'ci');
hasParams = Object.prototype.hasOwnProperty.call(options,'params');
}
if (options && !options.hasOwnProperty('ci') && !options.hasOwnProperty('params')) {
var keys = hasParams ? options.params : null;
if (options && !hasCI && !hasParams) {
keys = [];
for (var i = 1; i < arguments.length; i++) {
keys.push(arguments[i]);
}
}
if (options && (options.hasOwnProperty('ci') || options.hasOwnProperty('params')) && arguments.length > 2) {
if (options && (hasCI || hasParams) && arguments.length > 2) {
if (!keys) keys = [];
for (var i = 2; i < arguments.length; i++) {
for (i = 2; i < arguments.length; i++) {
keys.push(arguments[i]);
}
}
if (keys) {
for (var i = 0; i < keys.length; i++) {
for (i = 0; i < keys.length; i++) {
// eslint-disable-next-line no-useless-escape
var r = new RegExp('\%' + (i + 1), 'g');
translated = translated.replace(r, keys[i]);
+5 -5
View File
@@ -100,12 +100,12 @@ var init = function init () {
_.each(mongoprofile.store, function eachStoredProfile (p) {
// allign with default profile
for (var key in defaultprofile) {
if (defaultprofile.hasOwnProperty(key) && !p.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(defaultprofile,key) && !Object.prototype.hasOwnProperty.call(p,key)) {
p[key] = defaultprofile[key];
}
}
for (key in p) {
if (p.hasOwnProperty(key) && !defaultprofile.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(p,key) && !Object.prototype.hasOwnProperty.call(defaultprofile,key)) {
delete p[key];
}
}
@@ -232,7 +232,7 @@ var init = function init () {
$('#pe_profiles').empty();
for (var key in record.store) {
if (record.store.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(record.store,key)) {
$('#pe_profiles').append('<option value="' + key + '">' + key + '</option>');
}
}
@@ -656,7 +656,7 @@ var init = function init () {
var adjustedRecord = _.cloneDeep(record);
for (var key in adjustedRecord.store) {
if (adjustedRecord.store.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(adjustedRecord.store,key)) {
var profile = adjustedRecord.store[key];
if (!profile.perGIvalues) {
delete profile.perGIvalues;
@@ -707,7 +707,7 @@ var init = function init () {
function getFirstAvailableProfile(record) {
var availableProfiles = [];
for (var key in record.store) {
if (record.store.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(record.store,key)) {
if (key !== currentprofile) {
availableProfiles.push(key);
}
+30 -39
View File
@@ -4,11 +4,23 @@ const _get = require('lodash/get');
const express = require('express');
const compression = require('compression');
const bodyParser = require('body-parser');
const randomToken = require('random-token');
const path = require('path');
const fs = require('fs');
const ejs = require('ejs');
function resolvePath(filePath) {
if (fs.existsSync(filePath)) return filePath;
let p = path.join(__dirname, filePath);
if (fs.existsSync(p)) return p;
p = path.join(process.cwd(), filePath);
if (fs.existsSync(p)) return p;
return require.resolve(filePath);
}
function create (env, ctx) {
var app = express();
var appInfo = env.name + ' ' + env.version;
@@ -101,27 +113,14 @@ function create (env, ctx) {
}
app.set('view engine', 'ejs');
// this allows you to render .html files as templates in addition to .ejs
app.engine('html', require('ejs').renderFile);
app.set("views", path.join(__dirname, "views/"));
app.set("views", resolvePath('/views'));
let cacheBuster = 'developmentMode';
let lastModified = new Date();
let busterPath = '/tmp/cacheBusterToken';
if (process.env.NODE_ENV !== 'development') {
busterPath = process.cwd() + busterPath;
} else {
busterPath = __dirname + busterPath;
}
if (fs.existsSync(busterPath)) {
cacheBuster = fs.readFileSync(busterPath).toString().trim();
var stats = fs.statSync(busterPath);
lastModified = stats.mtime;
}
let cacheBuster = process.env.NODE_ENV == 'development' ? 'developmentMode': randomToken(16);
app.locals.cachebuster = cacheBuster;
let lastModified = new Date();
app.get("/robots.txt", (req, res) => {
res.setHeader('Content-Type', 'text/plain');
res.send(['User-agent: *','Disallow: /'].join('\n'));
@@ -133,7 +132,7 @@ function create (env, ctx) {
res.setHeader('Last-Modified', lastModified.toUTCString());
}
res.send(ejs.render(fs.readFileSync(
require.resolve(`${__dirname}/views/service-worker.js`),
resolvePath('/views/service-worker.js'),
{ encoding: 'utf-8' }),
{ locals: app.locals}
));
@@ -147,19 +146,19 @@ function create (env, ctx) {
console.log('Development environment detected, setting static file cache age to 1 second');
}
var staticFiles = express.static(env.static_files, {
var staticFiles = express.static(resolvePath(env.static_files), {
maxAge
});
// serve the static content
app.use(staticFiles);
app.use('/translations', express.static('translations', {
app.use('/translations', express.static(resolvePath('/translations'), {
maxAge
}));
if (ctx.bootErrors && ctx.bootErrors.length > 0) {
const bootErrorView = require('./lib/server/booterror')(env, ctx);
const bootErrorView = require('./booterror')(env, ctx);
bootErrorView.setLocals(app.locals);
app.get('*', bootErrorView);
return app;
@@ -185,11 +184,11 @@ function create (env, ctx) {
///////////////////////////////////////////////////
// api and json object variables
///////////////////////////////////////////////////
const apiRoot = require('./lib/api/root')(env, ctx);
var api = require('./lib/api/')(env, ctx);
var api3 = require('./lib/api3/')(env, ctx);
var ddata = require('./lib/data/endpoints')(env, ctx);
var notificationsV2 = require('./lib/api/notifications-v2')(app, ctx);
const apiRoot = require('../api/root')(env, ctx);
var api = require('../api/')(env, ctx);
var api3 = require('../api3/')(env, ctx);
var ddata = require('../data/endpoints')(env, ctx);
var notificationsV2 = require('../api/notifications-v2')(app, ctx);
app.use(compression({
filter: function shouldCompress (req, res) {
@@ -242,7 +241,7 @@ function create (env, ctx) {
});
});
const clockviews = require('./lib/server/clocks.js')(env, ctx);
const clockviews = require('./clocks.js')(env, ctx);
clockviews.setLocals(app.locals);
app.use("/clock", clockviews);
@@ -278,7 +277,7 @@ function create (env, ctx) {
const swaggerUi = require('swagger-ui-express');
const swaggerUseSchema = schema => (...args) => swaggerUi.setup(schema)(...args);
const swaggerDocument = require('./swagger.json');
const swaggerDocumentApiV3 = require('./lib/api3/swagger.json');
const swaggerDocumentApiV3 = require('../api3/swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUseSchema(swaggerDocument));
app.use('/api3-docs', swaggerUi.serve, swaggerUseSchema(swaggerDocumentApiV3));
@@ -291,7 +290,6 @@ function create (env, ctx) {
// if production, rely on postinstall script to run packaging for us
app.locals.bundle = '/bundle';
app.locals.mode = 'production';
if (process.env.NODE_ENV === 'development') {
@@ -302,7 +300,7 @@ function create (env, ctx) {
app.locals.bundle = '/devbundle';
const webpack = require('webpack');
var webpack_conf = require('./webpack.config');
var webpack_conf = require('../../webpack.config');
const middleware = require('webpack-dev-middleware');
const compiler = webpack(webpack_conf);
@@ -320,16 +318,9 @@ function create (env, ctx) {
}
// Production bundling
var tmpFiles;
if (fs.existsSync(process.cwd() + '/tmp/cacheBusterToken')) {
tmpFiles = express.static('tmp', {
const tmpFiles = express.static(resolvePath('/tmp/public'), {
maxAge: maxAge
});
} else {
tmpFiles = express.static(__dirname + '/tmp', {
maxAge: maxAge
});
}
// serve the static content
app.use('/bundle', tmpFiles);
@@ -350,7 +341,7 @@ function create (env, ctx) {
, coffee_match: /coffeescript/
, json_match: /json/
, cssmin: myCssmin
, cache: __dirname + '/tmp'
, cache: resolvePath('/tmp/public')
, onerror: undefined
, }));
+1 -1
View File
@@ -111,7 +111,7 @@ function boot (env, language) {
err: 'MONGODB_URI setting is missing, cannot connect to database'});
}
if (!env.api_secret) {
if (!env.enclave.isApiKeySet()) {
ctx.bootErrors.push({'desc': 'Mandatory setting missing',
err: 'API_SECRET setting is missing, cannot enable REST API'});
}
+81
View File
@@ -0,0 +1,81 @@
'use strict;'
const path = require('path');
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const fs = require('fs');
// this is a class for holding potentially sensitive data in the app
// the class also implement functions to use the data, so the data is not shared outside the class
const init = function init () {
const enclave = {};
const secrets = {};
const apiKey = Symbol('api-secret');
const apiKeySHA1 = Symbol('api-secretSHA1');
const apiKeySHA512 = Symbol('api-secretSHA512');
const jwtKey = Symbol('jwtkey');
let apiKeySet = false;
function readKey (filename) {
let filePath = path.resolve(__dirname + '/../../tmp/' + filename);
if (fs.existsSync(filePath)) {
return fs.readFileSync(filePath).toString().trim();
}
console.error('Key file ', filePath, 'not found');
return null;
}
secrets[jwtKey] = readKey('randomString');
function genHash(data, algorihtm) {
const hash = crypto.createHash(algorihtm);
data = hash.update(data, 'utf-8');
return data.digest('hex');
}
enclave.setApiKey = function setApiKey (keyValue) {
if (keyValue.length < 12) return;
apiKeySet = true;
secrets[apiKey] = keyValue;
secrets[apiKeySHA1] = genHash(keyValue,'sha1');
secrets[apiKeySHA512] = genHash(keyValue,'sha512');
}
enclave.isApiKeySet = function isApiKeySet () {
return isApiKeySet;
}
enclave.isApiKey = function isApiKey (keyValue) {
return keyValue == secrets[apiKeySHA1] || keyValue == secrets[apiKeySHA512];
}
enclave.setJWTKey = function setJWTKey (keyValue) {
secrets[jwtKey] = keyValue;
}
enclave.signJWT = function signJWT(token, lifetime) {
const lt = lifetime ? lifetime : '8h';
return jwt.sign(token, secrets[jwtKey], { expiresIn: lt });
}
enclave.verifyJWT = function verifyJWT(tokenString) {
try {
return jwt.verify(tokenString, secrets[jwtKey]);
} catch(err) {
return null;
}
}
enclave.getSubjectHash = function getSubjectHash(id) {
var shasum = crypto.createHash('sha1');
shasum.update(secrets[apiKey]);
shasum.update(id);
return shasum.digest('hex');
}
return enclave;
}
module.exports = init;
+12 -10
View File
@@ -5,16 +5,16 @@ const _trim = require('lodash/trim');
const _forIn = require('lodash/forIn');
const _startsWith = require('lodash/startsWith');
const _camelCase = require('lodash/camelCase');
const enclave = require('./enclave');
const owasp = require('owasp-password-strength-test');
const fs = require('fs');
const crypto = require('crypto');
const consts = require('./lib/constants');
const consts = require('../constants');
const env = {
settings: require('./lib/settings')()
settings: require('../settings')()
};
var shadowEnv;
@@ -34,13 +34,14 @@ function config ( ) {
env.PORT = readENV('PORT', 1337);
env.HOSTNAME = readENV('HOSTNAME', null);
env.IMPORT_CONFIG = readENV('IMPORT_CONFIG', null);
env.static_files = readENV('NIGHTSCOUT_STATIC_FILES', __dirname + '/static/');
env.static_files = readENV('NIGHTSCOUT_STATIC_FILES', '/static');
env.debug = {
minify: readENVTruthy('DEBUG_MINIFY', true)
};
env.err = [];
env.notifies = [];
env.enclave = enclave();
setSSL();
setAPISecret();
@@ -85,10 +86,12 @@ function setAPISecret() {
console.error(msg);
env.err.push({ desc: msg });
} else {
var shasum = crypto.createHash('sha1');
shasum.update(readENV('API_SECRET'));
var testresult = owasp.test(readENV('API_SECRET'));
const apiSecret = readENV('API_SECRET');
delete process.env.API_SECRET;
env.enclave.setApiKey(apiSecret);
var testresult = owasp.test(apiSecret);
const messages = testresult.errors;
if (messages) {
@@ -98,13 +101,12 @@ function setAPISecret() {
env.notifies.push({persistent: true, title: 'Security issue', message: m + ' Please change your API_SECRET to reduce risk of unauthorized access.'});
});
}
env.api_secret = shasum.digest('hex');
}
}
}
function setVersion() {
var software = require('./package.json');
var software = require('../../package.json');
env.version = software.version;
env.name = software.name;
}
@@ -123,7 +125,7 @@ function setStorage() {
// TODO: clean up a bit
// Some people prefer to use a json configuration file instead.
// This allows a provided json config to override environment variables
var DB = require('./database_configuration.json'),
var DB = require('../../database_configuration.json'),
DB_URL = DB.url ? DB.url : env.storageURI,
DB_COLLECTION = DB.collection ? DB.collection : env.entries_collection;
env.storageURI = DB_URL;
+3 -3
View File
@@ -28,7 +28,7 @@
const fs = require('fs');
const env = require('./env')( );
const language = require('./lib/language')();
const language = require('../language')();
const translate = language.set(env.settings.language).translate;
language.loadLocalization(fs);
@@ -47,7 +47,7 @@ function create (app) {
return transport.createServer(app);
}
require('./lib/server/bootevent')(env, language).boot(function booted (ctx) {
require('./bootevent')(env, language).boot(function booted (ctx) {
console.log('Boot event processing completed');
@@ -68,7 +68,7 @@ require('./lib/server/bootevent')(env, language).boot(function booted (ctx) {
///////////////////////////////////////////////////
// setup socket io for data and message transmission
///////////////////////////////////////////////////
var websocket = require('./lib/server/websocket')(env, ctx, server);
var websocket = require('./websocket')(env, ctx, server);
ctx.bus.on('data-processed', function() {
websocket.update();
+1 -1
View File
@@ -41,7 +41,7 @@ function init (env, ctx, server) {
if (verParse) {
versionNum = 10000 * parseInt(verParse[1]) + 100 * parseInt(verParse[2]) + 1 * parseInt(verParse[3]);
}
var apiEnabled = env.api_secret ? true : false;
var apiEnabled = env.enclave.isApiKeySet();
var activeProfile = ctx.ddata.lastProfileFromSwitch;
+9 -9
View File
@@ -26,23 +26,23 @@
"url": "https://github.com/nightscout/cgm-remote-monitor/issues"
},
"scripts": {
"start": "node server.js",
"start": "node lib/server/server.js",
"test": "env-cmd -f ./my.test.env mocha --require ./tests/hooks.js -exit ./tests/*.test.js",
"test-single": "env-cmd -f ./my.test.env mocha --require ./tests/hooks.js --exit ./tests/$TEST.test.js",
"test-ci": "env-cmd -f ./ci.test.env nyc --reporter=lcov --reporter=text-summary mocha --require ./tests/hooks.js --exit ./tests/*.test.js",
"env": "env",
"postinstall": "webpack --mode production --config webpack.config.js && npm run-script update-buster",
"bundle": "webpack --mode production --config webpack.config.js && npm run-script update-buster",
"bundle-dev": "webpack --mode development --config webpack.config.js && npm run-script update-buster",
"postinstall": "webpack --mode production --config webpack.config.js && npm run-script generate-keys",
"bundle": "webpack --mode production --config webpack.config.js && npm run-script generate-keys",
"bundle-dev": "webpack --mode development --config webpack.config.js && npm run-script generate-keys",
"bundle-analyzer": "webpack --mode development --config webpack.config.js --profile --json > stats.json && webpack-bundle-analyzer stats.json",
"update-buster": "node bin/generateCacheBuster.js >tmp/cacheBusterToken",
"generate-keys": "node bin/generateRandomString.js >tmp/randomString",
"coverage": "cat ./coverage/lcov.info | env-cmd -f ./ci.test.env codacy-coverage",
"dev": "env-cmd -f ./my.env nodemon --inspect server.js 0.0.0.0",
"dev-test": "env-cmd -f ./my.devtest.env nodemon --inspect server.js 0.0.0.0",
"prod": "env-cmd -f ./my.prod.env node server.js 0.0.0.0",
"dev": "env-cmd -f ./my.env nodemon --inspect lib/server/server.js 0.0.0.0",
"dev-test": "env-cmd -f ./my.devtest.env nodemon --inspect lib/server/server.js 0.0.0.0",
"prod": "env-cmd -f ./my.prod.env node lib/server/server.js 0.0.0.0",
"lint": "eslint lib"
},
"main": "server.js",
"main": "lib/server/server.js",
"nodemonConfig": {
"ignore": [
"tests/*",
+1 -1
View File
@@ -10,7 +10,7 @@ describe('Clean MONGO after tests', function ( ) {
var api = require('../lib/api/');
beforeEach(function (done) {
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../env')();
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
this.wares = require('../lib/middleware/')(self.env);
+1 -1
View File
@@ -70,7 +70,7 @@ describe('admintools', function ( ) {
before(function (done) {
benv.setup(function() {
benv.require(__dirname + '/../tmp/js/bundle.app.js');
benv.require(__dirname + '/../tmp/public/js/bundle.app.js');
self.$ = $;
+3 -1
View File
@@ -13,7 +13,9 @@ describe('Alexa REST api', function ( ) {
const apiRoot = require('../lib/api/root');
const api = require('../lib/api/');
before(function (done) {
var env = require('../env')( );
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../lib/server/env')( );
env.settings.enable = ['alexa'];
env.settings.authDefaultRoles = 'readable';
env.api_secret = 'this is my long pass phrase';
+6 -5
View File
@@ -8,11 +8,12 @@ var language = require('../lib/language')();
describe('Devicestatus API', function ( ) {
this.timeout(10000);
var self = this;
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
var api = require('../lib/api/');
beforeEach(function (done) {
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../env')();
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
this.wares = require('../lib/middleware/')(self.env);
@@ -31,7 +32,7 @@ describe('Devicestatus API', function ( ) {
console.log('Inserting devicestatus entry');
request(self.app)
.post('/api/devicestatus/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.send({
device: 'xdripjs://rigName'
, xdripjs: {
@@ -53,7 +54,7 @@ describe('Devicestatus API', function ( ) {
.get('/api/devicestatus/')
.query('find[created_at][$gte]=2018-12-16')
.query('find[created_at][$lte]=2018-12-17')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
console.log(JSON.stringify(response.body[0]));
@@ -69,7 +70,7 @@ describe('Devicestatus API', function ( ) {
request(self.app)
.delete('/api/devicestatus/')
.query('find[created_at][$gte]=2018-12-16')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.end(function (err) {
if (err) {
@@ -80,7 +81,7 @@ describe('Devicestatus API', function ( ) {
request(self.app)
.get('/api/devicestatus/')
.query('find[created_at][$lte]=2018-12-16')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
response.body.length.should.equal(0);
+13 -10
View File
@@ -9,10 +9,13 @@ require('should');
describe('Entries REST api', function ( ) {
var entries = require('../lib/api/entries/');
var self = this;
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
this.timeout(10000);
before(function (done) {
self.env = require('../env')( );
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')( );
self.env.settings.authDefaultRoles = 'readable';
self.wares = require('../lib/middleware/')(self.env);
self.archive = null;
@@ -254,7 +257,7 @@ describe('Entries REST api', function ( ) {
console.log('Inserting glucose entry')
request(self.app)
.post('/entries/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.send({
"type": "sgv", "sgv": "199", "dateString": "2014-07-20T00:44:15.000-07:00"
, "date": 1405791855000, "device": "dexcom", "direction": "NOT COMPUTABLE"
@@ -268,7 +271,7 @@ describe('Entries REST api', function ( ) {
console.log('Ensuring glucose entry was inserted successfully');
request(self.app)
.get('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
var entry = response.body[0];
@@ -283,7 +286,7 @@ describe('Entries REST api', function ( ) {
console.log('Deleting test glucose entry');
request(self.app)
.delete('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.end(function (err) {
if (err) {
@@ -293,7 +296,7 @@ describe('Entries REST api', function ( ) {
console.log('Testing if glucose entry was deleted');
request(self.app)
.get('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
response.body.length.should.equal(0);
@@ -307,12 +310,12 @@ describe('Entries REST api', function ( ) {
});
});
it('post multipole entries, query, delete, verify gone', function (done) {
it('post multiple entries, query, delete, verify gone', function (done) {
// insert a glucose entry - needs to be unique from example data
console.log('Inserting glucose entry')
request(self.app)
.post('/entries/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.send([{
"type": "sgv", "sgv": "199", "dateString": "2014-07-20T00:44:15.000-07:00"
, "date": 1405791855000, "device": "dexcom", "direction": "NOT COMPUTABLE"
@@ -329,7 +332,7 @@ describe('Entries REST api', function ( ) {
console.log('Ensuring glucose entry was inserted successfully');
request(self.app)
.get('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
var entry = response.body[0];
@@ -345,7 +348,7 @@ describe('Entries REST api', function ( ) {
console.log('Deleting test glucose entry');
request(self.app)
.delete('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.end(function (err) {
if (err) {
@@ -355,7 +358,7 @@ describe('Entries REST api', function ( ) {
console.log('Testing if glucose entries were deleted');
request(self.app)
.get('/entries.json?find[dateString][$gte]=2014-07-20&count=100')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.expect(function (response) {
response.body.length.should.equal(0);
+6 -3
View File
@@ -13,10 +13,13 @@ describe('Security of REST API V1', function() {
this.timeout(30000);
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
before(function(done) {
var api = require('../lib/api/');
self.env = require('../env')();
self.env.api_secret = 'this is my long pass phrase';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'denied';
this.wares = require('../lib/middleware/')(self.env);
self.app = require('express')();
@@ -71,7 +74,7 @@ describe('Security of REST API V1', function() {
it('Data load should succeed with API SECRET', function(done) {
request(self.app)
.get('/api/v1/entries.json')
.set('api-secret', self.env.api_secret)
.set('api-secret', known)
.expect(200)
.end(function(err, res) {
done();
+3 -1
View File
@@ -8,7 +8,9 @@ require('should');
describe('Status REST api', function ( ) {
var api = require('../lib/api/');
before(function (done) {
var env = require('../env')( );
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../lib/server/env')( );
env.settings.enable = ['careportal', 'rawbg'];
env.settings.authDefaultRoles = 'readable';
env.api_secret = 'this is my long pass phrase';
+11 -9
View File
@@ -10,10 +10,12 @@ describe('Treatment API', function ( ) {
this.timeout(10000);
var self = this;
var api_secret_hash = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
var api = require('../lib/api/');
beforeEach(function (done) {
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../env')();
self.env = require('../lib/server/env')();
self.env.settings.authDefaultRoles = 'readable';
self.env.settings.enable = ['careportal', 'api'];
this.wares = require('../lib/middleware/')(self.env);
@@ -37,7 +39,7 @@ describe('Treatment API', function ( ) {
var now = (new Date()).toISOString();
request(self.app)
.post('/api/treatments/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.send({eventType: 'Meal Bolus', created_at: now, carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl', notes: '<IMG SRC="javascript:alert(\'XSS\');">'})
.expect(200)
.end(function (err) {
@@ -90,7 +92,7 @@ describe('Treatment API', function ( ) {
self.ctx.treatments().remove({ }, function ( ) {
request(self.app)
.post('/api/treatments/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.send({eventType: 'Meal Bolus', created_at: _moment(current_time).format("YYYY-MM-DDTHH:mm:ss.SSSZZ"), carbs: '30', insulin: '2.00', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'})
.expect(200)
.end(function (err) {
@@ -124,7 +126,7 @@ describe('Treatment API', function ( ) {
var now = (new Date()).toISOString();
request(self.app)
.post('/api/treatments/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.send([
{eventType: 'BG Check', created_at: now, glucose: 100, preBolus: '0', glucoseType: 'Finger', units: 'mg/dl', notes: ''}
, {eventType: 'Meal Bolus', created_at: now, carbs: '30', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'}
@@ -151,7 +153,7 @@ describe('Treatment API', function ( ) {
var now = (new Date()).toISOString();
request(self.app)
.post('/api/treatments/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.send([
{eventType: 'BG Check', glucose: 100, units: 'mg/dl', created_at: now}
, {eventType: 'BG Check', glucose: 100, units: 'mg/dl', created_at: now}
@@ -192,7 +194,7 @@ describe('Treatment API', function ( ) {
var now = (new Date()).toISOString();
request(self.app)
.post('/api/treatments/')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.send({eventType: 'Meal Bolus', created_at: now, carbs: '99', insulin: '2.00', preBolus: '15', glucose: 100, glucoseType: 'Finger', units: 'mg/dl'})
.expect(200)
.end(function (err) {
@@ -204,7 +206,7 @@ describe('Treatment API', function ( ) {
request(self.app)
.get('/api/treatments/')
.query('find[carbs]=99')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.expect(200)
.expect(function (response) {
response.body[0].carbs.should.equal(99);
@@ -218,7 +220,7 @@ describe('Treatment API', function ( ) {
request(self.app)
.delete('/api/treatments/')
.query('find[carbs]=99')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.expect(200)
.end(function (err) {
if (err) {
@@ -229,7 +231,7 @@ describe('Treatment API', function ( ) {
request(self.app)
.get('/api/treatments/')
.query('find[carbs]=99')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', api_secret_hash || '')
.expect(200)
.expect(function (response) {
response.body.length.should.equal(0);
+1 -1
View File
@@ -14,7 +14,7 @@ describe('authed REST api', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
var env = require('../lib/server/env')( );
env.settings.authDefaultRoles = 'readable';
this.wares = require('../lib/middleware/')(env);
this.archive = null;
+5 -3
View File
@@ -9,11 +9,13 @@ describe('Verifyauth REST api', function ( ) {
var self = this;
this.timeout(10000);
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
var api = require('../lib/api/');
before(function (done) {
self.env = require('../env')( );
self.env.api_secret = 'this is my long pass phrase';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
self.env = require('../lib/server/env')( );
self.env.settings.authDefaultRoles = 'denied';
this.wares = require('../lib/middleware/')(self.env);
self.app = require('express')( );
@@ -37,7 +39,7 @@ describe('Verifyauth REST api', function ( ) {
it('/verifyauth should return OK', function (done) {
request(self.app)
.get('/api/verifyauth')
.set('api-secret', self.env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.end(function(err, res) {
res.body.message.message.should.equal('OK');
+2 -2
View File
@@ -20,7 +20,7 @@ describe('ar2', function ( ) {
var ar2 = require('../lib/plugins/ar2')(ctx);
var bgnow = require('../lib/plugins/bgnow')(ctx);
var env = require('../env')();
var env = require('../lib/server/env')();
var now = Date.now();
var before = now - FIVE_MINS;
@@ -42,7 +42,7 @@ describe('ar2', function ( ) {
it('should plot a line if coneFactor is 0', function () {
ctx.ddata.sgvs = [{mgdl: 100, mills: before}, {mgdl: 105, mills: now}];
var env0 = require('../env')();
var env0 = require('../lib/server/env')();
env0.extendedSettings = { ar2: { coneFactor: 0 } };
var sbx = require('../lib/sandbox')().serverInit(env0, ctx).withExtendedSettings(ar2);
bgnow.setProperties(sbx);
+1 -1
View File
@@ -5,7 +5,7 @@ const language = require('../lib/language')(fs);
describe('basalprofile', function ( ) {
var sandbox = require('../lib/sandbox')();
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {
settings: {}
, language: language
+1 -1
View File
@@ -3,7 +3,7 @@ var Stream = require('stream');
var levels = require('../lib/levels');
describe('boluswizardpreview', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
env.testMode = true;
var ctx = {
+1 -1
View File
@@ -4,7 +4,7 @@ require('should');
var levels = require('../lib/levels');
describe('cage', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.ddata = require('../lib/data/ddata')();
ctx.notifications = require('../lib/notifications')(env, ctx);
+8 -2
View File
@@ -10,6 +10,10 @@ var nowData = {
, treatments: []
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
describe('careportal', function ( ) {
this.timeout(60000); // TODO: see why this test takes longer on Travis to complete
@@ -34,7 +38,7 @@ describe('careportal', function ( ) {
done( );
});
it ('open careportal, and enter a treatment', function (done) {
it ('open careportal, and enter a treatment', async () =>{
console.log('Careportal test client start');
@@ -49,8 +53,11 @@ describe('careportal', function ( ) {
console.log('Careportal test client init');
client.init();
sleep(50);
console.log('Careportal test client data update');
client.dataUpdate(nowData, true);
sleep(50);
client.careportal.prepareEvents();
@@ -89,7 +96,6 @@ describe('careportal', function ( ) {
client.careportal.save();
done();
});
});
+1 -1
View File
@@ -15,7 +15,7 @@ describe('Database Size', function() {
var dataWarn = { dbstats: { dataSize: 1024 * 1024 * 250, indexSize: 1024 * 1024 * 100, fileSize: 1024 * 1024 * 360 } };
var dataUrgent = { dbstats: { dataSize: 1024 * 1024 * 300, indexSize: 1024 * 1024 * 150, fileSize: 1024 * 1024 * 496 } };
var env = require('../env')();
var env = require('../lib/server/env')();
it('display database size in range', function(done) {
var sandbox = require('../lib/sandbox')();
+1 -1
View File
@@ -6,7 +6,7 @@ var should = require('should');
describe('ddata', function ( ) {
// var sandbox = require('../lib/sandbox')();
// var env = require('../env')();
// var env = require('../lib/server/env')();
var ctx = {};
ctx.ddata = require('../lib/data/ddata')();
+18 -18
View File
@@ -7,7 +7,7 @@ describe('env', function () {
process.env.SHOW_PLUGINS = 'iob';
process.env.ENABLE = 'iob cob';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
var showPlugins = env.settings.showPlugins;
showPlugins.should.containEql( 'iob' );
showPlugins.should.containEql( 'delta' );
@@ -22,7 +22,7 @@ describe('env', function () {
process.env.ENABLE = 'scaryplugin';
process.env.SCARYPLUGIN_DO_THING = 'yes';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.isEnabled( 'scaryplugin' ).should.equal( true );
//Note the camelCase
@@ -35,7 +35,7 @@ describe('env', function () {
it( 'add pushover to enable if one of the env vars is set', function () {
process.env.PUSHOVER_API_TOKEN = 'abc12345';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.enable.should.containEql( 'pushover' );
env.extendedSettings.pushover.apiToken.should.equal( 'abc12345' );
@@ -45,7 +45,7 @@ describe('env', function () {
it( 'add pushover to enable if one of the weird azure env vars is set', function () {
process.env.CUSTOMCONNSTR_PUSHOVER_API_TOKEN = 'abc12345';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.enable.should.containEql( 'pushover' );
env.extendedSettings.pushover.apiToken.should.equal( 'abc12345' );
@@ -54,17 +54,17 @@ describe('env', function () {
it( 'readENVTruthy ', function () {
process.env.INSECURE_USE_HTTP = 'true';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.insecureUseHttp.should.be.true();
process.env.INSECURE_USE_HTTP = 'false';
env = require( '../env' )();
env = require( '../lib/server/env' )();
env.insecureUseHttp.should.be.false();
process.env.INSECURE_USE_HTTP = 'not set ok, so use default value false';
env = require( '../env' )();
env = require( '../lib/server/env' )();
env.insecureUseHttp.should.be.false();
delete process.env.INSECURE_USE_HTTP; // unset INSECURE_USE_HTTP
process.env.SECURE_HSTS_HEADER = 'true';
env = require( '../env' )();
env = require( '../lib/server/env' )();
env.insecureUseHttp.should.be.false(); // not defined should be false
env.secureHstsHeader.should.be.true();
});
@@ -75,28 +75,28 @@ describe('env', function () {
describe ( 'mmol', function () {
it( 'mmol => mmol', function () {
process.env.DISPLAY_UNITS = MMOL;
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MMOL );
delete process.env.DISPLAY_UNITS;
} );
it( 'mmol/l => mmol', function () {
process.env.DISPLAY_UNITS = 'mmol/l';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MMOL );
delete process.env.DISPLAY_UNITS;
} );
it( 'mmol/L => mmol', function () {
process.env.DISPLAY_UNITS = 'mmol/L';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MMOL );
delete process.env.DISPLAY_UNITS;
} );
it( 'MMOL => mmol', function () {
process.env.DISPLAY_UNITS = 'MMOL';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MMOL );
delete process.env.DISPLAY_UNITS;
} );
@@ -105,28 +105,28 @@ describe('env', function () {
describe ( 'mg/dl', function () {
it( 'mg/dl => mg/dl', function () {
process.env.DISPLAY_UNITS = MGDL;
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
it( 'mg/dL => mg/dl', function () {
process.env.DISPLAY_UNITS = 'mg/dL';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
it( 'MG/DL => mg/dl', function () {
process.env.DISPLAY_UNITS = 'MG/DL';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
it( 'mgdl => mg/dl', function () {
process.env.DISPLAY_UNITS = 'mgdl';
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
@@ -139,14 +139,14 @@ describe('env', function () {
random = [...Array(~~(Math.random()*20)+1)].map(i=>(~~(Math.random()*36)).toString(36)).join('');
process.env.DISPLAY_UNITS = random;
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
it( '<null> => mg/dl', function () {
delete process.env.DISPLAY_UNITS;
var env = require( '../env' )();
var env = require( '../lib/server/env' )();
env.settings.units.should.equal( MGDL );
delete process.env.DISPLAY_UNITS;
} );
+1 -1
View File
@@ -5,7 +5,7 @@ var levels = require('../lib/levels');
describe('errorcodes', function ( ) {
var now = Date.now();
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.ddata = require('../lib/data/ddata')();
ctx.notifications = require('../lib/notifications')(env, ctx);
+1 -1
View File
@@ -22,7 +22,7 @@ function configure () {
process.env.API_SECRET = apiSecret;
process.env.HOSTNAME = 'localhost';
const env = require('../../../env')();
const env = require('../../../lib/server/env')();
if (useHttps) {
env.ssl = {
+1 -1
View File
@@ -25,7 +25,7 @@ function configure () {
process.env.API_SECRET = apiSecret;
process.env.HOSTNAME = 'localhost';
const env = require('../../../env')();
const env = require('../../../lib/server/env')();
if (useHttps) {
env.ssl = {
+3 -2
View File
@@ -10,6 +10,7 @@ function headless (benv, binding) {
function init (opts, callback) {
var localStorage = opts.localStorage || './localstorage';
const t = Date.now();
console.log('Headless init');
@@ -24,13 +25,13 @@ function headless (benv, binding) {
console.log('Setting up benv', Date.now() - t);
benv.require(__dirname + '/../../tmp/js/bundle.report.js');
benv.require(__dirname + '/../../tmp/public/js/bundle.app.js');
console.log('Bundle loaded', Date.now() - t);
self.$ = $;
self.localCookieStorage = self.localStorage = self.$.localStorage = require('./localstorage');
self.localCookieStorage = self.localStorage = self.$.localStorage = require(localStorage);
self.$.fn.tooltip = function mockTooltip ( ) { };
+1 -1
View File
@@ -4,7 +4,7 @@ require('should');
var levels = require('../lib/levels');
describe('insulinage', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.levels = levels;
ctx.ddata = require('../lib/data/ddata')();
+1 -1
View File
@@ -13,7 +13,7 @@ var ctx_top = {
, levels: levels
};
ctx_top.language.set('en');
var env = require('../env')();
var env = require('../lib/server/env')();
var loop = require('../lib/plugins/loop')(ctx_top);
var sandbox = require('../lib/sandbox')(ctx_top);
+1 -1
View File
@@ -4,7 +4,7 @@ var should = require('should');
var assert = require('assert');
describe('mongo storage', function () {
var env = require('../env')();
var env = require('../lib/server/env')();
before(function (done) {
delete env.api_secret;
+3 -3
View File
@@ -16,8 +16,8 @@ describe('Notifications API', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
env.testMode = true;
var ctx = {
@@ -68,7 +68,7 @@ describe('Notifications API', function ( ) {
function makeRequest () {
request(app)
.get('/notifications/ack?level=1')
.set('api-secret', env.api_secret || '')
.set('api-secret', known || '')
.expect(200)
.end(function (err) {
should.not.exist(err);
+1 -1
View File
@@ -4,7 +4,7 @@ var should = require('should');
describe('openaps storage', function () {
var env = require('../env')();
var env = require('../lib/server/env')();
before(function (done) {
+1 -1
View File
@@ -14,7 +14,7 @@ var top_ctx = {
top_ctx.language.set('en');
var levels = require('../lib/levels');
top_ctx.levels = levels;
var env = require('../env')();
var env = require('../lib/server/env')();
var openaps = require('../lib/plugins/openaps')(top_ctx);
var sandbox = require('../lib/sandbox')(top_ctx);
+6 -2
View File
@@ -91,7 +91,9 @@ describe('Pebble Endpoint', function ( ) {
var pebble = require('../lib/server/pebble');
before(function (done) {
var env = require('../env')( );
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../lib/server/env')( );
env.settings.authDefaultRoles = 'readable';
this.app = require('express')( );
this.app.enable('api');
@@ -226,7 +228,9 @@ describe('Pebble Endpoint', function ( ) {
describe('Pebble Endpoint with Raw and IOB and COB', function ( ) {
var pebbleRaw = require('../lib/server/pebble');
before(function (done) {
var env = require('../env')( );
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../lib/server/env')( );
env.settings.enable = ['rawbg', 'iob', 'cob'];
env.settings.authDefaultRoles = 'readable';
this.appRaw = require('express')( );
+1 -1
View File
@@ -11,7 +11,7 @@ var top_ctx = {
, settings: require('../lib/settings')()
};
top_ctx.language.set('en');
var env = require('../env')();
var env = require('../lib/server/env')();
var levels = require('../lib/levels');
var profile = require('../lib/profilefunctions')();
top_ctx.levels = levels;
+3 -3
View File
@@ -6,7 +6,7 @@ var levels = require('../lib/levels');
describe('pushnotify', function ( ) {
it('send a pushover alarm, but only 1 time', function (done) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.levels = levels;
@@ -40,7 +40,7 @@ describe('pushnotify', function ( ) {
});
it('send a pushover notification, but only 1 time', function (done) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.levels = levels;
ctx.notifications = require('../lib/notifications')(env, ctx);
@@ -72,7 +72,7 @@ describe('pushnotify', function ( ) {
});
it('send a pushover alarm, and then cancel', function (done) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.levels = levels;
+1 -1
View File
@@ -33,7 +33,7 @@ describe('sandbox', function ( ) {
});
function createServerSandbox() {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.ddata = require('../lib/data/ddata')();
ctx.notifications = require('../lib/notifications')(env, ctx);
+9 -15
View File
@@ -21,15 +21,15 @@ describe('API_SECRET', function ( ) {
it('should fail when unauthorized', function (done) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
setup_app(env, function (ctx) {
// console.log(this.app.enabled('api'));
ctx.app.enabled('api').should.equal(true);
// ping_status(ctx.app, done);
// ping_authorized_endpoint(ctx.app, 200, done);
ping_status(ctx.app, again);
function again ( ) {
ctx.app.api_secret = '';
@@ -44,16 +44,13 @@ describe('API_SECRET', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
setup_app(env, function (ctx) {
// console.log(this.app.enabled('api'));
ctx.app.enabled('api').should.equal(true);
// ping_status(ctx.app, done);
// ping_authorized_endpoint(ctx.app, 200, done);
ping_status(ctx.app, again);
function again ( ) {
ctx.app.api_secret = env.api_secret;
ctx.app.api_secret = known;
ping_authorized_endpoint(ctx.app, 200, done);
}
});
@@ -63,7 +60,7 @@ describe('API_SECRET', function ( ) {
it('should not work short', function ( ) {
delete process.env.API_SECRET;
process.env.API_SECRET = 'tooshort';
var env = require('../env')( );
var env = require('../lib/server/env')( );
should.not.exist(env.api_secret);
env.err[0].desc.should.startWith('API_SECRET should be at least');
});
@@ -73,10 +70,8 @@ describe('API_SECRET', function ( ) {
.get('/status.json')
.expect(200)
.end(function (err, res) {
// console.log(res.body);
res.body.status.should.equal('ok');
fn( );
// console.log('err', err, 'res', res);
});
}
@@ -90,7 +85,6 @@ describe('API_SECRET', function ( ) {
res.body.status.should.equal('ok');
}
fn( );
// console.log('err', err, 'res', res);
});
}
+1 -1
View File
@@ -5,7 +5,7 @@ var times = require('../lib/times');
var levels = require('../lib/levels');
describe('sage', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.levels = levels;
ctx.ddata = require('../lib/data/ddata')();
+1 -1
View File
@@ -2,7 +2,7 @@ var should = require('should');
var levels = require('../lib/levels');
describe('simplealarms', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {
settings: {}
, language: require('../lib/language')()
+1 -1
View File
@@ -13,7 +13,7 @@ describe('timeago', function() {
var timeago = require('../lib/plugins/timeago')(ctx);
var env = require('../env')();
var env = require('../lib/server/env')();
function freshSBX () {
//set extendedSettings right before calling withExtendedSettings, there's some strange test interference here
+1 -1
View File
@@ -4,7 +4,7 @@ var levels = require('../lib/levels');
describe('treatmentnotify', function ( ) {
var env = require('../env')();
var env = require('../lib/server/env')();
var ctx = {};
ctx.ddata = require('../lib/data/ddata')();
ctx.notifications = require('../lib/notifications')(env, ctx);
+10 -8
View File
@@ -24,10 +24,12 @@ describe('verifyauth', function ( ) {
it('should return defaults when called without secret', function (done) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
var known512 = '8c8743d38cbe00debe4b3ba8d0ffbb85e4716c982a61bb9e57bab203178e3718b2965831c1a5e42b9da16f082fdf8a6cecf993b49ed67e3a8b1cd475885d8070';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
env.enclave.isApiKey(known512).should.equal(true);
setup_app(env, function (ctx) {
ctx.app.enabled('api').should.equal(true);
ctx.app.api_secret = '';
@@ -39,8 +41,8 @@ describe('verifyauth', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
setup_app(env, function (ctx) {
ctx.app.enabled('api').should.equal(true);
ctx.app.api_secret = 'wrong secret';
@@ -59,8 +61,8 @@ describe('verifyauth', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
setup_app(env, function (ctx) {
ctx.app.enabled('api').should.equal(true);
ctx.app.api_secret = 'wrong secret';
@@ -88,8 +90,8 @@ describe('verifyauth', function ( ) {
var known = 'b723e97aa97846eb92d5264f084b2823f57c4aa1';
delete process.env.API_SECRET;
process.env.API_SECRET = 'this is my long pass phrase';
var env = require('../env')( );
env.api_secret.should.equal(known);
var env = require('../lib/server/env')( );
env.enclave.isApiKey(known).should.equal(true);
setup_app(env, function (ctx) {
ctx.app.enabled('api').should.equal(true);
ctx.app.api_secret = env.api_secret;
+1 -1
View File
@@ -112,7 +112,7 @@
<%- include('partials/authentication-status') %>
<script src="<%= locals.bundle %>/js/bundle.report.js"></script>
<script src="<%= locals.bundle %>/js/bundle.app.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/js/foodinit.js"></script>
</body>
+1 -1
View File
@@ -23,7 +23,7 @@
<a id="drawerToggle" class="tip" original-title="Settings" aria-label="Settings" href="#"><i class="icon-menu"></i></a>
<a id="testAlarms" class="tip" original-title="Alarm Test / Smartphone Enable" aria-label="Alarm Test / Smartphone Enable" href="#"><i class="icon-volume"></i></a>
<a id="editbutton" class="tip" original-title="Edit Mode" aria-label="Edit Mode" href="#" style="display:none;"><i class="icon-edit"></i></a>
<a id="adminnotifies" class="tip" original-title="Admin ntofications" aria-label="Admin notifications" href="#" style="display:none;"><i class="plugicon-notifies"></i></a>
<a id="adminnotifies" class="tip" original-title="Admin ntofications" aria-label="Admin notifications" href="#" style="display:none;"><i class="plugicon-notifies" style='color: #c91515'></i></a>
</div>
<% } %>
</div>
+1 -1
View File
@@ -166,7 +166,7 @@
<%- include('partials/authentication-status') %>
<script src="/api/v1/status.js"></script>
<script src="<%= locals.bundle %>/js/bundle.report.js"></script>
<script src="<%= locals.bundle %>/js/bundle.app.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/js/profileinit.js"></script>
</body>
+1 -1
View File
@@ -122,7 +122,7 @@
<%- include('partials/authentication-status') %>
<script src="<%= locals.bundle %>/js/bundle.report.js"></script>
<script src="<%= locals.bundle %>/js/bundle.app.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/report/js/flotcandle.js"></script>
<script src="/report/js/loopalyzer.js"></script>
-1
View File
@@ -29,7 +29,6 @@ const CACHE_LIST = [
'/css/main.css',
'/bundle/js/bundle.app.js',
'/bundle/js/bundle.clock.js',
'/bundle/js/bundle.report.js',
'/socket.io/socket.io.js',
'/js/client.js',
'/images/logo2.png'
+2 -5
View File
@@ -107,7 +107,6 @@ const rules = [
const appEntry = ['./bundle/bundle.source.js'];
const clockEntry = ['./bundle/bundle.clocks.source.js'];
const reportEntry = ['./bundle/bundle.reports.source.js'];
let mode = 'production';
let publicPath = '/bundle/';
@@ -122,7 +121,6 @@ if (process.env.NODE_ENV == 'development') {
appEntry.unshift(hot);
clockEntry.unshift(hot);
reportEntry.unshift(hot);
rules.unshift({
enforce: "pre",
@@ -162,11 +160,10 @@ module.exports = {
context: path.resolve(__dirname, '.'),
entry: {
app: appEntry,
clock: clockEntry,
report: reportEntry
clock: clockEntry
},
output: {
path: path.resolve(__dirname, './tmp'),
path: path.resolve(__dirname, './tmp/public'),
publicPath,
filename: 'js/bundle.[name].js',
sourceMapFilename: 'js/bundle.[name].js.map',