1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-25 16:59:17 +01:00

Refactored rename of Sites => Logins

This commit is contained in:
Kyle Spearrin 2017-01-03 18:40:07 -05:00
parent fcce60eccd
commit fb486003b5
34 changed files with 601 additions and 601 deletions

View File

@ -3,8 +3,8 @@
formData = [], formData = [],
barType = null; barType = null;
chrome.storage.local.get('disableAddSiteNotification', function (obj) { chrome.storage.local.get('disableAddLoginNotification', function (obj) {
if (!obj || !obj['disableAddSiteNotification']) { if (!obj || !obj['disableAddLoginNotification']) {
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: 'bgCollectPageDetails' command: 'bgCollectPageDetails'
}); });

View File

@ -1,11 +1,11 @@
var SiteRequest = function (site) { var LoginRequest = function (login) {
this.folderId = site.folderId; this.folderId = login.folderId;
this.name = site.name ? site.name.encryptedString : null; this.name = login.name ? login.name.encryptedString : null;
this.uri = site.uri ? site.uri.encryptedString : null; this.uri = login.uri ? login.uri.encryptedString : null;
this.username = site.username ? site.username.encryptedString : null; this.username = login.username ? login.username.encryptedString : null;
this.password = site.password ? site.password.encryptedString : null; this.password = login.password ? login.password.encryptedString : null;
this.notes = site.notes ? site.notes.encryptedString : null; this.notes = login.notes ? login.notes.encryptedString : null;
this.favorite = site.favorite; this.favorite = login.favorite;
}; };
var FolderRequest = function (folder) { var FolderRequest = function (folder) {

View File

@ -13,7 +13,7 @@ var FolderResponse = function (response) {
this.revisionDate = response.RevisionDate; this.revisionDate = response.RevisionDate;
}; };
var SiteResponse = function (response) { var LoginResponse = function (response) {
this.id = response.Id; this.id = response.Id;
this.folderId = response.FolderId; this.folderId = response.FolderId;
this.name = response.Name; this.name = response.Name;

View File

@ -15,12 +15,12 @@ var FolderData = function (response, userId) {
this.revisionDate = response.revisionDate; this.revisionDate = response.revisionDate;
}; };
var SiteData = function (response, userId) { var LoginData = function (response, userId) {
this.id = response.id; this.id = response.id;
this.folderId = response.folderId; this.folderId = response.folderId;
this.userId = userId; this.userId = userId;
if (response instanceof SiteResponse) { if (response instanceof LoginResponse) {
this.name = response.name; this.name = response.name;
this.uri = response.uri; this.uri = response.uri;
this.username = response.username; this.username = response.username;

View File

@ -11,7 +11,7 @@ var CipherString = function (encryptedString) {
} }
}; };
var Site = function (obj, alreadyEncrypted) { var Login = function (obj, alreadyEncrypted) {
this.id = obj.id ? obj.id : null; this.id = obj.id ? obj.id : null;
this.folderId = obj.folderId ? obj.folderId : null; this.folderId = obj.folderId ? obj.folderId : null;
this.favorite = obj.favorite ? true : false; this.favorite = obj.favorite ? true : false;
@ -62,7 +62,7 @@ var Folder = function (obj, alreadyEncrypted) {
return deferred.promise; return deferred.promise;
}; };
Site.prototype.decrypt = function () { Login.prototype.decrypt = function () {
var self = this; var self = this;
var model = { var model = {
id: self.id, id: self.id,

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLoginController', function ($scope, $state, $stateParams, loginService, userService, toastr, .controller('accountsLoginController', function ($scope, $state, $stateParams, authService, userService, toastr,
utilsService, $analytics, i18nService) { utilsService, $analytics, i18nService) {
utilsService.initListSectionItemListeners($(document), angular); utilsService.initListSectionItemListeners($(document), angular);
$scope.i18n = i18nService; $scope.i18n = i18nService;
@ -32,7 +32,7 @@
return; return;
} }
$scope.loginPromise = loginService.logIn(model.email, model.masterPassword); $scope.loginPromise = authService.logIn(model.email, model.masterPassword);
$scope.loginPromise.then(function () { $scope.loginPromise.then(function () {
userService.isTwoFactorAuthenticated(function (isTwoFactorAuthenticated) { userService.isTwoFactorAuthenticated(function (isTwoFactorAuthenticated) {

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLoginTwoFactorController', function ($scope, $state, loginService, toastr, utilsService, .controller('accountsLoginTwoFactorController', function ($scope, $state, authService, toastr, utilsService,
$analytics, i18nService) { $analytics, i18nService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
$scope.model = {}; $scope.model = {};
@ -15,7 +15,7 @@
return; return;
} }
$scope.loginPromise = loginService.logInTwoFactor(model.code); $scope.loginPromise = authService.logInTwoFactor(model.code);
$scope.loginPromise.then(function () { $scope.loginPromise.then(function () {
$analytics.eventTrack('Logged In From Two-step'); $analytics.eventTrack('Logged In From Two-step');
$state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true }); $state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true });

View File

@ -95,26 +95,26 @@
data: { authorize: true }, data: { authorize: true },
params: { animation: null, from: 'vault' } params: { animation: null, from: 'vault' }
}) })
.state('viewSite', { .state('viewLogin', {
url: '/view-site?siteId', url: '/view-login?loginId',
templateUrl: 'app/vault/views/vaultViewSite.html', templateUrl: 'app/vault/views/vaultViewLogin.html',
controller: 'vaultViewSiteController', controller: 'vaultViewLoginController',
data: { authorize: true }, data: { authorize: true },
params: { animation: null, from: 'vault' } params: { animation: null, from: 'vault' }
}) })
.state('addSite', { .state('addLogin', {
url: '/add-site', url: '/add-login',
templateUrl: 'app/vault/views/vaultAddSite.html', templateUrl: 'app/vault/views/vaultAddLogin.html',
controller: 'vaultAddSiteController', controller: 'vaultAddLoginController',
data: { authorize: true }, data: { authorize: true },
params: { animation: null, name: null, uri: null, folderId: null, site: null, from: 'vault' } params: { animation: null, name: null, uri: null, folderId: null, login: null, from: 'vault' }
}) })
.state('editSite', { .state('editLogin', {
url: '/edit-site?siteId', url: '/edit-login?loginId',
templateUrl: 'app/vault/views/vaultEditSite.html', templateUrl: 'app/vault/views/vaultEditLogin.html',
controller: 'vaultEditSiteController', controller: 'vaultEditLoginController',
data: { authorize: true }, data: { authorize: true },
params: { animation: null, fromView: true, site: null, from: 'vault' } params: { animation: null, fromView: true, login: null, from: 'vault' }
}) })
.state('passwordGenerator', { .state('passwordGenerator', {
@ -190,7 +190,7 @@
params: { animation: null } params: { animation: null }
}); });
}) })
.run(function ($rootScope, userService, loginService, cryptoService, tokenService, $state, constantsService, stateService) { .run(function ($rootScope, userService, authService, cryptoService, tokenService, $state, constantsService, stateService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) { if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) {
stateService.purgeState(); stateService.purgeState();
@ -221,7 +221,7 @@
if (!isAuthenticated || tokenService.isTokenExpired(token)) { if (!isAuthenticated || tokenService.isTokenExpired(token)) {
event.preventDefault(); event.preventDefault();
loginService.logOut(function () { authService.logOut(function () {
$state.go('home'); $state.go('home');
}); });
} }

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.current') .module('bit.current')
.controller('currentController', function ($scope, siteService, tldjs, toastr, $q, $window, $state, $timeout, .controller('currentController', function ($scope, loginService, tldjs, toastr, $q, $window, $state, $timeout,
autofillService, $analytics, i18nService) { autofillService, $analytics, i18nService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
@ -11,7 +11,7 @@ angular
domain = null, domain = null,
canAutofill = false; canAutofill = false;
$scope.sites = []; $scope.logins = [];
$scope.loaded = false; $scope.loaded = false;
$scope.$on('$viewContentLoaded', function () { $scope.$on('$viewContentLoaded', function () {
@ -41,17 +41,17 @@ angular
canAutofill = true; canAutofill = true;
}); });
var filteredSites = []; var filteredLogins = [];
var sitePromise = $q.when(siteService.getAllDecrypted()); var loginPromise = $q.when(loginService.getAllDecrypted());
sitePromise.then(function (sites) { loginPromise.then(function (logins) {
for (var i = 0; i < sites.length; i++) { for (var i = 0; i < logins.length; i++) {
if (sites[i].domain && sites[i].domain === domain) { if (logins[i].domain && logins[i].domain === domain) {
filteredSites.push(sites[i]); filteredLogins.push(logins[i]);
} }
} }
$scope.loaded = true; $scope.loaded = true;
$scope.sites = filteredSites; $scope.logins = filteredLogins;
}); });
}); });
} }
@ -66,8 +66,8 @@ angular
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password')); $analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
}; };
$scope.addSite = function () { $scope.addLogin = function () {
$state.go('addSite', { $state.go('addLogin', {
animation: 'in-slide-up', animation: 'in-slide-up',
name: domain, name: domain,
uri: url, uri: url,
@ -75,16 +75,16 @@ angular
}); });
}; };
$scope.fillSite = function (site) { $scope.fillLogin = function (login) {
var didAutofill = false; var didAutofill = false;
if (site && canAutofill && pageDetails && pageDetails.length) { if (login && canAutofill && pageDetails && pageDetails.length) {
for (var i = 0; i < pageDetails.length; i++) { for (var i = 0; i < pageDetails.length; i++) {
if (pageDetails[i].tabId !== tabId) { if (pageDetails[i].tabId !== tabId) {
continue; continue;
} }
var fillScript = autofillService.generateFillScript(pageDetails[i].details, site.username, site.password); var fillScript = autofillService.generateFillScript(pageDetails[i].details, login.username, login.password);
if (tabId && fillScript && fillScript.script && fillScript.script.length) { if (tabId && fillScript && fillScript.script && fillScript.script.length) {
didAutofill = true; didAutofill = true;
$analytics.eventTrack('Autofilled'); $analytics.eventTrack('Autofilled');
@ -104,11 +104,11 @@ angular
} }
}; };
$scope.viewSite = function (site, e) { $scope.viewLogin = function (login, e) {
e.stopPropagation(); e.stopPropagation();
$state.go('viewSite', { $state.go('viewLogin', {
siteId: site.id, loginId: login.id,
animation: 'in-slide-up', animation: 'in-slide-up',
from: 'current' from: 'current'
}); });

View File

@ -1,41 +1,41 @@
<div class="header"> <div class="header">
<div class="right"> <div class="right">
<a href="" ng-click="addSite()"><i class="fa fa-plus fa-lg"></i></a> <a href="" ng-click="addLogin()"><i class="fa fa-plus fa-lg"></i></a>
</div> </div>
<div class="title">{{i18n.currentTab}}</div> <div class="title">{{i18n.currentTab}}</div>
</div> </div>
<div class="content content-tabs"> <div class="content content-tabs">
<div ng-if="sites.length"> <div ng-if="logins.length">
<div class="list"> <div class="list">
<div class="list-grouped"> <div class="list-grouped">
<a href="javascript:void(0)" ng-click="fillSite(site)" class="list-grouped-item condensed" <a href="javascript:void(0)" ng-click="fillLogin(login)" class="list-grouped-item condensed"
title="{{i18n.autoFill}} {{site.name}}" ng-repeat="site in theSites = (sites | orderBy: ['name', 'username'])"> title="{{i18n.autoFill}} {{login.name}}" ng-repeat="login in theLogins = (logins | orderBy: ['name', 'username'])">
<span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" <span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{site.password}}" ng-class="{'disabled': !site.password}"> data-clipboard-text="{{login.password}}" ng-class="{'disabled': !login.password}">
<i class="fa fa-lg fa-key"></i> <i class="fa fa-lg fa-key"></i>
</span> </span>
<span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" <span class="btn-list" href="" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{site.username}}" ng-class="{'disabled': !site.username}"> data-clipboard-text="{{login.username}}" ng-class="{'disabled': !login.username}">
<i class="fa fa-lg fa-user"></i> <i class="fa fa-lg fa-user"></i>
</span> </span>
<span class="btn-list" href="" ng-click="viewSite(site, $event) && $event.stopPropagation()" <span class="btn-list" href="" ng-click="viewLogin(login, $event) && $event.stopPropagation()"
title="{{i18n.edit}} {{site.name}}"> title="{{i18n.edit}} {{login.name}}">
<i class="fa fa-lg fa-pencil"></i> <i class="fa fa-lg fa-pencil"></i>
</span> </span>
<span class="text">{{site.name}}</span> <span class="text">{{login.name}}</span>
<span class="detail">{{site.username}}</span> <span class="detail">{{login.username}}</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div class="centered-message" ng-if="loaded && !sites.length"> <div class="centered-message" ng-if="loaded && !logins.length">
<p> <p>
{{i18n.autoFillInfo}} {{i18n.autoFillInfo}}
<button ng-click="addSite()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addSite}}</button> <button ng-click="addLogin()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addLogin}}</button>
</p> </p>
</div> </div>
<div class="page-loading" ng-if="!loaded"> <div class="page-loading" ng-if="!loaded">

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.global') .module('bit.global')
.controller('mainController', function ($scope, $state, loginService, toastr, i18nService) { .controller('mainController', function ($scope, $state, authService, toastr, i18nService) {
var self = this; var self = this;
self.currentYear = new Date().getFullYear(); self.currentYear = new Date().getFullYear();
self.animation = ''; self.animation = '';
@ -24,7 +24,7 @@ angular
$scope.$broadcast('syncStarted'); $scope.$broadcast('syncStarted');
} }
else if (msg.command === 'logout') { else if (msg.command === 'logout') {
loginService.logOut(function () { authService.logOut(function () {
toastr.warning(i18nService.loginExpired, i18nService.loggedOut); toastr.warning(i18nService.loginExpired, i18nService.loggedOut);
$state.go('home'); $state.go('home');
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.lock') .module('bit.lock')
.controller('lockController', function ($scope, $state, $analytics, i18nService, loginService, cryptoService, toastr, .controller('lockController', function ($scope, $state, $analytics, i18nService, authService, cryptoService, toastr,
userService, SweetAlert) { userService, SweetAlert) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
$('#master-password').focus(); $('#master-password').focus();
@ -15,7 +15,7 @@
cancelButtonText: i18nService.cancel cancelButtonText: i18nService.cancel
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
loginService.logOut(function () { authService.logOut(function () {
$analytics.eventTrack('Logged Out'); $analytics.eventTrack('Logged Out');
$state.go('home'); $state.go('home');
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.services') .module('bit.services')
.factory('loginService', function (cryptoService, apiService, userService, tokenService, $q, $rootScope, siteService, .factory('authService', function (cryptoService, apiService, userService, tokenService, $q, $rootScope, loginService,
folderService) { folderService) {
var _service = {}; var _service = {};
@ -73,9 +73,9 @@
cryptoService.clearKeyHash(function () { cryptoService.clearKeyHash(function () {
userService.clearUserId(function () { userService.clearUserId(function () {
userService.clearEmail(function () { userService.clearEmail(function () {
siteService.clear(userId, function () { loginService.clear(userId, function () {
folderService.clear(userId, function () { folderService.clear(userId, function () {
$rootScope.vaultSites = null; $rootScope.vaultLogins = null;
$rootScope.vaultFolders = null; $rootScope.vaultFolders = null;
chrome.runtime.sendMessage({ command: 'loggedOut' }); chrome.runtime.sendMessage({ command: 'loggedOut' });
callback(); callback();

View File

@ -16,8 +16,8 @@
.factory('folderService', function () { .factory('folderService', function () {
return chrome.extension.getBackgroundPage().folderService; return chrome.extension.getBackgroundPage().folderService;
}) })
.factory('siteService', function () { .factory('loginService', function () {
return chrome.extension.getBackgroundPage().siteService; return chrome.extension.getBackgroundPage().loginService;
}) })
.factory('syncService', function () { .factory('syncService', function () {
return chrome.extension.getBackgroundPage().syncService; return chrome.extension.getBackgroundPage().syncService;

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.settings') .module('bit.settings')
.controller('settingsController', function ($scope, loginService, $state, SweetAlert, utilsService, $analytics, .controller('settingsController', function ($scope, authService, $state, SweetAlert, utilsService, $analytics,
i18nService, constantsService, cryptoService) { i18nService, constantsService, cryptoService) {
utilsService.initListSectionItemListeners($(document), angular); utilsService.initListSectionItemListeners($(document), angular);
$scope.lockOption = ''; $scope.lockOption = '';
@ -38,7 +38,7 @@
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
cryptoService.toggleKey(function () { }); cryptoService.toggleKey(function () { });
loginService.logOut(function () { authService.logOut(function () {
$analytics.eventTrack('Logged Out'); $analytics.eventTrack('Logged Out');
$state.go('home'); $state.go('home');
}); });
@ -58,7 +58,7 @@
cancelButtonText: i18nService.cancel cancelButtonText: i18nService.cancel
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
loginService.logOut(function () { authService.logOut(function () {
$analytics.eventTrack('Logged Out'); $analytics.eventTrack('Logged Out');
$state.go('home'); $state.go('home');
}); });

View File

@ -4,7 +4,7 @@
.controller('settingsFeaturesController', function ($scope, i18nService, $analytics, constantsService) { .controller('settingsFeaturesController', function ($scope, i18nService, $analytics, constantsService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
$scope.disableGa = false; $scope.disableGa = false;
$scope.disableAddSiteNotification = false; $scope.disableAddLoginNotification = false;
chrome.storage.local.get(constantsService.disableGaKey, function (obj) { chrome.storage.local.get(constantsService.disableGaKey, function (obj) {
if (obj && obj[constantsService.disableGaKey]) { if (obj && obj[constantsService.disableGaKey]) {
@ -15,12 +15,12 @@
} }
}); });
chrome.storage.local.get(constantsService.disableAddSiteNotificationKey, function (obj) { chrome.storage.local.get(constantsService.disableAddLoginNotificationKey, function (obj) {
if (obj && obj[constantsService.disableAddSiteNotificationKey]) { if (obj && obj[constantsService.disableAddLoginNotificationKey]) {
$scope.disableAddSiteNotification = true; $scope.disableAddLoginNotification = true;
} }
else { else {
$scope.disableAddSiteNotification = false; $scope.disableAddLoginNotification = false;
} }
}); });
@ -45,22 +45,22 @@
}); });
}; };
$scope.updateAddSiteNotification = function () { $scope.updateAddLoginNotification = function () {
chrome.storage.local.get(constantsService.disableAddSiteNotificationKey, function (obj) { chrome.storage.local.get(constantsService.disableAddLoginNotificationKey, function (obj) {
if (obj[constantsService.disableAddSiteNotificationKey]) { if (obj[constantsService.disableAddLoginNotificationKey]) {
// enable // enable
obj[constantsService.disableAddSiteNotificationKey] = false; obj[constantsService.disableAddLoginNotificationKey] = false;
} }
else { else {
// disable // disable
$analytics.eventTrack('Disabled Add Site Notification'); $analytics.eventTrack('Disabled Add Login Notification');
obj[constantsService.disableAddSiteNotificationKey] = true; obj[constantsService.disableAddLoginNotificationKey] = true;
} }
chrome.storage.local.set(obj, function () { chrome.storage.local.set(obj, function () {
$scope.disableAddSiteNotification = obj[constantsService.disableAddSiteNotificationKey]; $scope.disableAddLoginNotification = obj[constantsService.disableAddLoginNotificationKey];
if (!obj[constantsService.disableAddSiteNotificationKey]) { if (!obj[constantsService.disableAddLoginNotificationKey]) {
$analytics.eventTrack('Enabled Add Site Notification'); $analytics.eventTrack('Enabled Add Login Notification');
} }
}); });
}); });

View File

@ -20,13 +20,13 @@
<div class="list-section"> <div class="list-section">
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item list-section-item-checkbox"> <div class="list-section-item list-section-item-checkbox">
<label for="notification-bar">{{i18n.disableAddSiteNotification}}</label> <label for="notification-bar">{{i18n.disableAddLoginNotification}}</label>
<input id="notification-bar" type="checkbox" ng-model="disableAddSiteNotification" <input id="notification-bar" type="checkbox" ng-model="disableAddLoginNotification"
ng-change="updateAddSiteNotification()"> ng-change="updateAddLoginNotification()">
</div> </div>
</div> </div>
<div class="list-section-footer"> <div class="list-section-footer">
{{i18n.addSiteNotificationDesc}} {{i18n.addLoginNotificationDesc}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -80,10 +80,10 @@
$analytics.eventTrack('Selected Generated Password'); $analytics.eventTrack('Selected Generated Password');
if (addState) { if (addState) {
addState.site.password = $scope.password; addState.login.password = $scope.password;
} }
else if (editState) { else if (editState) {
editState.site.password = $scope.password; editState.login.password = $scope.password;
} }
dismiss(); dismiss();
@ -91,18 +91,18 @@
function dismiss() { function dismiss() {
if (addState) { if (addState) {
$state.go('addSite', { $state.go('addLogin', {
animation: 'out-slide-down', animation: 'out-slide-down',
from: addState.from, from: addState.from,
site: addState.site login: addState.login
}); });
} }
else if (editState) { else if (editState) {
$state.go('editSite', { $state.go('editLogin', {
animation: 'out-slide-down', animation: 'out-slide-down',
site: editState.site, login: editState.login,
fromView: editState.fromView, fromView: editState.fromView,
siteId: editState.siteId, loginId: editState.loginId,
from: editState.from from: editState.from
}); });
} }

View File

@ -1,23 +1,23 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService, .controller('vaultAddLoginController', function ($scope, $state, $stateParams, loginService, folderService,
cryptoService, $q, toastr, utilsService, $analytics, i18nService) { cryptoService, $q, toastr, utilsService, $analytics, i18nService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
var from = $stateParams.from, var from = $stateParams.from,
folderId = $stateParams.folderId; folderId = $stateParams.folderId;
$scope.site = { $scope.login = {
folderId: folderId, folderId: folderId,
name: $stateParams.name, name: $stateParams.name,
uri: $stateParams.uri uri: $stateParams.uri
}; };
if ($stateParams.site) { if ($stateParams.login) {
angular.extend($scope.site, $stateParams.site); angular.extend($scope.login, $stateParams.login);
} }
if (!$stateParams.site && $scope.site.name && $scope.site.uri) { if (!$stateParams.login && $scope.login.name && $scope.login.uri) {
$('#username').focus(); $('#username').focus();
} }
else { else {
@ -36,11 +36,11 @@
return; return;
} }
$scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { $scope.savePromise = $q.when(loginService.encrypt(model)).then(function (loginModel) {
var site = new Site(siteModel, true); var login = new Login(loginModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) { return $q.when(loginService.saveWithServer(login)).then(function (login) {
$analytics.eventTrack('Added Site'); $analytics.eventTrack('Added Login');
toastr.success(i18nService.addedSite); toastr.success(i18nService.addedLogin);
$scope.close(); $scope.close();
}); });
}); });
@ -71,7 +71,7 @@
animation: 'in-slide-up', animation: 'in-slide-up',
addState: { addState: {
from: from, from: from,
site: $scope.site login: $scope.login
} }
}); });
}; };

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, $state, $stateParams, toastr, .controller('vaultController', function ($scope, $rootScope, loginService, folderService, $q, $state, $stateParams, toastr,
syncService, utilsService, $analytics, i18nService, stateService, $timeout) { syncService, utilsService, $analytics, i18nService, stateService, $timeout) {
var stateKey = 'vault', var stateKey = 'vault',
state = stateService.getState(stateKey) || {}; state = stateService.getState(stateKey) || {};
@ -20,8 +20,8 @@
var delayLoad = true; var delayLoad = true;
$scope.loaded = true; $scope.loaded = true;
if (!$rootScope.vaultSites) { if (!$rootScope.vaultLogins) {
$rootScope.vaultSites = []; $rootScope.vaultLogins = [];
delayLoad = false; delayLoad = false;
} }
if (!$rootScope.vaultFolders) { if (!$rootScope.vaultFolders) {
@ -40,7 +40,7 @@
function loadVault() { function loadVault() {
var decFolders = []; var decFolders = [];
var decSites = []; var decLogins = [];
var promises = []; var promises = [];
var folderPromise = $q.when(folderService.getAllDecrypted()); var folderPromise = $q.when(folderService.getAllDecrypted());
@ -49,16 +49,16 @@
}); });
promises.push(folderPromise); promises.push(folderPromise);
var sitePromise = $q.when(siteService.getAllDecrypted()); var loginPromise = $q.when(loginService.getAllDecrypted());
sitePromise.then(function (sites) { loginPromise.then(function (logins) {
decSites = sites; decLogins = logins;
}); });
promises.push(sitePromise); promises.push(loginPromise);
$q.all(promises).then(function () { $q.all(promises).then(function () {
$scope.loaded = true; $scope.loaded = true;
$rootScope.vaultFolders = decFolders; $rootScope.vaultFolders = decFolders;
$rootScope.vaultSites = decSites; $rootScope.vaultLogins = decLogins;
if (!delayLoad) { if (!delayLoad) {
setScrollY(); setScrollY();
@ -79,41 +79,41 @@
return item.name.toLowerCase(); return item.name.toLowerCase();
}; };
$scope.searchSites = function () { $scope.searchLogins = function () {
if (!$scope.searchText || $scope.searchText.length < 2) { if (!$scope.searchText || $scope.searchText.length < 2) {
return; return;
} }
return searchSite; return searchLogin;
}; };
function searchSite(site) { function searchLogin(login) {
var searchTerm = $scope.searchText.toLowerCase(); var searchTerm = $scope.searchText.toLowerCase();
if (site.name && site.name.toLowerCase().indexOf(searchTerm) !== -1) { if (login.name && login.name.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
if (site.username && site.username.toLowerCase().indexOf(searchTerm) !== -1) { if (login.username && login.username.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
if (site.uri && site.uri.toLowerCase().indexOf(searchTerm) !== -1) { if (login.uri && login.uri.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
return false; return false;
} }
$scope.addSite = function () { $scope.addLogin = function () {
storeState(); storeState();
$state.go('addSite', { $state.go('addLogin', {
animation: 'in-slide-up', animation: 'in-slide-up',
from: 'vault' from: 'vault'
}); });
}; };
$scope.viewSite = function (site) { $scope.viewLogin = function (login) {
storeState(); storeState();
$state.go('viewSite', { $state.go('viewLogin', {
siteId: site.id, loginId: login.id,
animation: 'in-slide-up', animation: 'in-slide-up',
from: 'vault' from: 'vault'
}); });

View File

@ -1,24 +1,24 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, .controller('vaultEditLoginController', function ($scope, $state, $stateParams, loginService, folderService,
cryptoService, $q, toastr, SweetAlert, utilsService, $analytics, i18nService) { cryptoService, $q, toastr, SweetAlert, utilsService, $analytics, i18nService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
var siteId = $stateParams.siteId; var loginId = $stateParams.loginId;
var fromView = $stateParams.fromView; var fromView = $stateParams.fromView;
var from = $stateParams.from; var from = $stateParams.from;
$scope.site = { $scope.login = {
folderId: null folderId: null
}; };
if ($stateParams.site) { if ($stateParams.login) {
angular.extend($scope.site, $stateParams.site); angular.extend($scope.login, $stateParams.login);
} }
else { else {
siteService.get(siteId, function (site) { loginService.get(loginId, function (login) {
$q.when(site.decrypt()).then(function (model) { $q.when(login.decrypt()).then(function (model) {
$scope.site = model; $scope.login = model;
}); });
}); });
} }
@ -36,11 +36,11 @@ angular
return; return;
} }
$scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { $scope.savePromise = $q.when(loginService.encrypt(model)).then(function (loginModel) {
var site = new Site(siteModel, true); var login = new Login(loginModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) { return $q.when(loginService.saveWithServer(login)).then(function (login) {
$analytics.eventTrack('Edited Site'); $analytics.eventTrack('Edited Login');
toastr.success(i18nService.editedSite); toastr.success(i18nService.editedLogin);
$scope.close(); $scope.close();
}); });
}); });
@ -48,16 +48,16 @@ angular
$scope.delete = function () { $scope.delete = function () {
SweetAlert.swal({ SweetAlert.swal({
title: i18nService.deleteSite, title: i18nService.deleteLogin,
text: i18nService.deleteSiteConfirmation, text: i18nService.deleteLoginConfirmation,
showCancelButton: true, showCancelButton: true,
confirmButtonText: i18nService.yes, confirmButtonText: i18nService.yes,
cancelButtonText: i18nService.no cancelButtonText: i18nService.no
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
$q.when(siteService.deleteWithServer(siteId)).then(function () { $q.when(loginService.deleteWithServer(loginId)).then(function () {
$analytics.eventTrack('Deleted Site'); $analytics.eventTrack('Deleted Login');
toastr.success(i18nService.deletedSite); toastr.success(i18nService.deletedLogin);
$state.go('tabs.vault', { $state.go('tabs.vault', {
animation: 'out-slide-down' animation: 'out-slide-down'
}); });
@ -68,8 +68,8 @@ angular
$scope.close = function () { $scope.close = function () {
if (fromView) { if (fromView) {
$state.go('viewSite', { $state.go('viewLogin', {
siteId: siteId, loginId: loginId,
animation: 'out-slide-down', animation: 'out-slide-down',
from: from from: from
}); });
@ -82,7 +82,7 @@ angular
}; };
$scope.generatePassword = function () { $scope.generatePassword = function () {
if ($scope.site.password) { if ($scope.login.password) {
SweetAlert.swal({ SweetAlert.swal({
title: i18nService.overwritePassword, title: i18nService.overwritePassword,
text: i18nService.overwritePasswordConfirmation, text: i18nService.overwritePasswordConfirmation,
@ -107,8 +107,8 @@ angular
animation: 'in-slide-up', animation: 'in-slide-up',
editState: { editState: {
fromView: fromView, fromView: fromView,
siteId: siteId, loginId: loginId,
site: $scope.site, login: $scope.login,
from: from from: from
} }
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultViewFolderController', function ($scope, siteService, folderService, $q, $state, $stateParams, toastr, .controller('vaultViewFolderController', function ($scope, loginService, folderService, $q, $state, $stateParams, toastr,
syncService, $analytics, i18nService, stateService) { syncService, $analytics, i18nService, stateService) {
var stateKey = 'viewFolder', var stateKey = 'viewFolder',
state = stateService.getState(stateKey) || {}; state = stateService.getState(stateKey) || {};
@ -10,7 +10,7 @@
var pageSize = 100, var pageSize = 100,
decFolder = null, decFolder = null,
decSites = []; decLogins = [];
$scope.folder = { $scope.folder = {
id: !state.folderId || state.folderId === '0' ? null : state.folderId, id: !state.folderId || state.folderId === '0' ? null : state.folderId,
@ -20,8 +20,8 @@
$('#search').focus(); $('#search').focus();
$scope.loaded = false; $scope.loaded = false;
$scope.vaultSites = []; $scope.vaultLogins = [];
$scope.pagedVaultSites = []; $scope.pagedVaultLogins = [];
$scope.searchText = null; $scope.searchText = null;
loadVault(); loadVault();
@ -39,15 +39,15 @@
promises.push(folderDeferred.promise); promises.push(folderDeferred.promise);
} }
var sitePromise = $q.when(siteService.getAllDecryptedForFolder($scope.folder.id)); var loginPromise = $q.when(loginService.getAllDecryptedForFolder($scope.folder.id));
sitePromise.then(function (sites) { loginPromise.then(function (logins) {
decSites = sites.sort(siteSort); decLogins = logins.sort(loginSort);
}); });
promises.push(sitePromise); promises.push(loginPromise);
$q.all(promises).then(function () { $q.all(promises).then(function () {
$scope.loaded = true; $scope.loaded = true;
$scope.vaultSites = decSites; $scope.vaultLogins = decLogins;
if (decFolder) { if (decFolder) {
$scope.folder.name = decFolder.name; $scope.folder.name = decFolder.name;
@ -55,14 +55,14 @@
if (state.searchText) { if (state.searchText) {
$scope.searchText = state.searchText; $scope.searchText = state.searchText;
$scope.searchSites(); $scope.searchLogins();
} }
setTimeout(setScrollY, 200); setTimeout(setScrollY, 200);
}); });
} }
function siteSort(a, b) { function loginSort(a, b) {
if (!a.name) { if (!a.name) {
return -1; return -1;
} }
@ -100,65 +100,65 @@
} }
$scope.loadMore = function () { $scope.loadMore = function () {
var pagedLength = $scope.pagedVaultSites.length; var pagedLength = $scope.pagedVaultLogins.length;
if ($scope.vaultSites.length > pagedLength) { if ($scope.vaultLogins.length > pagedLength) {
$scope.pagedVaultSites = $scope.pagedVaultLogins =
$scope.pagedVaultSites.concat($scope.vaultSites.slice(pagedLength, pagedLength + pageSize)); $scope.pagedVaultLogins.concat($scope.vaultLogins.slice(pagedLength, pagedLength + pageSize));
} }
}; };
$scope.searchSites = function () { $scope.searchLogins = function () {
if (!$scope.searchText || $scope.searchText.length < 2) { if (!$scope.searchText || $scope.searchText.length < 2) {
if ($scope.vaultSites.length !== decSites.length) { if ($scope.vaultLogins.length !== decLogins.length) {
resetList(decSites); resetList(decLogins);
} }
return; return;
} }
var matchedSites = []; var matchedLogins = [];
for (var i = 0; i < decSites.length; i++) { for (var i = 0; i < decLogins.length; i++) {
if (searchSite(decSites[i])) { if (searchLogin(decLogins[i])) {
matchedSites.push(decSites[i]); matchedLogins.push(decLogins[i]);
} }
} }
resetList(matchedSites); resetList(matchedLogins);
}; };
function resetList(sites) { function resetList(logins) {
$scope.vaultSites = sites; $scope.vaultLogins = logins;
$scope.pagedVaultSites = []; $scope.pagedVaultLogins = [];
$scope.loadMore(); $scope.loadMore();
} }
function searchSite(site) { function searchLogin(login) {
var searchTerm = $scope.searchText.toLowerCase(); var searchTerm = $scope.searchText.toLowerCase();
if (site.name && site.name.toLowerCase().indexOf(searchTerm) !== -1) { if (login.name && login.name.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
if (site.username && site.username.toLowerCase().indexOf(searchTerm) !== -1) { if (login.username && login.username.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
if (site.uri && site.uri.toLowerCase().indexOf(searchTerm) !== -1) { if (login.uri && login.uri.toLowerCase().indexOf(searchTerm) !== -1) {
return true; return true;
} }
return false; return false;
} }
$scope.addSite = function () { $scope.addLogin = function () {
storeState(); storeState();
$state.go('addSite', { $state.go('addLogin', {
animation: 'in-slide-up', animation: 'in-slide-up',
from: 'folder', from: 'folder',
folderId: $scope.folder.id folderId: $scope.folder.id
}); });
}; };
$scope.viewSite = function (site) { $scope.viewLogin = function (login) {
storeState(); storeState();
$state.go('viewSite', { $state.go('viewLogin', {
siteId: site.id, loginId: login.id,
animation: 'in-slide-up', animation: 'in-slide-up',
from: 'folder' from: 'folder'
}); });

View File

@ -1,19 +1,19 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, tldjs, toastr, $q, .controller('vaultViewLoginController', function ($scope, $state, $stateParams, loginService, tldjs, toastr, $q,
$analytics, i18nService) { $analytics, i18nService) {
$scope.i18n = i18nService; $scope.i18n = i18nService;
var from = $stateParams.from; var from = $stateParams.from;
$scope.site = null; $scope.login = null;
siteService.get($stateParams.siteId, function (site) { loginService.get($stateParams.loginId, function (login) {
if (!site) { if (!login) {
return; return;
} }
$q.when(site.decrypt()).then(function (model) { $q.when(login.decrypt()).then(function (model) {
$scope.site = model; $scope.login = model;
if (model.password) { if (model.password) {
var maskedPassword = ''; var maskedPassword = '';
@ -21,29 +21,29 @@ angular
maskedPassword += '•'; maskedPassword += '•';
} }
$scope.site.maskedPassword = maskedPassword; $scope.login.maskedPassword = maskedPassword;
} }
if (model.uri) { if (model.uri) {
$scope.site.showLaunch = model.uri.startsWith('http://') || model.uri.startsWith('https://'); $scope.login.showLaunch = model.uri.startsWith('http://') || model.uri.startsWith('https://');
var domain = tldjs.getDomain(model.uri); var domain = tldjs.getDomain(model.uri);
if (domain) { if (domain) {
$scope.site.website = domain; $scope.login.website = domain;
} }
else { else {
$scope.site.website = model.uri; $scope.login.website = model.uri;
} }
} }
else { else {
$scope.site.showLaunch = false; $scope.login.showLaunch = false;
} }
}); });
}); });
$scope.edit = function (site) { $scope.edit = function (login) {
$state.go('editSite', { $state.go('editLogin', {
animation: 'in-slide-up', animation: 'in-slide-up',
siteId: site.id, loginId: login.id,
fromView: true, fromView: true,
from: from from: from
}); });
@ -67,10 +67,10 @@ angular
} }
}; };
$scope.launchWebsite = function (site) { $scope.launchWebsite = function (login) {
if (site.showLaunch) { if (login.showLaunch) {
$analytics.eventTrack('Launched Website'); $analytics.eventTrack('Launched Website');
chrome.tabs.create({ url: site.uri }); chrome.tabs.create({ url: login.uri });
} }
}; };

View File

@ -1,6 +1,6 @@
<div class="header"> <div class="header">
<div class="right"> <div class="right">
<a href="" ng-click="addSite()"><i class="fa fa-plus fa-lg"></i></a> <a href="" ng-click="addLogin()"><i class="fa fa-plus fa-lg"></i></a>
</div> </div>
<div class="search"> <div class="search">
<input type="search" placeholder="{{i18n.searchVault}}" ng-model="searchText" id="search" /> <input type="search" placeholder="{{i18n.searchVault}}" ng-model="searchText" id="search" />
@ -8,7 +8,7 @@
</div> </div>
</div> </div>
<div class="content content-tabs"> <div class="content content-tabs">
<div ng-if="vaultSites.length && vaultSites.length >= 100 && vaultFolders.length && (!searchText || searchText.length < 2)"> <div ng-if="vaultLogins.length && vaultLogins.length >= 100 && vaultFolders.length && (!searchText || searchText.length < 2)">
<div class="list"> <div class="list">
<div class="list-section" style="padding-bottom: 0;"> <div class="list-section" style="padding-bottom: 0;">
<div class="list-section-header"> <div class="list-section-header">
@ -22,38 +22,38 @@
</div> </div>
</div> </div>
</div> </div>
<div ng-if="vaultSites.length && (vaultSites.length < 100 || (searchText && searchText.length >= 2))"> <div ng-if="vaultLogins.length && (vaultLogins.length < 100 || (searchText && searchText.length >= 2))">
<div class="list"> <div class="list">
<div class="list-grouped" ng-repeat="folder in vaultFolders | orderBy: folderSort" ng-show="vaultFolders.length"> <div class="list-grouped" ng-repeat="folder in vaultFolders | orderBy: folderSort" ng-show="vaultFolders.length">
<div ng-if="(vaultSites | filter: { folderId: folder.id } | filter: searchSites()).length"> <div ng-if="(vaultLogins | filter: { folderId: folder.id } | filter: searchLogins()).length">
<div class="list-grouped-header"> <div class="list-grouped-header">
<i class="fa fa-folder-open"></i> {{folder.name}} <i class="fa fa-folder-open"></i> {{folder.name}}
</div> </div>
<a href="javascript:void(0)" ng-click="viewSite(site)" <a href="javascript:void(0)" ng-click="viewLogin(login)"
class="list-grouped-item condensed" title="{{i18n.edit}} {{site.name}}" class="list-grouped-item condensed" title="{{i18n.edit}} {{login.name}}"
ng-repeat="site in vaultSites | filter: { folderId: folder.id } ng-repeat="login in vaultLogins | filter: { folderId: folder.id }
| filter: searchSites() | orderBy: ['name', 'username']"> | filter: searchLogins() | orderBy: ['name', 'username']">
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" ngclipboard <span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)" ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{site.password}}" ng-class="{'disabled': !site.password}"> data-clipboard-text="{{login.password}}" ng-class="{'disabled': !login.password}">
<i class="fa fa-lg fa-key"></i> <i class="fa fa-lg fa-key"></i>
</span> </span>
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" ngclipboard <span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)" ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{site.username}}" ng-class="{'disabled': !site.username}"> data-clipboard-text="{{login.username}}" ng-class="{'disabled': !login.username}">
<i class="fa fa-lg fa-user"></i> <i class="fa fa-lg fa-user"></i>
</span> </span>
<span class="text">{{site.name}}</span> <span class="text">{{login.name}}</span>
<span class="detail">{{site.username}}</span> <span class="detail">{{login.username}}</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="centered-message" ng-if="loaded && !vaultSites.length"> <div class="centered-message" ng-if="loaded && !vaultLogins.length">
<p> <p>
{{i18n.noSitesInList}} {{i18n.noLoginsInList}}
<button ng-click="addSite()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addSite}}</button> <button ng-click="addLogin()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addLogin}}</button>
</p> </p>
</div> </div>
<div class="page-loading" ng-if="!loaded"> <div class="page-loading" ng-if="!loaded">

View File

@ -1,4 +1,4 @@
<form name="theForm" ng-submit="save(site)" bit-form="savePromise"> <form name="theForm" ng-submit="save(login)" bit-form="savePromise">
<div class="header"> <div class="header">
<div class="left"> <div class="left">
<a ng-click="close()" href="">{{i18n.cancel}}</a> <a ng-click="close()" href="">{{i18n.cancel}}</a>
@ -7,30 +7,30 @@
<button type="submit" class="btn btn-link" ng-show="!theForm.$loading">{{i18n.save}}</button> <button type="submit" class="btn btn-link" ng-show="!theForm.$loading">{{i18n.save}}</button>
<i class="fa fa-spinner fa-lg" ng-show="theForm.$loading" ng-class="{'fa-spin' : theForm.$loading}"></i> <i class="fa fa-spinner fa-lg" ng-show="theForm.$loading" ng-class="{'fa-spin' : theForm.$loading}"></i>
</div> </div>
<div class="title">{{i18n.addSite}}</div> <div class="title">{{i18n.addLogin}}</div>
</div> </div>
<div class="content"> <div class="content">
<div class="list"> <div class="list">
<div class="list-section"> <div class="list-section">
<div class="list-section-header"> <div class="list-section-header">
{{i18n.siteInformation}} {{i18n.loginInformation}}
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<label for="name" class="item-label">{{i18n.name}}</label> <label for="name" class="item-label">{{i18n.name}}</label>
<input id="name" type="text" name="Name" ng-model="site.name"> <input id="name" type="text" name="Name" ng-model="login.name">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="uri" class="item-label">{{i18n.uri}}</label> <label for="uri" class="item-label">{{i18n.uri}}</label>
<input id="uri" type="text" name="Uri" ng-model="site.uri"> <input id="uri" type="text" name="Uri" ng-model="login.uri">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="username" class="item-label">{{i18n.username}}</label> <label for="username" class="item-label">{{i18n.username}}</label>
<input id="username" type="text" name="Username" ng-model="site.username"> <input id="username" type="text" name="Username" ng-model="login.username">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="password" class="item-label">{{i18n.password}}</label> <label for="password" class="item-label">{{i18n.password}}</label>
<input id="password" type="password" name="Password" ng-model="site.password"> <input id="password" type="password" name="Password" ng-model="login.password">
</div> </div>
<a class="list-section-item" href="" ng-click="generatePassword()"> <a class="list-section-item" href="" ng-click="generatePassword()">
{{i18n.generatePassword}} {{i18n.generatePassword}}
@ -42,7 +42,7 @@
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<label for="folder" class="item-label">{{i18n.folder}}</label> <label for="folder" class="item-label">{{i18n.folder}}</label>
<select id="folder" name="FolderId" ng-model="site.folderId"> <select id="folder" name="FolderId" ng-model="login.folderId">
<option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}"> <option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}">
{{folder.name}} {{folder.name}}
</option> </option>
@ -50,7 +50,7 @@
</div> </div>
<div class="list-section-item list-section-item-checkbox"> <div class="list-section-item list-section-item-checkbox">
<label for="favorite">{{i18n.favorite}}</label> <label for="favorite">{{i18n.favorite}}</label>
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite"> <input id="favorite" name="Favorite" type="checkbox" ng-model="login.favorite">
</div> </div>
</div> </div>
</div> </div>
@ -60,7 +60,7 @@
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes"></textarea> <textarea id="notes" name="Notes" rows="5" ng-model="login.notes"></textarea>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<form name="theForm" ng-submit="save(site)" bit-form="savePromise"> <form name="theForm" ng-submit="save(login)" bit-form="savePromise">
<div class="header"> <div class="header">
<div class="left"> <div class="left">
<a ng-click="close()" href="">{{i18n.cancel}}</a> <a ng-click="close()" href="">{{i18n.cancel}}</a>
@ -7,30 +7,30 @@
<button type="submit" class="btn btn-link" ng-show="!theForm.$loading">{{i18n.save}}</button> <button type="submit" class="btn btn-link" ng-show="!theForm.$loading">{{i18n.save}}</button>
<i class="fa fa-spinner fa-lg" ng-show="theForm.$loading" ng-class="{'fa-spin' : theForm.$loading}"></i> <i class="fa fa-spinner fa-lg" ng-show="theForm.$loading" ng-class="{'fa-spin' : theForm.$loading}"></i>
</div> </div>
<div class="title">{{i18n.editSite}}</div> <div class="title">{{i18n.editLogin}}</div>
</div> </div>
<div class="content"> <div class="content">
<div class="list"> <div class="list">
<div class="list-section"> <div class="list-section">
<div class="list-section-header"> <div class="list-section-header">
{{i18n.siteInformation}} {{i18n.loginInformation}}
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<label for="name" class="item-label">{{i18n.name}}</label> <label for="name" class="item-label">{{i18n.name}}</label>
<input id="name" type="text" name="Name" ng-model="site.name"> <input id="name" type="text" name="Name" ng-model="login.name">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="uri" class="item-label">{{i18n.uri}}</label> <label for="uri" class="item-label">{{i18n.uri}}</label>
<input id="uri" type="text" name="Uri" ng-model="site.uri"> <input id="uri" type="text" name="Uri" ng-model="login.uri">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="username" class="item-label">{{i18n.username}}</label> <label for="username" class="item-label">{{i18n.username}}</label>
<input id="username" type="text" name="Username" ng-model="site.username"> <input id="username" type="text" name="Username" ng-model="login.username">
</div> </div>
<div class="list-section-item"> <div class="list-section-item">
<label for="password" class="item-label">{{i18n.password}}</label> <label for="password" class="item-label">{{i18n.password}}</label>
<input id="password" type="password" name="Password" ng-model="site.password"> <input id="password" type="password" name="Password" ng-model="login.password">
</div> </div>
<a class="list-section-item" href="" ng-click="generatePassword()"> <a class="list-section-item" href="" ng-click="generatePassword()">
{{i18n.generatePassword}} {{i18n.generatePassword}}
@ -42,7 +42,7 @@
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<label for="folder" class="item-label">{{i18n.folder}}</label> <label for="folder" class="item-label">{{i18n.folder}}</label>
<select id="folder" name="FolderId" ng-model="site.folderId"> <select id="folder" name="FolderId" ng-model="login.folderId">
<option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}"> <option ng-repeat="folder in folders | orderBy: ['name']" value="{{folder.id}}">
{{folder.name}} {{folder.name}}
</option> </option>
@ -50,7 +50,7 @@
</div> </div>
<div class="list-section-item list-section-item-checkbox"> <div class="list-section-item list-section-item-checkbox">
<label for="favorite">{{i18n.favorite}}</label> <label for="favorite">{{i18n.favorite}}</label>
<input id="favorite" name="Favorite" type="checkbox" ng-model="site.favorite"> <input id="favorite" name="Favorite" type="checkbox" ng-model="login.favorite">
</div> </div>
</div> </div>
</div> </div>
@ -60,14 +60,14 @@
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<textarea id="notes" name="Notes" rows="5" ng-model="site.notes"></textarea> <textarea id="notes" name="Notes" rows="5" ng-model="login.notes"></textarea>
</div> </div>
</div> </div>
</div> </div>
<div class="list-section"> <div class="list-section">
<div class="list-section-items"> <div class="list-section-items">
<a href="" ng-click="delete()" class="list-section-item text-danger"> <a href="" ng-click="delete()" class="list-section-item text-danger">
<i class="fa fa-trash fa-fw fa-lg"></i> {{i18n.deleteSite}} <i class="fa fa-trash fa-fw fa-lg"></i> {{i18n.deleteLogin}}
</a> </a>
</div> </div>
</div> </div>

View File

@ -3,44 +3,44 @@
<a ui-sref="tabs.vault({animation: 'out-slide-right'})"><i class="fa fa-chevron-left"></i> {{i18n.myVault}}</a> <a ui-sref="tabs.vault({animation: 'out-slide-right'})"><i class="fa fa-chevron-left"></i> {{i18n.myVault}}</a>
</div> </div>
<div class="search"> <div class="search">
<input type="search" placeholder="{{i18n.searchFolder}}" ng-model="searchText" ng-change="searchSites()" id="search" /> <input type="search" placeholder="{{i18n.searchFolder}}" ng-model="searchText" ng-change="searchLogins()" id="search" />
<i class="fa fa-search"></i> <i class="fa fa-search"></i>
</div> </div>
<div class="right"> <div class="right">
<a href="" ng-click="addSite()"><i class="fa fa-plus fa-lg"></i></a> <a href="" ng-click="addLogin()"><i class="fa fa-plus fa-lg"></i></a>
</div> </div>
</div> </div>
<div class="content"> <div class="content">
<div ng-if="vaultSites.length" infinite-scroll="loadMore()" infinite-scroll-distance="1" infinite-scroll-parent="true" <div ng-if="vaultLogins.length" infinite-scroll="loadMore()" infinite-scroll-distance="1" infinite-scroll-parent="true"
infinite-scroll-immediate-check="true"> infinite-scroll-immediate-check="true">
<div class="list"> <div class="list">
<div class="list-section" style="padding-bottom: 0;"> <div class="list-section" style="padding-bottom: 0;">
<div class="list-section-header"> <div class="list-section-header">
{{folder.name}} {{folder.name}}
</div> </div>
<a href="javascript:void(0)" ng-click="viewSite(site)" <a href="javascript:void(0)" ng-click="viewLogin(login)"
class="list-section-item condensed" title="{{i18n.edit}} {{site.name}}" class="list-section-item condensed" title="{{i18n.edit}} {{login.name}}"
ng-repeat="site in pagedVaultSites"> ng-repeat="login in pagedVaultLogins">
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" ngclipboard <span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)" ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{site.password}}" ng-class="{'disabled': !site.password}"> data-clipboard-text="{{login.password}}" ng-class="{'disabled': !login.password}">
<i class="fa fa-lg fa-key"></i> <i class="fa fa-lg fa-key"></i>
</span> </span>
<span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" ngclipboard <span class="btn-list" ng-click="$event.stopPropagation()" title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)" ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{site.username}}" ng-class="{'disabled': !site.username}"> data-clipboard-text="{{login.username}}" ng-class="{'disabled': !login.username}">
<i class="fa fa-lg fa-user"></i> <i class="fa fa-lg fa-user"></i>
</span> </span>
<span class="text">{{site.name}}</span> <span class="text">{{login.name}}</span>
<span class="detail">{{site.username}}</span> <span class="detail">{{login.username}}</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div class="centered-message" ng-if="loaded && !vaultSites.length"> <div class="centered-message" ng-if="loaded && !vaultLogins.length">
<p> <p>
{{i18n.noSitesInList}} {{i18n.noLoginsInList}}
<button ng-click="addSite()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addSite}}</button> <button ng-click="addLogin()" style="margin-top: 20px;" class="btn btn-link btn-block">{{i18n.addLogin}}</button>
</p> </p>
</div> </div>
<div class="page-loading" ng-if="!loaded"> <div class="page-loading" ng-if="!loaded">

View File

@ -3,38 +3,38 @@
<a href="" ng-click="close()">{{i18n.close}}</a> <a href="" ng-click="close()">{{i18n.close}}</a>
</div> </div>
<div class="right"> <div class="right">
<a href="" ng-click="edit(site)">{{i18n.edit}}</a> <a href="" ng-click="edit(login)">{{i18n.edit}}</a>
</div> </div>
<div class="title">{{i18n.viewSite}}</div> <div class="title">{{i18n.viewLogin}}</div>
</div> </div>
<div class="content"> <div class="content">
<div class="list list-no-selection"> <div class="list list-no-selection">
<div class="list-section"> <div class="list-section">
<div class="list-section-header"> <div class="list-section-header">
{{i18n.siteInformation}} {{i18n.loginInformation}}
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
<span class="item-label">{{i18n.name}}</span> <span class="item-label">{{i18n.name}}</span>
{{site.name}} {{login.name}}
</div> </div>
<div class="list-section-item" ng-if="site.uri"> <div class="list-section-item" ng-if="login.uri">
<a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(site)" <a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(site)"
ng-show="site.showLaunch"> ng-show="login.showLaunch">
<i class="fa fa-lg fa-share-square-o"></i> <i class="fa fa-lg fa-share-square-o"></i>
</a> </a>
<span class="item-label">{{i18n.website}}</span> <span class="item-label">{{i18n.website}}</span>
{{site.website}} {{site.website}}
</div> </div>
<div class="list-section-item" ng-if="site.username"> <div class="list-section-item" ng-if="login.username">
<a class="btn-list" href="" title="{{i18n.copyUsername}}" ngclipboard ngclipboard-error="clipboardError(e)" <a class="btn-list" href="" title="{{i18n.copyUsername}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)" data-clipboard-target="#username"> ngclipboard-success="clipboardSuccess(e, i18n.username)" data-clipboard-target="#username">
<i class="fa fa-lg fa-clipboard"></i> <i class="fa fa-lg fa-clipboard"></i>
</a> </a>
<span class="item-label">{{i18n.username}}</span> <span class="item-label">{{i18n.username}}</span>
<span id="username">{{site.username}}</span> <span id="username">{{login.username}}</span>
</div> </div>
<div class="list-section-item" ng-if="site.password"> <div class="list-section-item" ng-if="login.password">
<a class="btn-list" href="" title="{{i18n.copyPassword}}" ngclipboard ngclipboard-error="clipboardError(e)" <a class="btn-list" href="" title="{{i18n.copyPassword}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)" data-clipboard-target="#password"> ngclipboard-success="clipboardSuccess(e, i18n.password)" data-clipboard-target="#password">
<i class="fa fa-lg fa-clipboard"></i> <i class="fa fa-lg fa-clipboard"></i>
@ -43,18 +43,18 @@
<i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i> <i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i>
</a> </a>
<span class="item-label">{{i18n.password}}</span> <span class="item-label">{{i18n.password}}</span>
<span ng-show="!showPassword">{{site.maskedPassword}}</span> <span ng-show="!showPassword">{{login.maskedPassword}}</span>
<span id="password" ng-show="showPassword" class="monospaced">{{site.password}}</span> <span id="password" ng-show="showPassword" class="monospaced">{{login.password}}</span>
</div> </div>
</div> </div>
</div> </div>
<div class="list-section" ng-if="site.notes"> <div class="list-section" ng-if="login.notes">
<div class="list-section-header"> <div class="list-section-header">
{{i18n.notes}} {{i18n.notes}}
</div> </div>
<div class="list-section-items"> <div class="list-section-items">
<div class="list-section-item"> <div class="list-section-item">
{{site.notes}} {{login.notes}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -42,7 +42,7 @@
<script src="app/services/servicesModule.js"></script> <script src="app/services/servicesModule.js"></script>
<script src="app/services/backgroundService.js"></script> <script src="app/services/backgroundService.js"></script>
<script src="app/services/loginService.js"></script> <script src="app/services/authService.js"></script>
<script src="app/services/validationService.js"></script> <script src="app/services/validationService.js"></script>
<script src="app/services/stateService.js"></script> <script src="app/services/stateService.js"></script>
@ -64,9 +64,9 @@
<script src="app/vault/vaultModule.js"></script> <script src="app/vault/vaultModule.js"></script>
<script src="app/vault/vaultController.js"></script> <script src="app/vault/vaultController.js"></script>
<script src="app/vault/vaultViewFolderController.js"></script> <script src="app/vault/vaultViewFolderController.js"></script>
<script src="app/vault/vaultAddSiteController.js"></script> <script src="app/vault/vaultAddLoginController.js"></script>
<script src="app/vault/vaultEditSiteController.js"></script> <script src="app/vault/vaultEditLoginController.js"></script>
<script src="app/vault/vaultViewSiteController.js"></script> <script src="app/vault/vaultViewLoginController.js"></script>
<script src="app/settings/settingsModule.js"></script> <script src="app/settings/settingsModule.js"></script>
<script src="app/settings/settingsController.js"></script> <script src="app/settings/settingsController.js"></script>

View File

@ -97,9 +97,9 @@ function initApiService() {
}); });
}; };
// Site APIs // Login APIs
ApiService.prototype.getSite = function (id, success, error) { ApiService.prototype.getLogin = function (id, success, error) {
var self = this; var self = this;
this.tokenService.getToken(function (token) { this.tokenService.getToken(function (token) {
$.ajax({ $.ajax({
@ -107,7 +107,7 @@ function initApiService() {
url: self.baseUrl + '/sites/' + id + '?access_token=' + token, url: self.baseUrl + '/sites/' + id + '?access_token=' + token,
dataType: 'json', dataType: 'json',
success: function (response) { success: function (response) {
success(new SiteResponse(response)); success(new LoginResponse(response));
}, },
error: function (jqXHR, textStatus, errorThrown) { error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, textStatus, errorThrown); handleError(error, jqXHR, textStatus, errorThrown);
@ -116,17 +116,17 @@ function initApiService() {
}); });
}; };
ApiService.prototype.postSite = function (siteRequest, success, error) { ApiService.prototype.postLogin = function (loginRequest, success, error) {
var self = this; var self = this;
this.tokenService.getToken(function (token) { this.tokenService.getToken(function (token) {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: self.baseUrl + '/sites?access_token=' + token, url: self.baseUrl + '/sites?access_token=' + token,
data: JSON.stringify(siteRequest), data: JSON.stringify(loginRequest),
contentType: 'application/json; charset=utf-8', contentType: 'application/json; charset=utf-8',
dataType: 'json', dataType: 'json',
success: function (response) { success: function (response) {
success(new SiteResponse(response)); success(new LoginResponse(response));
}, },
error: function (jqXHR, textStatus, errorThrown) { error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, textStatus, errorThrown); handleError(error, jqXHR, textStatus, errorThrown);
@ -135,17 +135,17 @@ function initApiService() {
}); });
}; };
ApiService.prototype.putSite = function (id, siteRequest, success, error) { ApiService.prototype.putLogin = function (id, loginRequest, success, error) {
var self = this; var self = this;
this.tokenService.getToken(function (token) { this.tokenService.getToken(function (token) {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: self.baseUrl + '/sites/' + id + '?access_token=' + token, url: self.baseUrl + '/sites/' + id + '?access_token=' + token,
data: JSON.stringify(siteRequest), data: JSON.stringify(loginRequest),
contentType: 'application/json; charset=utf-8', contentType: 'application/json; charset=utf-8',
dataType: 'json', dataType: 'json',
success: function (response) { success: function (response) {
success(new SiteResponse(response)); success(new LoginResponse(response));
}, },
error: function (jqXHR, textStatus, errorThrown) { error: function (jqXHR, textStatus, errorThrown) {
handleError(error, jqXHR, textStatus, errorThrown); handleError(error, jqXHR, textStatus, errorThrown);

View File

@ -1,7 +1,7 @@
function ConstantsService() { function ConstantsService() {
return { return {
disableGaKey: 'disableGa', disableGaKey: 'disableGa',
disableAddSiteNotificationKey: 'disableAddSiteNotification', disableAddLoginNotificationKey: 'disableAddLoginNotification',
lockOptionKey: 'lockOption', lockOptionKey: 'lockOption',
lastActiveKey: 'lastActive' lastActiveKey: 'lastActive'
}; };

View File

@ -0,0 +1,302 @@
function LoginService(cryptoService, userService, apiService) {
this.cryptoService = cryptoService;
this.userService = userService;
this.apiService = apiService;
this.decryptedLoginCache = null;
initLoginService();
};
function initLoginService() {
LoginService.prototype.clearCache = function () {
this.decryptedLoginCache = null
};
LoginService.prototype.encrypt = function (login) {
var model = {
id: login.id,
folderId: login.folderId,
favorite: login.favorite
};
return cryptoService.encrypt(login.name).then(function (cs) {
model.name = cs;
return cryptoService.encrypt(login.uri);
}).then(function (cs) {
model.uri = cs;
return cryptoService.encrypt(login.username);
}).then(function (cs) {
model.username = cs;
return cryptoService.encrypt(login.password);
}).then(function (cs) {
model.password = cs;
return cryptoService.encrypt(login.notes);
}).then(function (cs) {
model.notes = cs;
return model;
});
};
LoginService.prototype.get = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
this.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (logins && id in logins) {
callback(new Login(logins[id]));
return;
}
callback(null);
});
});
};
LoginService.prototype.getAll = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
this.userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
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]));
}
callback(response);
});
});
};
LoginService.prototype.getAllDecrypted = function () {
var deferred = Q.defer();
var self = this;
cryptoService.getKey(false, function (key) {
if (!key) {
deferred.reject();
return;
}
if (self.decryptedLoginCache) {
deferred.resolve(self.decryptedLoginCache);
return;
}
var promises = [];
var decLogins = [];
self.getAll(function (logins) {
for (var i = 0; i < logins.length; i++) {
promises.push(logins[i].decrypt().then(function (login) {
decLogins.push(login);
}));
}
Q.all(promises).then(function () {
self.decryptedLoginCache = decLogins;
deferred.resolve(self.decryptedLoginCache);
});
});
});
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 loginsToReturn;
});
};
LoginService.prototype.getAllDecryptedForDomain = function (domain) {
var self = this;
return self.getAllDecrypted().then(function (logins) {
var loginsToReturn = [];
for (var i = 0; i < logins.length; i++) {
if (logins[i].domain === domain) {
loginsToReturn.push(logins[i]);
}
}
return loginsToReturn;
});
};
LoginService.prototype.saveWithServer = function (login) {
var deferred = Q.defer();
var self = this,
request = new LoginRequest(login);
if (!login.id) {
self.apiService.postLogin(request, apiSuccess, function (response) {
handleError(response, deferred)
});
}
else {
self.apiService.putLogin(login.id, request, apiSuccess, function (response) {
handleError(response, deferred)
});
}
function apiSuccess(response) {
login.id = response.id;
userService.getUserId(function (userId) {
var data = new LoginData(response, userId);
self.upsert(data, function () {
deferred.resolve(login);
});
});
}
return deferred.promise;
};
LoginService.prototype.upsert = function (login, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
userService.getUserId(function (userId) {
var loginsKey = 'sites_' + userId;
chrome.storage.local.get(loginsKey, function (obj) {
var logins = obj[loginsKey];
if (!logins) {
logins = {};
}
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();
});
});
});
};
LoginService.prototype.replace = function (logins, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
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;
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();
});
});
});
};
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 deferred.promise;
};
function handleError(error, deferred) {
deferred.reject(error);
}
};

View File

@ -1,302 +0,0 @@
function SiteService(cryptoService, userService, apiService) {
this.cryptoService = cryptoService;
this.userService = userService;
this.apiService = apiService;
this.decryptedSiteCache = null;
initSiteService();
};
function initSiteService() {
SiteService.prototype.clearCache = function () {
this.decryptedSiteCache = null
};
SiteService.prototype.encrypt = function (site) {
var model = {
id: site.id,
folderId: site.folderId,
favorite: site.favorite
};
return cryptoService.encrypt(site.name).then(function (cs) {
model.name = cs;
return cryptoService.encrypt(site.uri);
}).then(function (cs) {
model.uri = cs;
return cryptoService.encrypt(site.username);
}).then(function (cs) {
model.username = cs;
return cryptoService.encrypt(site.password);
}).then(function (cs) {
model.password = cs;
return cryptoService.encrypt(site.notes);
}).then(function (cs) {
model.notes = cs;
return model;
});
};
SiteService.prototype.get = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
this.userService.getUserId(function (userId) {
var sitesKey = 'sites_' + userId;
chrome.storage.local.get(sitesKey, function (obj) {
var sites = obj[sitesKey];
if (sites && id in sites) {
callback(new Site(sites[id]));
return;
}
callback(null);
});
});
};
SiteService.prototype.getAll = function (callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
this.userService.getUserId(function (userId) {
var sitesKey = 'sites_' + userId;
chrome.storage.local.get(sitesKey, function (obj) {
var sites = obj[sitesKey];
var response = [];
for (var id in sites) {
if (!id) {
continue;
}
response.push(new Site(sites[id]));
}
callback(response);
});
});
};
SiteService.prototype.getAllDecrypted = function () {
var deferred = Q.defer();
var self = this;
cryptoService.getKey(false, function (key) {
if (!key) {
deferred.reject();
return;
}
if (self.decryptedSiteCache) {
deferred.resolve(self.decryptedSiteCache);
return;
}
var promises = [];
var decSites = [];
self.getAll(function (sites) {
for (var i = 0; i < sites.length; i++) {
promises.push(sites[i].decrypt().then(function (site) {
decSites.push(site);
}));
}
Q.all(promises).then(function () {
self.decryptedSiteCache = decSites;
deferred.resolve(self.decryptedSiteCache);
});
});
});
return deferred.promise;
};
SiteService.prototype.getAllDecryptedForFolder = function (folderId) {
var self = this;
return self.getAllDecrypted().then(function (sites) {
var sitesToReturn = [];
for (var i = 0; i < sites.length; i++) {
if (sites[i].folderId === folderId) {
sitesToReturn.push(sites[i]);
}
}
return sitesToReturn;
});
};
SiteService.prototype.getAllDecryptedForDomain = function (domain) {
var self = this;
return self.getAllDecrypted().then(function (sites) {
var sitesToReturn = [];
for (var i = 0; i < sites.length; i++) {
if (sites[i].domain === domain) {
sitesToReturn.push(sites[i]);
}
}
return sitesToReturn;
});
};
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, deferred)
});
}
else {
self.apiService.putSite(site.id, request, apiSuccess, function (response) {
handleError(response, deferred)
});
}
function apiSuccess(response) {
site.id = response.id;
userService.getUserId(function (userId) {
var data = new SiteData(response, userId);
self.upsert(data, function () {
deferred.resolve(site);
});
});
}
return deferred.promise;
};
SiteService.prototype.upsert = function (site, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
userService.getUserId(function (userId) {
var sitesKey = 'sites_' + userId;
chrome.storage.local.get(sitesKey, function (obj) {
var sites = obj[sitesKey];
if (!sites) {
sites = {};
}
if (site.constructor === Array) {
for (var i = 0; i < site.length; i++) {
sites[site[i].id] = site[i];
}
}
else {
sites[site.id] = site;
}
obj[sitesKey] = sites;
chrome.storage.local.set(obj, function () {
self.decryptedSiteCache = null;
callback();
});
});
});
};
SiteService.prototype.replace = function (sites, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
userService.getUserId(function (userId) {
var obj = {};
obj['sites_' + userId] = sites;
chrome.storage.local.set(obj, function () {
self.decryptedSiteCache = null;
callback();
});
});
};
SiteService.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.decryptedSiteCache = null;
callback();
});
};
SiteService.prototype.delete = function (id, callback) {
if (!callback || typeof callback !== 'function') {
throw 'callback function required';
}
var self = this;
userService.getUserId(function (userId) {
var sitesKey = 'sites_' + userId;
chrome.storage.local.get(sitesKey, function (obj) {
var sites = obj[sitesKey];
if (!sites) {
callback();
return;
}
if (id.constructor === Array) {
for (var i = 0; i < id.length; i++) {
if (id[i] in sites) {
delete sites[id[i]];
}
}
}
else if (id in sites) {
delete sites[id];
}
else {
callback();
return;
}
obj[sitesKey] = sites;
chrome.storage.local.set(obj, function () {
self.decryptedSiteCache = null;
callback();
});
});
});
};
SiteService.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 deferred.promise;
};
function handleError(error, deferred) {
deferred.reject(error);
}
};

View File

@ -1,5 +1,5 @@
function SyncService(siteService, folderService, userService, apiService) { function SyncService(loginService, folderService, userService, apiService) {
this.siteService = siteService; this.loginService = loginService;
this.folderService = folderService; this.folderService = folderService;
this.userService = userService; this.userService = userService;
this.apiService = apiService; this.apiService = apiService;
@ -27,13 +27,13 @@ function initSyncService() {
self.userService.getUserId(function (userId) { self.userService.getUserId(function (userId) {
var now = new Date(); var now = new Date();
var ciphers = self.apiService.getCiphers(function (response) { var ciphers = self.apiService.getCiphers(function (response) {
var sites = {}; var logins = {};
var folders = {}; var folders = {};
for (var i = 0; i < response.data.length; i++) { for (var i = 0; i < response.data.length; i++) {
var data = response.data[i]; var data = response.data[i];
if (data.type === 1) { if (data.type === 1) {
sites[data.id] = new SiteData(data, userId); logins[data.id] = new LoginData(data, userId);
} }
else if (data.type === 0) { else if (data.type === 0) {
folders[data.id] = new FolderData(data, userId); folders[data.id] = new FolderData(data, userId);
@ -41,7 +41,7 @@ function initSyncService() {
} }
self.folderService.replace(folders, function () { self.folderService.replace(folders, function () {
self.siteService.replace(sites, function () { self.loginService.replace(logins, function () {
self.setLastSync(now, function () { self.setLastSync(now, function () {
self.syncCompleted(true); self.syncCompleted(true);
callback(true); callback(true);
@ -95,7 +95,7 @@ function initSyncService() {
}); });
} }
function syncSites(serverSites, callback) { function syncLogins(serverLogins, callback) {
var self = this; var self = this;
self.userService.isAuthenticated(function (isAuthenticated) { self.userService.isAuthenticated(function (isAuthenticated) {
@ -105,23 +105,23 @@ function initSyncService() {
} }
self.userService.getUserId(function (userId) { self.userService.getUserId(function (userId) {
self.siteService.getAll(function (sites) { self.loginService.getAll(function (logins) {
var localSites = {}; var localLogins = {};
for (var i = 0; i < sites.length; i++) { for (var i = 0; i < logins.length; i++) {
localSites[sites[i].id] = sites[i]; localLogins[logins[i].id] = logins[i];
} }
var data = []; var data = [];
for (var j = 0; j < serverSites.length; j++) { for (var j = 0; j < serverLogins.length; j++) {
var serverSite = serverSites[j]; var serverLogin = serverLogins[j];
var existingLocalSite = localSites[serverSite.id]; var existingLocalLogin = localLogins[serverLogin.id];
if (!existingLocalSite || existingLocalSite.RevisionDate !== serverSite.RevisionDate) { if (!existingLocalLogin || existingLocalLogin.RevisionDate !== serverLogin.RevisionDate) {
data.push(new SiteData(serverSite, userId)); data.push(new LoginData(serverLogin, userId));
} }
} }
self.siteService.upsert(data, function () { self.loginService.upsert(data, function () {
callback(); callback();
}); });
}); });