Merge pull request #243 from samuelthomas2774/keytar

Add an option to store the master password in the system keychain
This commit is contained in:
Alexei Stukov 2018-08-23 22:30:57 +03:00 committed by GitHub
commit 3ba90705ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 334 additions and 87 deletions

View File

@ -6,3 +6,8 @@ node_js:
branches:
only:
- master
addons:
apt:
packages:
- libsecret-1-dev

View File

@ -12,7 +12,7 @@ import { Settings, Cache, Events } from 'modules';
import BuiltinModule from './BuiltinModule';
import { WebpackModules, ReactComponents, MonkeyPatch, Patcher, DiscordApi, Security } from 'modules';
import { VueInjector, Reflection, Modals, Toasts } from 'ui';
import { ClientLogger as Logger } from 'common';
import { ClientLogger as Logger, ClientIPC } from 'common';
import { request } from 'vendor';
import { Utils } from 'common';
import E2EEComponent from './E2EEComponent.vue';
@ -35,33 +35,59 @@ export default new class E2EE extends BuiltinModule {
this.encryptNewMessages = true;
this.ecdhDate = START_DATE;
this.handlePublicKey = this.handlePublicKey.bind(this);
this.fetchMasterKey = this.fetchMasterKey.bind(this);
}
async enabled(e) {
try {
const newMaster = await Modals.input('Open Database', 'Master Password', true).promise;
this.setMaster(newMaster);
Events.on('discord:MESSAGE_CREATE', this.handlePublicKey);
this.patchDispatcher();
this.patchMessageContent();
const selector = `.${WebpackModules.getClassName('channelTextArea', 'emojiButton')}`;
const cta = await ReactComponents.getComponent('ChannelTextArea', { selector });
this.patchChannelTextArea(cta);
this.patchChannelTextAreaSubmit(cta);
cta.forceUpdateAll();
} catch (err) {
Settings.getSetting(...this.settingPath).value = false;
Toasts.error('Invalid master password! E2EE Disabled');
}
await this.fetchMasterKey();
Settings.getSetting('security', 'default', 'use-keytar').on('setting-updated', this.fetchMasterKey);
Events.on('discord:MESSAGE_CREATE', this.handlePublicKey);
this.patchDispatcher();
this.patchMessageContent();
const selector = `.${WebpackModules.getClassName('channelTextArea', 'emojiButton')}`;
const cta = await ReactComponents.getComponent('ChannelTextArea', { selector });
this.patchChannelTextArea(cta);
this.patchChannelTextAreaSubmit(cta);
cta.forceUpdateAll();
}
async disabled(e) {
Settings.getSetting('security', 'default', 'use-keytar').off('setting-updated', this.fetchMasterKey);
Events.off('discord:MESSAGE_CREATE', this.handlePublicKey);
for (const patch of Patcher.getPatchesByCaller('BD:E2EE')) patch.unpatch();
const ctaComponent = await ReactComponents.getComponent('ChannelTextArea');
ctaComponent.forceUpdateAll();
}
async fetchMasterKey() {
try {
if (Settings.get('security', 'default', 'use-keytar')) {
const master = await ClientIPC.getPassword('betterdiscord', 'master');
if (master) return this.setMaster(master);
if (Settings.getSetting('security', 'e2eedb', 'e2ekvps').items.length) {
// Ask the user for their current password to save to the system keychain
const currentMaster = await Modals.input('Save to System Keychain', 'Master Password', true).promise;
await ClientIPC.setPassword('betterdiscord', 'master', currentMaster);
return this.setMaster(currentMaster);
}
// Generate a new master password and save it to the system keychain
const newMaster = Security.randomBytes();
await ClientIPC.setPassword('betterdiscord', 'master', newMaster);
return this.setMaster(newMaster);
}
const newMaster = await Modals.input('Open Database', 'Master Password', true).promise;
return this.setMaster(newMaster);
} catch (err) {
Settings.getSetting(...this.settingPath).value = false;
Toasts.error('Invalid master password! E2EE Disabled');
Logger.err('E2EE', ['Error fetching master password', err]);
}
}
setMaster(key) {
seed = Security.randomBytes();
const newMaster = Security.encrypt(seed, key);
@ -300,8 +326,11 @@ export default new class E2EE extends BuiltinModule {
component.props.readyState = 'LOADING';
Logger.info('E2EE', `Decrypting image: ${src}`);
request.get(src, { encoding: 'binary' }).then(res => {
(async () => {
(async () => {
try {
const res = await request.get(src, { encoding: 'binary' });
const arr = new Uint8Array(new ArrayBuffer(res.length));
for (let i = 0; i < res.length; i++) arr[i] = res.charCodeAt(i);
@ -330,10 +359,10 @@ export default new class E2EE extends BuiltinModule {
component.props.decrypting = false;
component.forceUpdate();
})();
}).catch(err => {
console.log('request error', err);
});
} catch (err) {
console.log('request error', err);
}
})();
}
patchChannelTextArea(cta) {
@ -355,4 +384,5 @@ export default new class E2EE extends BuiltinModule {
if (!this.encryptNewMessages || !key) return;
component.props.value = Security.encrypt(Security.decrypt(seed, [this.master, key]), component.props.value, '$:');
}
}

View File

@ -235,6 +235,13 @@
"text": "E2EE",
"hint": "End-to-end encryption",
"value": false
},
{
"id": "use-keytar",
"type": "bool",
"text": "Use system keychain",
"hint": "Store the master password in the system keychain",
"value": true
}
]
},

