diff --git a/app-template/package-template.json b/app-template/package-template.json index 232ac7e1f..a0324afdf 100644 --- a/app-template/package-template.json +++ b/app-template/package-template.json @@ -81,6 +81,7 @@ "grunt-exec": "^1.0.0", "grunt-nw-builder": "^2.0.3", "grunt-sass": "^1.2.0", + "keytar": "git+https://github.com/spasma/node-keytar.git", "load-grunt-tasks": "^3.5.0", "shelljs": "^0.3.0", "android-versions": "^1.2.1", diff --git a/src/js/services/desktopSecureStorageService.js b/src/js/services/desktopSecureStorageService.js index 6e148da2c..beda1fcb5 100644 --- a/src/js/services/desktopSecureStorageService.js +++ b/src/js/services/desktopSecureStorageService.js @@ -1,6 +1,82 @@ 'use strict'; -angular.module('copayApp.services').factory('desktopSecureStorageService', function($log) { - // Placeholder - return {}; +angular.module('copayApp.services').factory('desktopSecureStorageService', function($log, appConfigService, platformInfo, lodash, localStorageService) { + var root = {}; + var storage = null; + var serviceName = appConfigService.packageNameId; + var initialisationFailed = false; + + if (platformInfo.isNW) { + try { + var os = require('os'); + var arch = (os.arch() === 'x64' || process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432')) ? 'x64':'ia32'; + var file = './keytar/keytar-prebuild-v4.1.1-node-v51-'+process.platform+'-'+arch+'.node'; + storage = require('keytar'); + storage.setKeytarInstance(require(file)); + } catch (e) { + console.log(e); + initialisationFailed = true; + } + } + + root.get = function(key, cb) { + if (!platformInfo.isNW) { + cb(new Error('desktopSecureStorageService is only available on NW.js desktop.')); + return; + } + + if (initialisationFailed) + return localStorageService.get(key, cb); + + storage.getPassword(serviceName, key).then(function(result) { + return cb(null, result); // XX SP: result is null if no value is found as it should + }).catch(function (error) { + cb(new Error(error)); + }); + }; + + root.remove = function(key, cb) { + if (!platformInfo.isNW) { + cb(new Error('desktopSecureStorageService is only available on NW.js desktop.')); + return; + } + + if (initialisationFailed) + return localStorageService.remove(key, cb); + + storage.removePassword(serviceName, key).then(function (value) { + cb(); + }).catch(function (error) { + console.log(error); + cb(new Error(error)); + }) + }; + + root.set = function(key, value, cb) { + if (!platformInfo.isNW) { + cb(new Error('desktopSecureStorageService is only available on NW.js desktop.')); + return; + } + + if (initialisationFailed) + return localStorageService.set(key, value, cb); + + if (lodash.isObject(value)) { + value = JSON.stringify(value); + } + if (value && !lodash.isString(value)) { + value = value.toString(); + } + + storage.deletePassword(serviceName, key).then(function (result) { + storage.setPassword(serviceName, key, value).then(function (value) { + cb(); + }).catch(function (error) { + console.log(error); + cb(new Error(error)); + }) + }); + }; + + return root; }); \ No newline at end of file diff --git a/src/js/services/platformInfo.js b/src/js/services/platformInfo.js index 8396afa07..65932eb3c 100644 --- a/src/js/services/platformInfo.js +++ b/src/js/services/platformInfo.js @@ -66,5 +66,11 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { ret.versionIntelTEE = getVersionIntelTee(); ret.supportsIntelTEE = ret.versionIntelTEE.length > 0; + ret.isMac = typeof process !== 'undefined'?process.platform === 'darwin':false; + ret.isWindows = typeof process !== 'undefined'?process.platform === 'win32':false; + ret.isLinux = typeof process !== 'undefined'?process.platform === 'linux':false; + + ret.isDesktopApp = ret.isNW && (ret.isMac || ret.isWindows || ret.isLinux); + return ret; }); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index 25f2a6852..806a9a777 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -528,7 +528,7 @@ angular.module('copayApp.services') var walletId = client.credentials.walletId - if (!root.profile.addWallet(JSON.parse(client.export()))) + if (root.profile && !root.profile.addWallet(JSON.parse(client.export()))) return cb(gettextCatalog.getString("Wallet already in {{appName}}", { appName: appConfigService.nameCase })); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index a2d85950b..8f1317f5d 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -121,7 +121,7 @@ angular.module('copayApp.services') root.storeProfile = function(profile, cb) { var profileString = profile.toObj(); - if (platformInfo.isNW) { + if (platformInfo.isNW && !platformInfo.isMac) { storage.set('profile', profileString, cb); } else { secureStorageService.set('profile', profileString, cb); @@ -205,7 +205,7 @@ angular.module('copayApp.services') * @param {getProfileCallback} cb */ root.getProfile = function(cb) { - if (platformInfo.isNW) { + if (platformInfo.isNW && !platformInfo.isMac) { storage.get('profile', function(getErr, getStr) { _onOldProfileRetrieved(getErr, getStr, cb); }); @@ -728,15 +728,15 @@ angular.module('copayApp.services') root.setReceivedTransactions = function(walletId, txIds, cb) { storage.set('receivedTxs-' + walletId, txIds, cb); - } + }; root.getReceivedTransactions = function(walletId, cb) { storage.get('receivedTxs-' + walletId, cb); - } + }; root.removeReceivedTransactions = function(walletId, cb) { storage.remove('receivedTxs-' + walletId, cb); - } + }; root.checkIfFlagIsSet = function(key) { return new Promise(function(resolve, reject) { @@ -748,7 +748,7 @@ angular.module('copayApp.services') } }); }); - } + }; return root; }); diff --git a/www/keytar/keytar-prebuild-v4.1.1-node-v51-darwin-x64.node b/www/keytar/keytar-prebuild-v4.1.1-node-v51-darwin-x64.node new file mode 100755 index 000000000..e7fb6e805 Binary files /dev/null and b/www/keytar/keytar-prebuild-v4.1.1-node-v51-darwin-x64.node differ diff --git a/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-ia32.node b/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-ia32.node new file mode 100755 index 000000000..ccb3ba290 Binary files /dev/null and b/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-ia32.node differ diff --git a/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-x64.node b/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-x64.node new file mode 100755 index 000000000..b32a25ff0 Binary files /dev/null and b/www/keytar/keytar-prebuild-v4.1.1-node-v51-linux-x64.node differ diff --git a/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-ia32.node b/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-ia32.node new file mode 100644 index 000000000..caf5d21d2 Binary files /dev/null and b/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-ia32.node differ diff --git a/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-x64.node b/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-x64.node new file mode 100644 index 000000000..93f008765 Binary files /dev/null and b/www/keytar/keytar-prebuild-v4.1.1-node-v51-win32-x64.node differ