SymphonyElectron/js/config.js
Lynn 5d3377ec02 add unit test for isInDisplayBounds and config.js (#66)
* add unit test for util: isInDisplayBounds

* add tests for config.js
2017-04-26 09:46:15 -07:00

168 lines
5.9 KiB
JavaScript

'use strict';
const electron = require('electron');
const app = electron.app;
const path = require('path');
const fs = require('fs');
const isDevEnv = require('./utils/misc.js').isDevEnv;
const isMac = require('./utils/misc.js').isMac;
const getRegistry = require('./utils/getRegistry.js');
const configFileName = 'Symphony.config';
/**
* Tries to read given field from user config file, if field doesn't exist
* then tries reading from global config. User config is stord in directory:
* app.getPath('userData') and file called Symphony.config. Global config is
* stored in file Symphony.config in directory where executable gets installed.
*
* Config is a flat key/value file.
* e.g. { url: 'https://my.symphony.com', }
*
* @param {String} fieldName Name of field to try fetching
* @return {Promise} Returns promise that will succeed with field
* value if found in either user or global config. Otherwise will fail promise.
*/
function getConfigField(fieldName) {
return getUserConfigField(fieldName)
.then(function(value) {
// got value from user config
return value;
}, function () {
// failed to get value from user config, so try global config
return getGlobalConfigField(fieldName);
});
}
function getUserConfigField(fieldName) {
return readUserConfig().then(function(config) {
if (typeof fieldName === 'string' && fieldName in config) {
return config[fieldName];
}
throw new Error('field does not exist in user config: ' + fieldName);
});
}
function readUserConfig() {
return new Promise(function(resolve, reject) {
let configPath = path.join(app.getPath('userData'), configFileName);
fs.readFile(configPath, 'utf8', function(err, data) {
if (err) {
reject('cannot open user config file: ' + configPath + ', error: ' + err);
} else {
let config = {};
try {
// data is the contents of the text file we just read
config = JSON.parse(data);
} catch (e) {
reject('can not parse user config file data: ' + data + ', error: ' + err);
}
resolve(config);
}
});
});
}
function getGlobalConfigField(fieldName) {
return readGlobalConfig().then(function(config) {
if (typeof fieldName === 'string' && fieldName in config) {
return config[fieldName];
}
throw new Error('field does not exist in global config: ' + fieldName);
});
}
/**
* reads global configuration file: config/Symphony.config. this file is
* hold items (such as the start url) that are intended to be used as
* global (or default) values for all users running this app. for production
* this file is located relative to the executable - it is placed there by
* the installer. this makes the file easily modifable by admin (or person who
* installed app). for dev env, the file is read directly from packed asar file.
*/
function readGlobalConfig() {
return new Promise(function(resolve, reject) {
let configPath;
let globalConfigFileName = path.join('config', configFileName);
if (isDevEnv) {
// for dev env, get config file from asar
configPath = path.join(app.getAppPath(), globalConfigFileName);
} else {
// for non-dev, config file is placed by installer relative to exe.
// this is so the config can be easily be changed post install.
let execPath = path.dirname(app.getPath('exe'));
// for mac exec is stored in subdir, for linux/windows config
// dir is in the same location.
configPath = path.join(execPath, isMac ? '..' : '', globalConfigFileName);
}
fs.readFile(configPath, 'utf8', function(err, data) {
if (err) {
reject('cannot open global config file: ' + configPath + ', error: ' + err);
} else {
let config = {};
try {
// data is the contents of the text file we just read
config = JSON.parse(data);
} catch (e) {
reject('can not parse config file data: ' + data + ', error: ' + err);
}
getRegistry('PodUrl')
.then(function(url){
config.url = url;
resolve(config);
}).catch(function (){
resolve(config);
});
}
});
});
}
/**
* Updates user config with given field with new value
* @param {String} fieldName [description]
* @param {Object} newValue object to replace given value
* @return {[type]} [description]
*/
function updateConfigField(fieldName, newValue) {
return readUserConfig()
.then(function(config) {
return saveUserConfig(fieldName, newValue, config);
},
function() {
// in case config doesn't exist, can't read or is corrupted.
return saveUserConfig(fieldName, newValue, {});
});
}
function saveUserConfig(fieldName, newValue, oldConfig) {
return new Promise(function(resolve, reject) {
let configPath = path.join(app.getPath('userData'), configFileName);
if (!oldConfig || !fieldName) {
reject('can not save config, invalid input');
return;
}
// clone and set new value
let newConfig = Object.assign({}, oldConfig);
newConfig[fieldName] = newValue;
let jsonNewConfig = JSON.stringify(newConfig, null, ' ');
fs.writeFile(configPath, jsonNewConfig, 'utf8', (err) => {
if (err) {
reject(err);
} else {
resolve(newConfig);
}
});
});
}
module.exports = { getConfigField, updateConfigField, configFileName };