View File

@ -12,6 +12,7 @@ import { Toasts } from 'ui';
import { SettingsSet } from 'structs';
import { FileUtils, ClientLogger as Logger } from 'common';
import path from 'path';
import process from 'process';
import Globals from './globals';
import CssEditor from './csseditor';
import Events from './events';
@ -38,6 +39,12 @@ export default new class Settings {
return set;
});
// Set a hint for each platform for the use-keytar setting
const useKeytarSetting = this.getSetting('security', 'default', 'use-keytar');
if (process.platform === 'win32') useKeytarSetting.hint = 'Store the master password in Credential Manager';
if (process.platform === 'darwin') useKeytarSetting.hint = 'Store the master password in the default keychain';
if (process.platform === 'linux') useKeytarSetting.hint = 'Store the master password in libsecret';
}
/**

View File

@ -112,6 +112,22 @@ const ClientIPC = new class ClientIPC {
return this.send('dba', command);
}
getPassword(service, account) {
return this.send('keytar-get', {service, account});
}
setPassword(service, account, password) {
return this.send('keytar-set', {service, account, password});
}
deletePassword(service, account) {
return this.send('keytar-delete', {service, account});
}
findCredentials(service) {
return this.send('keytar-find-credentials', {service});
}
}
export default ClientIPC;

View File

@ -13,6 +13,7 @@ import sass from 'node-sass';
import { BrowserWindow, dialog, session } from 'electron';
import deepmerge from 'deepmerge';
import ContentSecurityPolicy from 'csp-parse';
import keytar from 'keytar';
import { FileUtils, BDIpc, Config, WindowUtils, CSSEditor, Database } from './modules';
@ -57,9 +58,10 @@ const globals = {
const CSP = {
'img-src': ['https://cdn.betterttv.net', 'https://cdn.frankerfacez.com'],
'script-src': [
'\'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4=\'', // React Devtools
'\'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU=\'', // Vue Devtools
'\'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE=\' \'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU=\''] // Vue Detector
`'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4='`, // React Devtools
`'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU='`, // Vue Devtools
`'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE=' 'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU='` // Vue Detector
]
};
class PatchedBrowserWindow extends BrowserWindow {
@ -136,6 +138,11 @@ class Comms {
});
BDIpc.on('bd-dba', (event, options) => this.bd.dbInstance.exec(options), true);
BDIpc.on('bd-keytar-get', (event, {service, account}) => keytar.getPassword(service, account), true);
BDIpc.on('bd-keytar-set', (event, {service, account, password}) => keytar.setPassword(service, account, password), true);
BDIpc.on('bd-keytar-delete', (event, {service, account}) => keytar.deletePassword(service, account), true);
BDIpc.on('bd-keytar-find-credentials', (event, {service}) => keytar.findCredentials(service), true);
}
async send(channel, message) {

View File

@ -70,18 +70,31 @@ gulp.task('css-editor', function () {
]);
});
gulp.task('dependencies', function () {
gulp.task('node-modules', function () {
return copydeps('.', 'release');
});
gulp.task('node-sass-bindings', function () {
gulp.task('node-sass-bindings', gulp.series(function () {
return del(['release/node_modules/node-sass/vendor']);
}, function () {
return pump([
gulp.src('other/node_sass_bindings/**/*'),
copy('release/node_modules/node-sass/vendor', { prefix: 2 })
]);
});
gulp.task('build-release', gulp.parallel('release-package', 'client', 'core', 'sparkplug', 'core-modules', 'index', 'css-editor', gulp.series('dependencies', 'node-sass-bindings')));
gulp.task('keytar-bindings', gulp.series(function () {
return del(['release/node_modules/keytar/build']);
}, function () {
return pump([
gulp.src('other/keytar/**/*'),
copy('release/node_modules/keytar/build/Release', {prefix: 2})
]);
}));
gulp.task('dependencies', gulp.series('node-modules', gulp.parallel('node-sass-bindings', 'keytar-bindings')));
gulp.task('build-release', gulp.parallel('release-package', 'client', 'core', 'sparkplug', 'core-modules', 'index', 'css-editor', 'dependencies'));
gulp.task('release', gulp.series(function () {
return del(['release/**/*']);

View File

@ -0,0 +1,3 @@
### node-keytar bindings
Copy this directory to `node_modules/keytar/build/Release/keytar.node` to use.

View File

@ -0,0 +1,4 @@
const keytar_version = require('keytar/package').version;
// module.exports = require('./keytar-' + process.platform + '-' + process.versions.modules + '-' + process.arch + '.node');
module.exports = require(`./keytar-${keytar_version}/${process.platform}-${process.arch}-${process.versions.modules}.node`);

Binary file not shown.

Binary file not shown.

229
package-lock.json generated
View File

@ -1563,7 +1563,6 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"dev": true,
"requires": {
"readable-stream": "2.3.5",
"safe-buffer": "5.1.1"
@ -1572,20 +1571,17 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"readable-stream": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
"integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
"dev": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@ -1600,7 +1596,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
@ -2012,8 +2007,7 @@
"chownr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
"dev": true
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
},
"cipher-base": {
"version": "1.0.4",
@ -2943,11 +2937,18 @@
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"dev": true
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"requires": {
"mimic-response": "1.0.1"
}
},
"deep-extend": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
"dev": true
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8="
},
"deep-is": {
"version": "0.1.3",
@ -3083,8 +3084,7 @@
"detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
"dev": true
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
},
"diff-match-patch": {
"version": "1.0.1",
@ -3323,6 +3323,28 @@
"sumchecker": "1.3.1"
},
"dependencies": {
"fs-extra": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"jsonfile": "2.4.0",
"klaw": "1.3.1",
"path-is-absolute": "1.0.1",
"rimraf": "2.6.2"
}
},
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11"
}
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
@ -3417,7 +3439,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "1.4.0"
}
@ -3984,6 +4005,11 @@
}
}
},
"expand-template": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
"integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg=="
},
"expand-tilde": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
@ -4431,16 +4457,13 @@
}
},
"fs-extra": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
"dev": true,
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz",
"integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==",
"requires": {
"graceful-fs": "4.1.11",
"jsonfile": "2.4.0",
"klaw": "1.3.1",
"path-is-absolute": "1.0.1",
"rimraf": "2.6.2"
"jsonfile": "4.0.0",
"universalify": "0.1.2"
}
},
"fs-mkdirp-stream": {
@ -4811,9 +4834,9 @@
"dev": true,
"optional": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.5",
"mime-types": "^2.1.12"
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.15"
}
},
"fs.realpath": {
@ -4916,8 +4939,8 @@
"dev": true,
"optional": true,
"requires": {
"ajv": "^4.9.1",
"har-schema": "^1.0.5"
"ajv": "4.11.8",
"har-schema": "1.0.5"
}
},
"has-unicode": {
@ -4986,7 +5009,7 @@
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
"number-is-nan": "1.0.1"
}
},
"is-typedarray": {
@ -5091,7 +5114,7 @@
"integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=",
"dev": true,
"requires": {
"mime-db": "~1.27.0"
"mime-db": "1.27.0"
}
},
"minimatch": {
@ -5100,7 +5123,7 @@
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
"brace-expansion": "1.1.7"
}
},
"minimist": {
@ -5219,8 +5242,8 @@
"dev": true,
"optional": true,
"requires": {
"os-homedir": "^1.0.0",
"os-tmpdir": "^1.0.0"
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
@ -5634,6 +5657,11 @@
"assert-plus": "1.0.0"
}
},
"github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -7155,8 +7183,7 @@
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=",
"dev": true
"integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc="
},
"inquirer": {
"version": "3.3.0",
@ -7727,10 +7754,9 @@
"dev": true
},
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "4.1.11"
}
@ -7763,6 +7789,15 @@
"integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=",
"dev": true
},
"keytar": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/keytar/-/keytar-4.2.1.tgz",
"integrity": "sha1-igamV3/fY3PgqmsRInfmPex3/RI=",
"requires": {
"nan": "2.8.0",
"prebuild-install": "2.5.3"
}
},
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
@ -8445,6 +8480,11 @@
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"dev": true
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@ -8643,9 +8683,7 @@
"nan": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
"dev": true,
"optional": true
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo="
},
"nanomatch": {
"version": "1.2.7",
@ -8724,7 +8762,6 @@
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz",
"integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==",
"dev": true,
"requires": {
"semver": "5.5.0"
}
@ -9025,6 +9062,11 @@
}
}
},
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@ -10501,6 +10543,44 @@
"uniqs": "2.0.0"
}
},
"prebuild-install": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz",
"integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==",
"requires": {
"detect-libc": "1.0.3",
"expand-template": "1.1.1",
"github-from-package": "0.0.0",
"minimist": "1.2.0",
"mkdirp": "0.5.1",
"node-abi": "2.4.3",
"noop-logger": "0.1.1",
"npmlog": "4.1.2",
"os-homedir": "1.0.2",
"pump": "2.0.1",
"rc": "1.2.6",
"simple-get": "2.8.1",
"tar-fs": "1.16.3",
"tunnel-agent": "0.6.0",
"which-pm-runs": "1.0.0"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"pump": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
"integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
"requires": {
"end-of-stream": "1.4.1",
"once": "1.4.0"
}
}
}
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@ -10754,7 +10834,6 @@
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz",
"integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=",
"dev": true,
"requires": {
"deep-extend": "0.4.2",
"ini": "1.3.5",
@ -10765,8 +10844,7 @@
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
@ -11877,6 +11955,21 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
},
"simple-get": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
"integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
"requires": {
"decompress-response": "3.3.0",
"once": "1.4.0",
"simple-concat": "1.0.0"
}
},
"single-line-log": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz",
@ -12574,8 +12667,7 @@
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"sumchecker": {
"version": "1.3.1",
@ -12721,11 +12813,32 @@
"inherits": "2.0.3"
}
},
"tar-fs": {
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
"integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
"requires": {
"chownr": "1.0.1",
"mkdirp": "0.5.1",
"pump": "1.0.3",
"tar-stream": "1.5.5"
},
"dependencies": {
"pump": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
"requires": {
"end-of-stream": "1.4.1",
"once": "1.4.0"
}
}
}
},
"tar-stream": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
"integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
"dev": true,
"requires": {
"bl": "1.2.2",
"end-of-stream": "1.4.1",
@ -12737,7 +12850,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "1.4.0"
}
@ -12745,20 +12857,17 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"readable-stream": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz",
"integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
"dev": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@ -12773,7 +12882,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
@ -12781,8 +12889,7 @@
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
"dev": true
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}
}
},
@ -13367,8 +13474,7 @@
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"unset-value": {
"version": "1.0.0",
@ -14413,6 +14519,11 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
},
"which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",

