diff --git a/src/models/domainModels.js b/src/models/domainModels.js index 8395e016..ede82871 100644 --- a/src/models/domainModels.js +++ b/src/models/domainModels.js @@ -42,32 +42,22 @@ var Folder = function (obj, alreadyEncrypted) { !function () { CipherString.prototype.decrypt = function (callback) { + var deferred = Q.defer(); + if (!this.decryptedValue) { var cryptoService = chrome.extension.getBackgroundPage().cryptoService; - cryptoService.decrypt(this, function (decValue) { + cryptoService.decrypt(this).then(function (decValue) { this.decryptedValue = decValue; - callback(this.decryptedValue); + deferred.resolve(this.decryptedValue); }); } else { callback(this.decryptedValue); - } - }; - - CipherString.prototype.decryptWithPromise = function () { - var deferred = Q.defer(); - - if (!this) { - deferred.resolve(null); - } - else { - this.decrypt(function (decVal) { - deferred.resolve(decVal); - }); + deferred.resolve(this.decryptedValue); } return deferred.promise; - } + }; Site.prototype.decrypt = function () { var self = this; @@ -79,29 +69,29 @@ var Folder = function (obj, alreadyEncrypted) { var deferred = Q.defer(); - self.name.decryptWithPromise().then(function (val) { + self.name.decrypt().then(function (val) { model.name = val; if (self.uri) { - return self.uri.decryptWithPromise(); + return self.uri.decrypt(); } return null; }).then(function (val) { model.uri = val; model.domain = tldjs.getDomain(val); if (self.username) { - return self.username.decryptWithPromise(); + return self.username.decrypt(); } return null; }).then(function (val) { model.username = val; if (self.password) { - return self.password.decryptWithPromise(); + return self.password.decrypt(); } return null; }).then(function (val) { model.password = val; if (self.notes) { - return self.notes.decryptWithPromise(); + return self.notes.decrypt(); } return null; }).then(function (val) { @@ -120,7 +110,7 @@ var Folder = function (obj, alreadyEncrypted) { var deferred = Q.defer(); - self.name.decryptWithPromise().then(function (val) { + self.name.decrypt().then(function (val) { model.name = val; deferred.resolve(model); }); diff --git a/src/popup/app/current/currentController.js b/src/popup/app/current/currentController.js index 701709c5..3194257b 100644 --- a/src/popup/app/current/currentController.js +++ b/src/popup/app/current/currentController.js @@ -1,7 +1,7 @@ angular .module('bit.current') - .controller('currentController', function ($scope, siteService, cipherService, tldjs, toastr, $q, $window, $state) { + .controller('currentController', function ($scope, siteService, tldjs, toastr, $q, $window, $state) { var pageDetails = null, tabId = null, url = null, diff --git a/src/popup/app/services/cipherService.js b/src/popup/app/services/cipherService.js deleted file mode 100644 index 91847319..00000000 --- a/src/popup/app/services/cipherService.js +++ /dev/null @@ -1,37 +0,0 @@ -angular - .module('bit.services') - - .factory('cipherService', function ($q, siteService) { - var _service = {}; - - _service.encryptSite = function (site) { - return $q.when(siteService.encrypt(site)); - }; - - _service.decryptSite = function (site) { - return $q.when(site.decrypt()); - }; - - _service.decrypt = decrypt; - - function decrypt(cipherString, index) { - return $q(function (resolve, reject) { - if (!cipherString) { - resolve({ - val: null, - index: index - }); - } - else { - cipherString.decrypt(function (decVal) { - resolve({ - val: decVal, - index: index - }); - }); - } - }); - } - - return _service; - }); diff --git a/src/popup/app/vault/vaultAddSiteController.js b/src/popup/app/vault/vaultAddSiteController.js index 49d0c0e5..524a1ba5 100644 --- a/src/popup/app/vault/vaultAddSiteController.js +++ b/src/popup/app/vault/vaultAddSiteController.js @@ -1,7 +1,7 @@ angular .module('bit.vault') - .controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService, cipherService, $q) { + .controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService, cryptoService, $q, toastr) { var returnScrollY = $stateParams.returnScrollY; var returnSearchText = $stateParams.returnSearchText; var fromCurrent = $stateParams.uri !== null; @@ -20,35 +20,18 @@ } popupUtils.initListSectionItemListeners(); - var promises = []; - var decFolders = [{ - id: null, - name: '(none)' - }]; - - folderService.getAll(function (folders) { - for (var i = 1; i < folders.length; i++) { - decFolders.push({ - id: folders[i].id - }); - - var folderNamePromise = cipherService.decrypt(folders[i].name, i); - promises.push(folderNamePromise); - folderNamePromise.then(function (obj) { - decFolders[obj.index].name = obj.val; - }); - } - - $q.all(promises).then(function () { - $scope.folders = decFolders; - }); + $q.when(folderService.getAllDecrypted()).then(function (folders) { + $scope.folders = folders.concat([{ + id: null, + name: '(none)' + }]); }); $scope.savePromise = null; $scope.save = function (model) { - $scope.savePromise = cipherService.encryptSite(model).then(function (siteModel) { + $scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { var site = new Site(siteModel, true); - return saveSite(site).then(function (site) { + return $q.when(siteService.saveWithServer(site)).then(function (site) { toastr.success('Added site'); $scope.close(); }); @@ -69,14 +52,4 @@ }); } }; - - function saveSite(site) { - return $q(function (resolve, reject) { - siteService.saveWithServer(site, function (site) { - resolve(site); - }, function (error) { - reject(error); - }); - }); - } }); diff --git a/src/popup/app/vault/vaultController.js b/src/popup/app/vault/vaultController.js index 0e34f6d1..70d910ce 100644 --- a/src/popup/app/vault/vaultController.js +++ b/src/popup/app/vault/vaultController.js @@ -1,7 +1,7 @@ angular .module('bit.vault') - .controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, cipherService, $state, $stateParams, toastr) { + .controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, $state, $stateParams, toastr) { $('#search').focus(); var delayLoad = true; diff --git a/src/popup/app/vault/vaultEditSiteController.js b/src/popup/app/vault/vaultEditSiteController.js index 77f7221a..2009b7c7 100644 --- a/src/popup/app/vault/vaultEditSiteController.js +++ b/src/popup/app/vault/vaultEditSiteController.js @@ -1,7 +1,7 @@ angular .module('bit.vault') - .controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, cipherService, $q, toastr) { + .controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, cryptoService, $q, toastr) { var returnScrollY = $stateParams.returnScrollY; var returnSearchText = $stateParams.returnSearchText; @@ -10,42 +10,25 @@ angular }; siteService.get($stateParams.siteId, function (site) { - cipherService.decryptSite(site).then(function (model) { + $q.when(site.decrypt()).then(function (model) { $scope.site = model; }); }); - var promises = []; - var decFolders = [{ - id: null, - name: '(none)' - }]; - - folderService.getAll(function (folders) { - for (var i = 1; i < folders.length; i++) { - decFolders.push({ - id: folders[i].id - }); - - var folderNamePromise = cipherService.decrypt(folders[i].name, i); - promises.push(folderNamePromise); - folderNamePromise.then(function (obj) { - decFolders[obj.index].name = obj.val; - }); - } - - $q.all(promises).then(function () { - $scope.folders = decFolders; - }); + $q.when(folderService.getAllDecrypted()).then(function (folders) { + $scope.folders = folders.concat([{ + id: null, + name: '(none)' + }]); }); popupUtils.initListSectionItemListeners(); $scope.savePromise = null; $scope.save = function (model) { - $scope.savePromise = cipherService.encryptSite(model).then(function (siteModel) { + $scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { var site = new Site(siteModel, true); - return saveSite(site).then(function (site) { + return $q.when(siteService.saveWithServer(site)).then(function (site) { toastr.success('Edited site'); $scope.close(); }); @@ -69,14 +52,4 @@ angular }); } }; - - function saveSite(site) { - return $q(function (resolve, reject) { - siteService.saveWithServer(site, function (site) { - resolve(site); - }, function (error) { - reject(error); - }); - }); - } }); diff --git a/src/popup/app/vault/vaultViewSiteController.js b/src/popup/app/vault/vaultViewSiteController.js index b0e0ec6e..68bf97d3 100644 --- a/src/popup/app/vault/vaultViewSiteController.js +++ b/src/popup/app/vault/vaultViewSiteController.js @@ -1,13 +1,13 @@ angular .module('bit.vault') - .controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, cipherService, tldjs, toastr) { + .controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, tldjs, toastr, $q) { var returnScrollY = $stateParams.returnScrollY; var returnSearchText = $stateParams.returnSearchText; $scope.site = null; siteService.get($stateParams.siteId, function (site) { - cipherService.decryptSite(site).then(function (model) { + $q.when(site.decrypt()).then(function (model) { $scope.site = model; if (model.password) { diff --git a/src/popup/index.html b/src/popup/index.html index 3d2db294..9d893fe0 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -39,7 +39,6 @@ - diff --git a/src/services/cryptoService.js b/src/services/cryptoService.js index 5cfeb8a0..aa4163b9 100644 --- a/src/services/cryptoService.js +++ b/src/services/cryptoService.js @@ -98,41 +98,39 @@ function initCryptoService() { }); }; - CryptoService.prototype.encrypt = function (plaintextValue, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } + CryptoService.prototype.encrypt = function (plaintextValue) { + var deferred = Q.defer(); if (plaintextValue === null || plaintextValue === undefined) { - callback(null); - return; + deferred.resolve(null); + } + else { + this.getKey(false, function (key) { + if (!key) { + throw 'Encryption key unavailable.'; + } + + var response = {}; + var params = { + mode: "cbc", + iv: sjcl.random.randomWords(4, 0) + }; + + var ctJson = sjcl.encrypt(key, plaintextValue, params, response); + + var ct = ctJson.match(/"ct":"([^"]*)"/)[1]; + var iv = sjcl.codec.base64.fromBits(response.iv); + + var cs = new CipherString(iv + "|" + ct); + deferred.resolve(cs); + }); } - this.getKey(false, function (key) { - if (!key) { - throw 'Encryption key unavailable.'; - } - - var response = {}; - var params = { - mode: "cbc", - iv: sjcl.random.randomWords(4, 0) - }; - - var ctJson = sjcl.encrypt(key, plaintextValue, params, response); - - var ct = ctJson.match(/"ct":"([^"]*)"/)[1]; - var iv = sjcl.codec.base64.fromBits(response.iv); - - var cs = new CipherString(iv + "|" + ct); - callback(cs); - }); + return deferred.promise; }; - CryptoService.prototype.decrypt = function (cipherString, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } + CryptoService.prototype.decrypt = function (cipherString) { + var deferred = Q.defer(); if (cipherString === null || cipherString === undefined || !cipherString.encryptedString) { throw 'cannot decrypt nothing'; @@ -148,7 +146,9 @@ function initCryptoService() { var decBits = sjcl.mode.cbc.decrypt(aes, ctBits, ivBits, null); var decValue = sjcl.codec.utf8String.fromBits(decBits); - callback(decValue); + deferred.resolve(decValue); }); + + return deferred.promise; }; }; diff --git a/src/services/folderService.js b/src/services/folderService.js index 5d7a1144..8f6ae4d6 100644 --- a/src/services/folderService.js +++ b/src/services/folderService.js @@ -13,26 +13,12 @@ function initFolderService() { id: folder.id }; - var deferred = Q.defer(); - - encryptWithPromise(folder.name).then(function (cs) { + return cryptoService.encrypt(folder.name).then(function (cs) { model.name = cs; - deferred.resolve(model); + return model; }); - - return deferred.promise; }; - function encryptWithPromise(plaintextString) { - var deferred = Q.defer(); - - cryptoService.encrypt(plaintextString, function (cipherString) { - deferred.resolve(cipherString); - }); - - return deferred.promise; - } - FolderService.prototype.get = function (id, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; @@ -101,10 +87,8 @@ function initFolderService() { return deferred.promise; }; - FolderService.prototype.saveWithServer = function (folder, callback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } + FolderService.prototype.saveWithServer = function (folder) { + var deferred = Q.defer(); var self = this, request = new FolderRequest(folder); @@ -121,10 +105,12 @@ function initFolderService() { userService.getUserId(function (userId) { var data = new FolderData(response, userId); self.upsert(data, function () { - callback(folder); + deferred.resolve(folder); }); }); } + + return deferred.promise; }; FolderService.prototype.upsert = function (folder, callback) { diff --git a/src/services/siteService.js b/src/services/siteService.js index 78105177..6b889673 100644 --- a/src/services/siteService.js +++ b/src/services/siteService.js @@ -15,38 +15,24 @@ function initSiteService() { favorite: site.favorite }; - var deferred = Q.defer(); - - encryptWithPromise(site.name).then(function (cs) { + return cryptoService.encrypt(site.name).then(function (cs) { model.name = cs; - return encryptWithPromise(site.uri); + return cryptoService.encrypt(site.uri); }).then(function (cs) { model.uri = cs; - return encryptWithPromise(site.username); + return cryptoService.encrypt(site.username); }).then(function (cs) { model.username = cs; - return encryptWithPromise(site.password); + return cryptoService.encrypt(site.password); }).then(function (cs) { model.password = cs; - return encryptWithPromise(site.notes); + return cryptoService.encrypt(site.notes); }).then(function (cs) { model.notes = cs; - deferred.resolve(model); + return model; }); - - return deferred.promise; }; - function encryptWithPromise(plaintextString) { - var deferred = Q.defer(); - - cryptoService.encrypt(plaintextString, function (cipherString) { - deferred.resolve(cipherString); - }); - - return deferred.promise; - } - SiteService.prototype.get = function (id, callback) { if (!callback || typeof callback !== 'function') { throw 'callback function required'; @@ -118,18 +104,20 @@ function initSiteService() { return deferred.promise; }; - SiteService.prototype.saveWithServer = function (site, successCallback, errorCallback) { + SiteService.prototype.saveWithServer = function (site) { + var deferred = Q.defer(); + var self = this, request = new SiteRequest(site); if (!site.id) { self.apiService.postSite(request, apiSuccess, function (response) { - handleError(response, errorCallback) + handleError(response, deferred) }); } else { self.apiService.putSite(site.id, request, apiSuccess, function (response) { - handleError(response, errorCallback) + handleError(response, deferred) }); } @@ -138,12 +126,12 @@ function initSiteService() { userService.getUserId(function (userId) { var data = new SiteData(response, userId); self.upsert(data, function () { - if (successCallback) { - successCallback(site); - } + deferred.resolve(site); }); }); } + + return deferred.promise; }; SiteService.prototype.upsert = function (site, callback) { @@ -230,27 +218,26 @@ function initSiteService() { }); }; - SiteService.prototype.deleteWithServer = function (id, successCallback, errorCallback) { - if (!callback || typeof callback !== 'function') { - throw 'callback function required'; - } + SiteService.prototype.deleteWithServer = function (id) { + var deferred = Q.defer(); var self = this; self.apiService.deleteCipher(id, function (response) { - self.delete(id, successCallback); + self.delete(id, function () { + deferred.resolve(); + }); }, function (response) { - handleError(response, errorCallback) + handleError(response, deferred) }); + + return deferred.promise; }; - function handleError(error, callback) { + function handleError(error, deferred) { if (error.status == 401 || error.status == 403) { // TODO: logout - } - if (callback) { - callback(error); - } + deferred.reject(error); } };