convert to promises. loginService cipher refactor

This commit is contained in:
Kyle Spearrin 2017-10-13 17:07:20 -04:00
parent 294817d17b
commit 2b5915b257
15 changed files with 526 additions and 527 deletions

View File

@ -32,14 +32,14 @@ var bg_isBackground = true,
bg_i18nService = new i18nService(bg_utilsService);
bg_constantsService = new ConstantsService(bg_i18nService);
bg_cryptoService = new CryptoService(bg_constantsService);
bg_tokenService = new TokenService();
bg_tokenService = new TokenService(bg_utilsService);
bg_appIdService = new AppIdService();
bg_apiService = new ApiService(bg_tokenService, bg_appIdService, bg_utilsService, bg_constantsService, logout);
bg_environmentService = new EnvironmentService(bg_constantsService, bg_apiService);
bg_userService = new UserService(bg_tokenService, bg_apiService, bg_cryptoService);
bg_settingsService = new SettingsService(bg_userService);
bg_loginService = new LoginService(bg_cryptoService, bg_userService, bg_apiService, bg_settingsService);
bg_folderService = new FolderService(bg_cryptoService, bg_userService, bg_apiService, bg_i18nService);
bg_userService = new UserService(bg_tokenService, bg_apiService, bg_cryptoService, bg_utilsService);
bg_settingsService = new SettingsService(bg_userService, bg_utilsService);
bg_loginService = new LoginService(bg_cryptoService, bg_userService, bg_apiService, bg_settingsService, bg_utilsService);
bg_folderService = new FolderService(bg_cryptoService, bg_userService, bg_apiService, bg_i18nService, bg_utilsService);
bg_lockService = new LockService(bg_constantsService, bg_cryptoService, bg_folderService, bg_loginService, bg_utilsService,
setIcon, refreshBadgeAndMenu);
bg_syncService = new SyncService(bg_loginService, bg_folderService, bg_userService, bg_apiService, bg_settingsService,
@ -807,27 +807,23 @@ var bg_isBackground = true,
}
}
// TODO: Fix callback hell by moving to promises
function logout(expired, callback) {
bg_userService.getUserId(function (userId) {
bg_syncService.setLastSync(new Date(0), function () {
bg_settingsService.clear(function () {
bg_tokenService.clearToken(function () {
bg_cryptoService.clearKeys(function () {
bg_userService.clear(function () {
bg_loginService.clear(userId, function () {
bg_folderService.clear(userId, function () {
chrome.runtime.sendMessage({
command: 'doneLoggingOut', expired: expired
});
setIcon();
refreshBadgeAndMenu();
callback();
});
});
});
});
bg_syncService.setLastSync(new Date(0), function () {
bg_userService.getUserIdPromise().then(function (userId) {
return Q.all([
bg_tokenService.clearToken(),
bg_cryptoService.clearKeys(),
bg_userService.clear(),
bg_settingsService.clear(userId),
bg_loginService.clear(userId),
bg_folderService.clear(userId)
]).then(function () {
chrome.runtime.sendMessage({
command: 'doneLoggingOut', expired: expired
});
setIcon();
refreshBadgeAndMenu();
callback();
});
});
});

View File

@ -7,12 +7,49 @@
this.favorite = cipher.favorite;
switch (type) {
case 1: // login
case 1: // cipherType.login
this.login = {
uri: cipher.uri ? cipher.uri.encryptedString : null,
username: cipher.username ? cipher.username.encryptedString : null,
password: cipher.password ? cipher.password.encryptedString : null,
totp: cipher.totp ? cipher.totp.encryptedString : null
uri: cipher.login.uri ? cipher.login.uri.encryptedString : null,
username: cipher.login.username ? cipher.login.username.encryptedString : null,
password: cipher.login.password ? cipher.login.password.encryptedString : null,
totp: cipher.login.totp ? cipher.login.totp.encryptedString : null
};
break;
case 2: // cipherType.secureNote
this.secureNote = {
type: cipher.secureNote.type
};
break;
case 3: // cipherType.card
this.card = {
cardholderName: cipher.card.cardholderName ? cipher.card.cardholderName.encryptedString : null,
brand: cipher.card.brand ? cipher.card.brand.encryptedString : null,
number: cipher.card.number ? cipher.card.number.encryptedString : null,
expMonth: cipher.card.expMonth ? cipher.card.expMonth.encryptedString : null,
expYear: cipher.card.expYear ? cipher.card.expYear.encryptedString : null,
code: cipher.card.code ? cipher.card.code.encryptedString : null
};
break;
case 4: // cipherType.identity
this.identity = {
title: cipher.identity.title ? cipher.identity.title.encryptedString : null,
firstName: cipher.identity.firstName ? cipher.identity.firstName.encryptedString : null,
middleName: cipher.identity.middleName ? cipher.identity.middleName.encryptedString : null,
lastName: cipher.identity.lastName ? cipher.identity.lastName.encryptedString : null,
address1: cipher.identity.address1 ? cipher.identity.address1.encryptedString : null,
address2: cipher.identity.address2 ? cipher.identity.address2.encryptedString : null,
address3: cipher.identity.address3 ? cipher.identity.address3.encryptedString : null,
city: cipher.identity.city ? cipher.identity.city.encryptedString : null,
state: cipher.identity.state ? cipher.identity.state.encryptedString : null,
postalCode: cipher.identity.postalCode ? cipher.identity.postalCode.encryptedString : null,
country: cipher.identity.country ? cipher.identity.country.encryptedString : null,
company: cipher.identity.company ? cipher.identity.company.encryptedString : null,
email: cipher.identity.email ? cipher.identity.email.encryptedString : null,
phone: cipher.identity.phone ? cipher.identity.phone.encryptedString : null,
ssn: cipher.identity.ssn ? cipher.identity.ssn.encryptedString : null,
username: cipher.identity.username ? cipher.identity.username.encryptedString : null,
passportNumber: cipher.identity.passportNumber ? cipher.identity.passportNumber.encryptedString : null,
licenseNumber: cipher.identity.licenseNumber ? cipher.identity.licenseNumber.encryptedString : null
};
break;
default:

View File

@ -1,7 +1,7 @@
angular
.module('bit.vault')
.controller('vaultAttachmentsController', function ($scope, $state, $stateParams, loginService, $q, toastr,
.controller('vaultAttachmentsController', function ($scope, $state, $stateParams, loginService, toastr,
SweetAlert, utilsService, $analytics, i18nService, cryptoService, tokenService) {
$scope.i18n = i18nService;
utilsService.initListSectionItemListeners($(document), angular);
@ -10,44 +10,44 @@ angular
$scope.canAccessAttachments = $scope.isPremium;
$scope.hasUpdatedKey = false;
loginService.get($stateParams.id, function (login) {
$q.when(login.decrypt()).then(function (model) {
$scope.login = model;
$scope.canAccessAttachments = $scope.isPremium || !!$scope.login.organizationId;
loginService.get($stateParams.id).then(function (login) {
return login.decrypt();
}).then(function (model) {
$scope.login = model;
$scope.canAccessAttachments = $scope.isPremium || !!$scope.login.organizationId;
if (!$scope.canAccessAttachments) {
SweetAlert.swal({
title: i18nService.premiumRequired,
text: i18nService.premiumRequiredDesc,
showCancelButton: true,
confirmButtonText: i18nService.learnMore,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
chrome.tabs.create({ url: 'https://vault.bitwarden.com/#/?premium=purchase' });
}
});
return;
}
else {
cryptoService.getEncKey().then(function (key) {
$scope.hasUpdatedKey = !!key;
if (!$scope.hasUpdatedKey) {
SweetAlert.swal({
title: i18nService.featureUnavailable,
text: i18nService.updateKey,
showCancelButton: true,
confirmButtonText: i18nService.learnMore,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
chrome.tabs.create({ url: 'https://help.bitwarden.com/article/update-encryption-key/' });
}
});
}
});
}
});
if (!$scope.canAccessAttachments) {
SweetAlert.swal({
title: i18nService.premiumRequired,
text: i18nService.premiumRequiredDesc,
showCancelButton: true,
confirmButtonText: i18nService.learnMore,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
chrome.tabs.create({ url: 'https://vault.bitwarden.com/#/?premium=purchase' });
}
});
return;
}
else {
cryptoService.getEncKey().then(function (key) {
$scope.hasUpdatedKey = !!key;
if (!$scope.hasUpdatedKey) {
SweetAlert.swal({
title: i18nService.featureUnavailable,
text: i18nService.updateKey,
showCancelButton: true,
confirmButtonText: i18nService.learnMore,
cancelButtonText: i18nService.cancel
}, function (confirmed) {
if (confirmed) {
chrome.tabs.create({ url: 'https://help.bitwarden.com/article/update-encryption-key/' });
}
});
}
});
}
});
$scope.submitPromise = null;
@ -69,8 +69,8 @@ angular
return deferred.promise;
}
$scope.submitPromise = $q.when(loginService.saveAttachmentWithServer($scope.login, files[0])).then(function (login) {
$q.when(login.decrypt()).then(function (model) {
$scope.submitPromise = loginService.saveAttachmentWithServer($scope.login, files[0]).then(function (login) {
login.decrypt().then(function (model) {
$scope.login = model;
});
$analytics.eventTrack('Added Attachment');
@ -100,7 +100,7 @@ angular
cancelButtonText: i18nService.no
}, function (confirmed) {
if (confirmed) {
$q.when(loginService.deleteAttachmentWithServer($stateParams.id, attachment.id)).then(function () {
loginService.deleteAttachmentWithServer($stateParams.id, attachment.id).then(function () {
var index = $scope.login.attachments.indexOf(attachment);
if (index > -1) {
$scope.login.attachments.splice(index, 1);

View File

@ -2,7 +2,7 @@ angular
.module('bit.vault')
.controller('vaultEditLoginController', function ($scope, $state, $stateParams, loginService, folderService,
cryptoService, $q, toastr, SweetAlert, utilsService, $analytics, i18nService, constantsService) {
cryptoService, toastr, SweetAlert, utilsService, $analytics, i18nService, constantsService) {
$scope.i18n = i18nService;
$scope.constants = constantsService;
$scope.showAttachments = !utilsService.isEdge();
@ -21,14 +21,14 @@ angular
angular.extend($scope.login, $stateParams.login);
}
else {
loginService.get(loginId, function (login) {
$q.when(login.decrypt()).then(function (model) {
$scope.login = model;
});
loginService.get(loginId).then(function (login) {
return login.decrypt();
}).then(function (model) {
$scope.login = model;
});
}
$q.when(folderService.getAllDecrypted()).then(function (folders) {
folderService.getAllDecrypted().then(function (folders) {
$scope.folders = folders;
});
@ -41,9 +41,9 @@ angular
return;
}
$scope.savePromise = $q.when(loginService.encrypt(model)).then(function (loginModel) {
$scope.savePromise = loginService.encrypt(model).then(function (loginModel) {
var login = new Login(loginModel, true);
return $q.when(loginService.saveWithServer(login)).then(function (login) {
return loginService.saveWithServer(login).then(function (login) {
$analytics.eventTrack('Edited Login');
toastr.success(i18nService.editedLogin);
$scope.close();
@ -60,7 +60,7 @@ angular
cancelButtonText: i18nService.no
}, function (confirmed) {
if (confirmed) {
$q.when(loginService.deleteWithServer(loginId)).then(function () {
loginService.deleteWithServer(loginId).then(function () {
$analytics.eventTrack('Deleted Login');
toastr.success(i18nService.deletedLogin);
$state.go('tabs.vault', {

View File

@ -1,7 +1,7 @@
angular
.module('bit.vault')
.controller('vaultViewLoginController', function ($scope, $state, $stateParams, loginService, toastr, $q,
.controller('vaultViewLoginController', function ($scope, $state, $stateParams, loginService, toastr,
$analytics, i18nService, utilsService, totpService, $timeout, tokenService, $window, cryptoService, SweetAlert,
constantsService) {
$scope.constants = constantsService;
@ -12,45 +12,45 @@ angular
$scope.isPremium = tokenService.getPremium();
$scope.login = null;
loginService.get($stateParams.loginId, function (login) {
loginService.get($stateParams.loginId).then(function (login) {
if (!login) {
return;
}
$q.when(login.decrypt()).then(function (model) {
$scope.login = model;
return login.decrypt();
}).then(function (model) {
$scope.login = model;
if (model.password) {
$scope.login.maskedPassword = $scope.maskValue(model.password);
}
if (model.password) {
$scope.login.maskedPassword = $scope.maskValue(model.password);
}
if (model.uri) {
$scope.login.showLaunch = model.uri.startsWith('http://') || model.uri.startsWith('https://');
var domain = utilsService.getDomain(model.uri);
if (domain) {
$scope.login.website = domain;
}
else {
$scope.login.website = model.uri;
}
if (model.uri) {
$scope.login.showLaunch = model.uri.startsWith('http://') || model.uri.startsWith('https://');
var domain = utilsService.getDomain(model.uri);
if (domain) {
$scope.login.website = domain;
}
else {
$scope.login.showLaunch = false;
$scope.login.website = model.uri;
}
}
else {
$scope.login.showLaunch = false;
}
if (model.totp && (login.organizationUseTotp || tokenService.getPremium())) {
totpUpdateCode();
totpTick();
if (totpInterval) {
clearInterval(totpInterval);
}
if (model.totp && (login.organizationUseTotp || tokenService.getPremium())) {
totpUpdateCode();
totpInterval = setInterval(function () {
totpTick();
if (totpInterval) {
clearInterval(totpInterval);
}
totpInterval = setInterval(function () {
totpTick();
}, 1000);
}
});
}, 1000);
}
});
$scope.edit = function (login) {

View File

@ -257,8 +257,10 @@ function initApiService() {
// Cipher APIs
ApiService.prototype.postCipher = function (cipherRequest, success, error) {
var self = this;
ApiService.prototype.postCipher = function (cipherRequest) {
var self = this,
deferred = Q.defer();
handleTokenState(self).then(function (tokenHeader) {
$.ajax({
type: 'POST',
@ -268,19 +270,23 @@ function initApiService() {
dataType: 'json',
headers: tokenHeader,
success: function (response) {
success(new CipherResponse(response));
deferred.resolve(new CipherResponse(response));
},
error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, false, self);
handleError(deferred.reject, jqXHR, false, self);
}
});
}, function (jqXHR) {
handleError(error, jqXHR, true, self);
handleError(deferred.reject, jqXHR, true, self);
});
return deferred.promise;
};
ApiService.prototype.putCipher = function (id, cipherRequest, success, error) {
var self = this;
ApiService.prototype.putCipher = function (id, cipherRequest) {
var self = this,
deferred = Q.defer();
handleTokenState(self).then(function (tokenHeader) {
$.ajax({
type: 'PUT',
@ -290,19 +296,23 @@ function initApiService() {
dataType: 'json',
headers: tokenHeader,
success: function (response) {
success(new CipherResponse(response));
deferred.resolve(new CipherResponse(response));
},
error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, false, self);
handleError(deferred.reject, jqXHR, false, self);
}
});
}, function (jqXHR) {
handleError(error, jqXHR, true, self);
handleError(deferred.reject, jqXHR, true, self);
});
return deferred.promise;
};
ApiService.prototype.deleteCipher = function (id, success, error) {
var self = this;
ApiService.prototype.deleteCipher = function (id) {
var self = this,
deferred = Q.defer();
handleTokenState(self).then(function (tokenHeader) {
$.ajax({
type: 'DELETE',
@ -310,19 +320,23 @@ function initApiService() {
dataType: 'text',
headers: tokenHeader,
success: function (response) {
success();
deferred.resolve(response);
},
error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, false, self);
handleError(deferred.reject, jqXHR, false, self);
}
});
}, function (jqXHR) {
handleError(error, jqXHR, true, self);
handleError(deferred.reject, jqXHR, true, self);
});
return deferred.promise;
};
ApiService.prototype.postCipherAttachment = function (id, formData, success, error) {
var self = this;
ApiService.prototype.postCipherAttachment = function (id, formData) {
var self = this,
deferred = Q.defer();
handleTokenState(self).then(function (tokenHeader) {
$.ajax({
type: 'POST',
@ -333,19 +347,23 @@ function initApiService() {
dataType: 'json',
headers: tokenHeader,
success: function (response) {
success(new CipherResponse(response));
deferred.resolve(new CipherResponse(response));
},
error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, false, self);
handleError(deferred.reject, jqXHR, false, self);
}
});
}, function (jqXHR) {
handleError(error, jqXHR, true, self);
handleError(deferred.reject, jqXHR, true, self);
});
return deferred.promise;
};
ApiService.prototype.deleteCipherAttachment = function (id, attachmentId, success, error) {
var self = this;
var self = this,
deferred = Q.defer();
handleTokenState(self).then(function (tokenHeader) {
$.ajax({
type: 'DELETE',
@ -353,15 +371,17 @@ function initApiService() {
dataType: 'text',
headers: tokenHeader,
success: function (response) {
success();
deferred.resolve(response);
},
error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, false, self);
handleError(deferred.reject, jqXHR, false, self);
}
});
}, function (jqXHR) {
handleError(error, jqXHR, true, self);
handleError(deferred.reject, jqXHR, true, self);
});
return deferred.promise;
};
// Sync APIs

View File

@ -226,7 +226,7 @@ function initAutofill() {
didAutofill = true;
if (!options.skipLastUsed) {
self.loginService.updateLastUsedDate(options.login.id, function () { });
self.loginService.updateLastUsedDate(options.login.id);
}
chrome.tabs.sendMessage(tab.id, {

View File

@ -336,21 +336,15 @@ function initCryptoService(constantsService) {
return deferred.promise;
};
CryptoService.prototype.clearKeys = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
CryptoService.prototype.clearKeys = function () {
var self = this;
Q.all([
return Q.all([
self.clearKey(),
self.clearKeyHash(),
self.clearOrgKeys(),
self.clearEncKey(),
self.clearPrivateKey()
]).then(function () {
callback();
});
]);
};
CryptoService.prototype.toggleKey = function (callback) {

View File

@ -1,8 +1,9 @@
function FolderService(cryptoService, userService, apiService, i18nService) {
function FolderService(cryptoService, userService, apiService, i18nService, utilsService) {
this.cryptoService = cryptoService;
this.userService = userService;
this.apiService = apiService;
this.i18nService = i18nService;
this.utilsService = utilsService;
this.decryptedFolderCache = null;
initFolderService();
@ -171,33 +172,19 @@ function initFolderService() {
});
};
FolderService.prototype.replace = function (folders, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
FolderService.prototype.replace = function (folders) {
var self = this;
self.userService.getUserId(function (userId) {
var obj = {};
obj['folders_' + userId] = folders;
chrome.storage.local.set(obj, function () {
self.decryptedFolderCache = null;
callback();
});
self.userService.getUserIdPromise().then(function (userId) {
return self.utilsService.saveObjToStorage('folders_' + userId, folders);
}).then(function () {
self.decryptedFolderCache = null;
});
};
FolderService.prototype.clear = function (userId, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
FolderService.prototype.clear = function (userId) {
var self = this;
chrome.storage.local.remove('folders_' + userId, function () {
return self.utilsService.removeFromStorage('folders_' + userId).then(function () {
self.decryptedFolderCache = null;
callback();
});
};

View File

@ -1,16 +1,18 @@
function LoginService(cryptoService, userService, apiService, settingsService) {
function LoginService(cryptoService, userService, apiService, settingsService, utilsService) {
this.cryptoService = cryptoService;
this.userService = userService;
this.apiService = apiService;
this.settingsService = settingsService;
this.decryptedLoginCache = null;
this.utilsService = utilsService;
this.decryptedCipherCache = null;
this.localDataKey = 'sitesLocalData';
initLoginService();
}
function initLoginService() {
LoginService.prototype.clearCache = function () {
this.decryptedLoginCache = null;
this.decryptedCipherCache = null;
};
LoginService.prototype.encrypt = function (login) {
@ -93,114 +95,98 @@ function initLoginService() {
});
};
LoginService.prototype.get = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
LoginService.prototype.get = function (id) {
var self = this,
key = null,
localData;
this.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
var localDataKey = 'sitesLocalData';
return self.userService.getUserIdPromise().then(function (userId) {
key = 'ciphers_' + userId;
return self.utilsService.getObjFromStorage(self.localDataKey);
}).then(function (data) {
localData = data;
if (!localData) {
localData = {};
}
return self.utilsService.getObjFromStorage(key);
}).then(function (ciphers) {
if (ciphers && id in ciphers) {
return new Login(ciphers[id], false, localData[id]);
}
chrome.storage.local.get(localDataKey, function (localDataObj) {
var localData = localDataObj[localDataKey];
if (!localData) {
localData = {};
}
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (logins && id in logins) {
callback(new Login(logins[id], false, localData[id]));
return;
}
callback(null);
});
});
return null;
});
};
LoginService.prototype.getAll = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
LoginService.prototype.getAll = function () {
var self = this,
key = null,
localData = null;
this.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
var localDataKey = 'sitesLocalData';
chrome.storage.local.get(localDataKey, function (localDataObj) {
var localData = localDataObj[localDataKey];
if (!localData) {
localData = {};
self.userService.getUserIdPromise().then(function (userId) {
key = 'ciphers_' + userId;
return self.utilsService.getObjFromStorage(self.localDataKey);
}).then(function (data) {
localData = data;
if (!localData) {
localData = {};
}
return self.utilsService.getObjFromStorage(key);
}).then(function (logins) {
var response = [];
for (var id in logins) {
if (id) {
response.push(new Login(logins[id], false, localData[id]));
}
}
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
var response = [];
for (var id in logins) {
if (!id) {
continue;
}
response.push(new Login(logins[id], false, localData[id]));
}
callback(response);
});
});
return response;
});
};
LoginService.prototype.getAllDecrypted = function () {
var deferred = Q.defer();
var self = this;
var self = this,
decLogins = [];
self.cryptoService.getKey().then(function (key) {
return self.cryptoService.getKey().then(function (key) {
if (!key) {
deferred.reject();
return;
}
if (self.decryptedLoginCache) {
deferred.resolve(self.decryptedLoginCache);
if (self.decryptedCipherCache) {
deferred.resolve(self.decryptedCipherCache);
return;
}
return self.getAll();
}).then(function (logins) {
var promises = [];
var decLogins = [];
self.getAll(function (logins) {
for (var i = 0; i < logins.length; i++) {
/* jshint ignore:start */
promises.push(logins[i].decrypt().then(function (login) {
decLogins.push(login);
}));
/* jshint ignore:end */
}
for (var i = 0; i < logins.length; i++) {
/* jshint ignore:start */
promises.push(logins[i].decrypt().then(function (login) {
decLogins.push(login);
}));
/* jshint ignore:end */
}
Q.all(promises).then(function () {
self.decryptedLoginCache = decLogins;
deferred.resolve(self.decryptedLoginCache);
});
});
return Q.all(promises);
}).then(function () {
self.decryptedCipherCache = decLogins;
return self.decryptedCipherCache;
});
return deferred.promise;
};
LoginService.prototype.getAllDecryptedForFolder = function (folderId) {
var self = this;
return self.getAllDecrypted().then(function (logins) {
var loginsToReturn = [];
for (var i = 0; i < logins.length; i++) {
if (logins[i].folderId === folderId) {
loginsToReturn.push(logins[i]);
return this.getAllDecrypted().then(function (ciphers) {
var ciphersToReturn = [];
for (var i = 0; i < ciphers.length; i++) {
if (ciphers[i].folderId === folderId) {
ciphersToReturn.push(ciphers[i]);
}
}
return loginsToReturn;
return ciphersToReturn;
});
};
@ -222,265 +208,222 @@ function initLoginService() {
return matchingDomains;
});
var loginsPromise = self.getAllDecrypted().then(function (logins) {
return logins;
});
return Q.all([eqDomainsPromise, self.getAllDecrypted()]).then(function (result) {
var matchingDomains = result[0],
ciphers = result[1],
ciphersToReturn = [];
return Q.all([eqDomainsPromise, loginsPromise]).then(function (result) {
var matchingDomains = result[0];
var logins = result[1];
var loginsToReturn = [];
for (var i = 0; i < logins.length; i++) {
if (logins[i].domain && matchingDomains.indexOf(logins[i].domain) >= 0) {
loginsToReturn.push(logins[i]);
for (var i = 0; i < ciphers.length; i++) {
if (ciphers[i].domain && matchingDomains.indexOf(ciphers[i].domain) > -1) {
ciphersToReturn.push(ciphers[i]);
}
}
return loginsToReturn;
return ciphersToReturn;
});
};
LoginService.prototype.getLastUsedForDomain = function (domain) {
var self = this;
var deferred = Q.defer();
self.getAllDecryptedForDomain(domain).then(function (logins) {
if (!logins.length) {
var self = this,
deferred = Q.defer();
self.getAllDecryptedForDomain(domain).then(function (ciphers) {
if (!ciphers.length) {
deferred.reject();
return;
}
var sortedLogins = logins.sort(self.sortLoginsByLastUsed);
deferred.resolve(sortedLogins[0]);
var sortedCiphers = ciphers.sort(self.sortCiphersByLastUsed);
deferred.resolve(sortedCiphers[0]);
});
return deferred.promise;
};
LoginService.prototype.saveWithServer = function (login) {
LoginService.prototype.saveWithServer = function (cipher) {
var deferred = Q.defer();
var self = this,
request = new CipherRequest(login, 1); // 1 = Login
// TODO
request = new CipherRequest(cipher, 1); // 1 = Login
if (!login.id) {
self.apiService.postCipher(request, apiSuccess, function (response) {
handleError(response, deferred);
if (!cipher.id) {
self.apiService.postCipher(request).then(apiSuccess, function (response) {
deferred.reject(response);
});
}
else {
self.apiService.putCipher(login.id, request, apiSuccess, function (response) {
handleError(response, deferred);
self.apiService.putCipher(cipher.id, request).then(apiSuccess, function (response) {
deferred.reject(response);
});
}
function apiSuccess(response) {
login.id = response.id;
self.userService.getUserId(function (userId) {
cipher.id = response.id;
self.userService.getUserIdPromise().then(function (userId) {
var data = new LoginData(response, userId);
self.upsert(data, function () {
deferred.resolve(login);
});
return self.upsert(data);
}).then(function () {
deferred.resolve(cipher);
});
}
return deferred.promise;
};
LoginService.prototype.upsert = function (login, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
LoginService.prototype.upsert = function (cipher) {
var self = this,
key = null;
var self = this;
return self.userService.getUserIdPromise().then(function (userId) {
key = 'ciphers_' + userId;
return self.utilsService.getObjFromStorage(key);
}).then(function (ciphers) {
if (!ciphers) {
ciphers = {};
}
self.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (!logins) {
logins = {};
if (cipher.constructor === Array) {
for (var i = 0; i < cipher.length; i++) {
ciphers[cipher[i].id] = cipher[i];
}
}
else {
ciphers[cipher.id] = cipher;
}
if (login.constructor === Array) {
for (var i = 0; i < login.length; i++) {
logins[login[i].id] = login[i];
}
}
else {
logins[login.id] = login;
}
obj[loginsKey] = logins;
chrome.storage.local.set(obj, function () {
self.decryptedLoginCache = null;
callback();
});
});
return self.utilsService.saveObjToStorage(key, ciphers);
}).then(function () {
self.decryptedCipherCache = null;
});
};
LoginService.prototype.updateLastUsedDate = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
LoginService.prototype.updateLastUsedDate = function (id) {
var self = this;
var localDataKey = 'sitesLocalData';
chrome.storage.local.get(localDataKey, function (obj) {
var loginsLocalData = obj[localDataKey];
if (!loginsLocalData) {
loginsLocalData = {};
var ciphersLocalData = null;
return self.utilsService.getObjFromStorage(self.localDataKey).then(function (obj) {
ciphersLocalData = obj;
if (!ciphersLocalData) {
ciphersLocalData = {};
}
if (loginsLocalData[id]) {
loginsLocalData[id].lastUsedDate = new Date().getTime();
if (ciphersLocalData[id]) {
ciphersLocalData[id].lastUsedDate = new Date().getTime();
}
else {
loginsLocalData[id] = {
ciphersLocalData[id] = {
lastUsedDate: new Date().getTime()
};
}
obj[localDataKey] = loginsLocalData;
return self.utilsService.saveObjToStorage(key, ciphersLocalData);
}).then(function () {
if (!self.decryptedCipherCache) {
return;
}
chrome.storage.local.set(obj, function () {
if (self.decryptedLoginCache) {
for (var i = 0; i < self.decryptedLoginCache.length; i++) {
if (self.decryptedLoginCache[i].id === id) {
self.decryptedLoginCache[i].localData = loginsLocalData[id];
break;
}
for (var i = 0; i < self.decryptedCipherCache.length; i++) {
if (self.decryptedCipherCache[i].id === id) {
self.decryptedCipherCache[i].localData = ciphersLocalData[id];
break;
}
}
});
};
LoginService.prototype.replace = function (ciphers) {
var self = this;
self.userService.getUserIdPromise().then(function (userId) {
return self.utilsService.saveObjToStorage('ciphers_' + userId, ciphers);
}).then(function () {
self.decryptedCipherCache = null;
});
};
LoginService.prototype.clear = function (userId) {
var self = this;
return self.utilsService.removeFromStorage('ciphers_' + userId).then(function () {
self.decryptedCipherCache = null;
});
};
LoginService.prototype.delete = function (id) {
var self = this,
key = null;
self.userService.getUserIdPromise().then(function () {
key = 'ciphers_' + userId;
return self.utilsService.getObjFromStorage(key);
}).then(function (logins) {
if (!logins) {
return null;
}
if (id.constructor === Array) {
for (var i = 0; i < id.length; i++) {
if (id[i] in logins) {
delete logins[id[i]];
}
}
}
else if (id in logins) {
delete logins[id];
}
else {
return null;
}
callback();
});
});
};
return logins;
}).then(function (logins) {
if (!logins) {
return false;
}
LoginService.prototype.replace = function (logins, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
self.userService.getUserId(function (userId) {
var obj = {};
obj['sites_' + userId] = logins;
chrome.storage.local.set(obj, function () {
self.decryptedLoginCache = null;
callback();
});
});
};
LoginService.prototype.clear = function (userId, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
chrome.storage.local.remove('sites_' + userId, function () {
self.decryptedLoginCache = null;
callback();
});
};
LoginService.prototype.delete = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
self.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (!logins) {
callback();
return;
}
if (id.constructor === Array) {
for (var i = 0; i < id.length; i++) {
if (id[i] in logins) {
delete logins[id[i]];
}
}
}
else if (id in logins) {
delete logins[id];
}
else {
callback();
return;
}
obj[loginsKey] = logins;
chrome.storage.local.set(obj, function () {
self.decryptedLoginCache = null;
callback();
});
});
return self.utilsService.saveObjToStorage(key, logins);
}).then(function (clearCache) {
if (clearCache !== false) {
self.decryptedCipherCache = null;
}
});
};
LoginService.prototype.deleteWithServer = function (id) {
var deferred = Q.defer();
var self = this;
self.apiService.deleteCipher(id, function () {
self.delete(id, function () {
deferred.resolve();
});
}, function (response) {
handleError(response, deferred);
return self.apiService.deleteCipher(id).then(function () {
return self.delete(id);
});
return deferred.promise;
};
LoginService.prototype.saveNeverDomain = function (domain) {
var deferred = Q.defer();
var neverKey = 'neverDomains';
if (!domain) {
deferred.resolve();
}
else {
chrome.storage.local.get(neverKey, function (obj) {
var domains = obj[neverKey];
if (!domains) {
domains = {};
}
domains[domain] = null;
obj[neverKey] = domains;
chrome.storage.local.set(obj, function () {
deferred.resolve();
});
});
return Q.fcall(function () { });
}
return deferred.promise;
var key = 'neverDomains';
return self.utilsService.getObjFromStorage(key).then(function (domains) {
if (!domains) {
domains = {};
}
domains[domain] = null;
return self.utilsService.saveObjToStorage(key, domains);
});
};
LoginService.prototype.saveAttachmentWithServer = function (login, unencryptedFile) {
var deferred = Q.defer();
var self = this;
LoginService.prototype.saveAttachmentWithServer = function (cipher, unencryptedFile) {
var deferred = Q.defer(),
self = this,
response = null,
data = null,
apiErrored = false;
var key, encFileName;
var reader = new FileReader();
reader.readAsArrayBuffer(unencryptedFile);
reader.onload = function (evt) {
self.cryptoService.getOrgKey(login.organizationId).then(function (theKey) {
self.cryptoService.getOrgKey(cipher.organizationId).then(function (theKey) {
key = theKey;
return self.cryptoService.encrypt(unencryptedFile.name, key);
}).then(function (fileName) {
@ -491,18 +434,24 @@ function initLoginService() {
var blob = new Blob([encData], { type: 'application/octet-stream' });
fd.append('data', blob, encFileName.encryptedString);
self.apiService.postCipherAttachment(login.id, fd,
function (response) {
self.userService.getUserId(function (userId) {
var data = new LoginData(response, userId);
self.upsert(data, function () {
deferred.resolve(new Login(data));
});
});
},
function (response) {
handleErrorMessage(response, deferred);
});
return self.apiService.postCipherAttachment(cipher.id, fd);
}).then(function (resp) {
response = resp;
return self.userService.getUserIdPromise();
}, function (resp) {
apiErrored = true;
handleErrorMessage(resp, deferred);
}).then(function (userId) {
if (apiErrored === true) {
return;
}
data = new LoginData(response, userId);
return self.upsert(data);
}).then(function () {
if (data) {
deferred.resolve(new Login(data));
}
});
};
reader.onerror = function (evt) {
@ -512,48 +461,46 @@ function initLoginService() {
return deferred.promise;
};
LoginService.prototype.deleteAttachment = function (id, attachmentId, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
LoginService.prototype.deleteAttachment = function (id, attachmentId) {
var self = this,
key = null;
var self = this;
self.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (logins && id in logins && logins[id].attachments) {
for (var i = 0; i < logins[id].attachments.length; i++) {
if (logins[id].attachments[i].id === attachmentId) {
logins[id].attachments.splice(i, 1);
}
self.userService.getUserIdPromise().then(function () {
key = 'ciphers_' + userId;
return self.utilsService.getObjFromStorage(key);
}).then(function (logins) {
if (logins && id in logins && logins[id].attachments) {
for (var i = 0; i < logins[id].attachments.length; i++) {
if (logins[id].attachments[i].id === attachmentId) {
logins[id].attachments.splice(i, 1);
}
}
obj[loginsKey] = logins;
chrome.storage.local.set(obj, function () {
self.decryptedLoginCache = null;
callback();
});
}
else {
callback();
}
});
return self.utilsService.saveObjToStorage(key, logins);
}
else {
return false;
}
}).then(function (clearCache) {
if (clearCache !== false) {
self.decryptedCipherCache = null;
}
});
};
LoginService.prototype.deleteAttachmentWithServer = function (id, attachmentId) {
var deferred = Q.defer();
var self = this,
deferred = Q.defer();
var self = this;
self.apiService.deleteCipherAttachment(id, attachmentId, function () {
self.deleteAttachment(id, attachmentId, function () {
deferred.resolve();
});
self.apiService.deleteCipherAttachment(id, attachmentId).then(function () {
return self.deleteAttachment(id, attachmentId);
}, function (response) {
handleErrorMessage(response, deferred);
return false;
}).then(function (apiSuccess) {
if (apiSuccess !== false) {
deferred.resolve();
}
});
return deferred.promise;

View File

@ -1,5 +1,6 @@
function SettingsService(userService) {
function SettingsService(userService, utilsService) {
this.userService = userService;
this.utilsService = utilsService;
this.settingsCache = null;
initSettingsService();
@ -85,18 +86,10 @@ function initSettingsService() {
});
}
SettingsService.prototype.clear = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
SettingsService.prototype.clear = function (userId) {
var self = this;
this.userService.getUserId(function (userId) {
chrome.storage.local.remove('settings_' + userId, function () {
self.settingsCache = null;
callback();
});
return self.utilsService.removeFromStorage('settings_' + userId).then(function () {
self.settingsCache = null;
});
};

View File

@ -131,38 +131,22 @@ function initSyncService() {
}
function syncFolders(self, userId, response) {
var deferred = Q.defer();
var folders = {};
for (var i = 0; i < response.length; i++) {
folders[response[i].id] = new FolderData(response[i], userId);
}
self.folderService.replace(folders, function () {
deferred.resolve();
});
return deferred.promise;
return self.folderService.replace(folders);
}
function syncCiphers(self, userId, response) {
var deferred = Q.defer();
var logins = {};
for (var i = 0; i < response.length; i++) {
var data = response[i];
if (data.type === 1) {
logins[data.id] = new LoginData(data, userId);
}
}
self.loginService.replace(logins, function () {
deferred.resolve();
});
return deferred.promise;
return self.loginService.replace(logins);
}
function syncSettings(self, userId, response) {

View File

@ -1,4 +1,5 @@
function TokenService() {
function TokenService(utilsService) {
this.utilsService = utilsService;
initTokenService();
}
@ -123,16 +124,13 @@ function initTokenService() {
});
};
TokenService.prototype.clearToken = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
_token = _decodedToken = _refreshToken = null;
chrome.storage.local.remove('accessToken', function () {
chrome.storage.local.remove('refreshToken', function () {
callback();
});
TokenService.prototype.clearToken = function () {
var self = this;
return Q.all([
self.utilsService.removeFromStorage('accessToken'),
self.utilsService.removeFromStorage('refreshToken')
]).then(function () {
_token = _decodedToken = _refreshToken = null;
});
};

View File

@ -1,7 +1,8 @@
function UserService(tokenService, apiService, cryptoService) {
function UserService(tokenService, apiService, cryptoService, utilsService) {
this.tokenService = tokenService;
this.apiService = apiService;
this.cryptoService = cryptoService;
this.utilsService = utilsService;
initUserService();
}
@ -72,6 +73,21 @@ function initUserService() {
});
};
UserService.prototype.getUserIdPromise = function () {
if (_userId) {
return Q.fcall(function () {
return _userId;
});
}
return utilsService.getObjFromStorage(userIdKey).then(function (obj) {
if (obj) {
_userId = obj;
}
return _userId;
});
};
UserService.prototype.getEmail = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
@ -108,18 +124,14 @@ function initUserService() {
return deferred.promise;
};
UserService.prototype.clear = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
_userId = _email = _stamp = null;
chrome.storage.local.remove(userIdKey, function () {
chrome.storage.local.remove(userEmailKey, function () {
chrome.storage.local.remove(stampKey, function () {
callback();
});
});
UserService.prototype.clear = function () {
var self = this;
return Q.all([
self.utilsService.removeFromStorage(userIdKey),
self.utilsService.removeFromStorage(userEmailKey),
self.utilsService.removeFromStorage(stampKey)
]).then(function () {
_userId = _email = _stamp = null;
});
};

View File

@ -245,6 +245,37 @@ function initUtilsService() {
theWindow.location.search.indexOf('uilocation=popup') > -1;
};
UtilsService.prototype.saveObjToStorage = function (key, obj) {
var deferred = Q.defer();
var storedObj = {};
storedObj[key] = obj;
chrome.storage.local.set(storedObj, function () {
deferred.resolve();
});
return deferred.promise;
};
UtilsService.prototype.removeFromStorage = function (key) {
var deferred = Q.defer();
chrome.storage.local.remove(key, function () {
deferred.resolve();
});
return deferred.promise;
};
UtilsService.prototype.getObjFromStorage = function (key) {
var deferred = Q.defer();
chrome.storage.local.get(key, function (obj) {
if (obj && obj[key]) {
deferred.resolve(obj[key]);
}
else {
deferred.resolve(null);
}
});
return deferred.promise;
};
function validIpAddress(ipString) {
var ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return ipRegex.test(ipString);