View File

@ -18,6 +18,8 @@
"dependencies": {
"csp-parse": "github:macropodhq/csp-parse",
"deepmerge": "^2.1.1",
"fs-extra": "^7.0.0",
"keytar": "4.2.1",
"nedb": "^1.8.0",
"node-sass": "^4.9.2"
},
@ -69,6 +71,7 @@
"webpack": "^3.12.0"
},
"scripts": {
"install": "node scripts/install.js",
"build": "npm run build --prefix client && npm run build --prefix core && npm run build --prefix csseditor && npm run build --prefix installer",
"build_client": "npm run build --prefix client",
"watch_client": "npm run watch --prefix client",

41
scripts/install.js Normal file
View File

@ -0,0 +1,41 @@
const process = require('process');
const fs = require('fs-extra');
const path = require('path');
// Copy the node-sass bindings to node_modules/node-sass/vendor
const node_sass_path = path.resolve(require.resolve('node-sass'), '..', '..');
const prebuilt_node_sass_bindings_path = path.resolve(__dirname, '..', 'other', 'node_sass_bindings');
for (const node_sass_binding_name of fs.readdirSync(prebuilt_node_sass_bindings_path)) {
const binding_path = path.join(prebuilt_node_sass_bindings_path, node_sass_binding_name);
const installation_path = path.join(node_sass_path, 'vendor', node_sass_binding_name);
if (fs.existsSync(installation_path)) continue;
console.log('Copying node-sass binding from', binding_path, 'to', installation_path);
fs.copySync(binding_path, installation_path);
}
// Copy the keytar bindings to node_modules/keytar/vendor
const keytar_path = path.resolve(require.resolve('keytar'), '..', '..');
const prebuilt_keytar_bindings_path = path.resolve(__dirname, '..', 'other', 'keytar', 'keytar.node');
const keytar_release_path = path.join(keytar_path, 'build', 'Release');
const keytar_binding_path = path.join(keytar_release_path, 'keytar.node');
if (fs.existsSync(path.join(keytar_release_path, 'keytar.node'))) {
const stat = fs.statSync(path.join(keytar_release_path, 'keytar.node'));
// if (stat.isFile()) {
console.log('Deleting keytar binding');
fs.removeSync(path.join(keytar_path, 'build'));
// }
}
if (!fs.existsSync(path.join(keytar_release_path, 'keytar.node'))) {
fs.mkdirpSync(keytar_release_path);
console.log('Copying keytar bindings from', prebuilt_keytar_bindings_path, 'to', keytar_binding_path);
fs.copySync(prebuilt_keytar_bindings_path, keytar_binding_path);
}