diff --git a/src/Web/gulpfile.js b/src/Web/gulpfile.js
index 1ce68a2e..48e95ef1 100644
--- a/src/Web/gulpfile.js
+++ b/src/Web/gulpfile.js
@@ -289,6 +289,7 @@ gulp.task('dist:js:lib', function () {
.src([
paths.libDir + 'sjcl/sjcl.js',
paths.libDir + 'sjcl/*.js',
+ paths.libDir + 'angulartics/angulartics.js',
paths.libDir + '**/*.js',
'!' + paths.libDir + '**/*.min.js',
'!' + paths.libDir + 'angular/**/*',
diff --git a/src/Web/wwwroot/_references.js b/src/Web/wwwroot/_references.js
index f6998200..6c5d79bc 100644
--- a/src/Web/wwwroot/_references.js
+++ b/src/Web/wwwroot/_references.js
@@ -47,3 +47,24 @@
///
///
///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
diff --git a/src/Web/wwwroot/app/accounts/accountsLoginController.js b/src/Web/wwwroot/app/accounts/accountsLoginController.js
index 01a1883f..1e4ed236 100644
--- a/src/Web/wwwroot/app/accounts/accountsLoginController.js
+++ b/src/Web/wwwroot/app/accounts/accountsLoginController.js
@@ -1,7 +1,7 @@
angular
.module('bit.accounts')
- .controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService, $state, appSettings) {
+ .controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService, $state, appSettings, $analytics) {
var rememberedEmail = $cookies.get(appSettings.rememberdEmailCookieName);
if (rememberedEmail) {
$scope.model = {
@@ -29,9 +29,11 @@ angular
var profile = authService.getUserProfile();
if (profile.twoFactor) {
+ $analytics.eventTrack('Logged In To Two-step');
$state.go('frontend.login.twoFactor');
}
else {
+ $analytics.eventTrack('Logged In');
$state.go('backend.vault');
}
});
@@ -42,6 +44,7 @@ angular
$scope.twoFactorPromise = authService.logInTwoFactor(model.code, "Authenticator");
$scope.twoFactorPromise.then(function () {
+ $analytics.eventTrack('Logged In From Two-step');
$state.go('backend.vault');
});
};
diff --git a/src/Web/wwwroot/app/accounts/accountsLogoutController.js b/src/Web/wwwroot/app/accounts/accountsLogoutController.js
index ff513bd4..418e9689 100644
--- a/src/Web/wwwroot/app/accounts/accountsLogoutController.js
+++ b/src/Web/wwwroot/app/accounts/accountsLogoutController.js
@@ -1,7 +1,8 @@
angular
.module('bit.accounts')
- .controller('accountsLogoutController', function ($scope, authService, $state) {
+ .controller('accountsLogoutController', function ($scope, authService, $state, $analytics) {
authService.logOut();
+ $analytics.eventTrack('Logged Out');
$state.go('frontend.login.info');
});
diff --git a/src/Web/wwwroot/app/accounts/accountsRegisterController.js b/src/Web/wwwroot/app/accounts/accountsRegisterController.js
index 3dd71776..dd48a964 100644
--- a/src/Web/wwwroot/app/accounts/accountsRegisterController.js
+++ b/src/Web/wwwroot/app/accounts/accountsRegisterController.js
@@ -1,7 +1,7 @@
angular
.module('bit.accounts')
- .controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService) {
+ .controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService, $analytics) {
var params = $location.search();
$scope.success = false;
@@ -11,7 +11,7 @@ angular
$scope.registerPromise = null;
$scope.register = function (form) {
- if ($scope.model.masterPassword != $scope.model.confirmMasterPassword) {
+ if ($scope.model.masterPassword !== $scope.model.confirmMasterPassword) {
validationService.addError(form, 'ConfirmMasterPassword', 'Master password confirmation does not match.', true);
return;
}
@@ -26,6 +26,7 @@ angular
$scope.registerPromise = apiService.accounts.register(request, function () {
$scope.success = true;
+ $analytics.eventTrack('Registered');
}).$promise;
};
});
diff --git a/src/Web/wwwroot/app/directives/masterPasswordDirective.js b/src/Web/wwwroot/app/directives/masterPasswordDirective.js
index 7c5eb8fe..271a9108 100644
--- a/src/Web/wwwroot/app/directives/masterPasswordDirective.js
+++ b/src/Web/wwwroot/app/directives/masterPasswordDirective.js
@@ -18,7 +18,7 @@ angular
}
var key = cryptoService.makeKey(value, profile.email, true);
- var valid = key == cryptoService.getKey(true);
+ var valid = key === cryptoService.getKey(true);
ngModel.$setValidity('masterPassword', valid);
return valid ? value : undefined;
});
@@ -30,7 +30,7 @@ angular
}
var key = cryptoService.makeKey(value, profile.email, true);
- var valid = key == cryptoService.getKey(true);
+ var valid = key === cryptoService.getKey(true);
ngModel.$setValidity('masterPassword', valid);
return value;
diff --git a/src/Web/wwwroot/app/settings/settingsChangeEmailController.js b/src/Web/wwwroot/app/settings/settingsChangeEmailController.js
index eefb1d7e..1ce1bba5 100644
--- a/src/Web/wwwroot/app/settings/settingsChangeEmailController.js
+++ b/src/Web/wwwroot/app/settings/settingsChangeEmailController.js
@@ -1,7 +1,8 @@
angular
.module('bit.settings')
- .controller('settingsChangeEmailController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, authService, $q, toastr) {
+ .controller('settingsChangeEmailController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, authService, $q, toastr, $analytics) {
+ $analytics.eventTrack('settingsChangeEmailController', { category: 'Modal' });
var _masterPasswordHash,
_newMasterPasswordHash,
_newKey;
@@ -48,6 +49,7 @@
$scope.confirmPromise = apiService.accounts.email(request, function () {
$uibModalInstance.dismiss('cancel');
+ $analytics.eventTrack('Changed Email');
authService.logOut();
$state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'Email Changed');
diff --git a/src/Web/wwwroot/app/settings/settingsChangePasswordController.js b/src/Web/wwwroot/app/settings/settingsChangePasswordController.js
index f00519dd..82676442 100644
--- a/src/Web/wwwroot/app/settings/settingsChangePasswordController.js
+++ b/src/Web/wwwroot/app/settings/settingsChangePasswordController.js
@@ -2,9 +2,10 @@
.module('bit.settings')
.controller('settingsChangePasswordController', function ($scope, $state, apiService, $uibModalInstance,
- cryptoService, authService, cipherService, validationService, $q, toastr) {
+ cryptoService, authService, cipherService, validationService, $q, toastr, $analytics) {
+ $analytics.eventTrack('settingsChangePasswordController', { category: 'Modal' });
$scope.save = function (model, form) {
- if ($scope.model.newMasterPassword != $scope.model.confirmNewMasterPassword) {
+ if ($scope.model.newMasterPassword !== $scope.model.confirmNewMasterPassword) {
validationService.addError(form, 'ConfirmNewMasterPassword', 'New master password confirmation does not match.', true);
return;
}
@@ -36,6 +37,7 @@
$scope.savePromise = apiService.accounts.putPassword(request, function () {
$uibModalInstance.dismiss('cancel');
authService.logOut();
+ $analytics.eventTrack('Changed Password');
$state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'Master Password Changed');
});
diff --git a/src/Web/wwwroot/app/settings/settingsDeleteController.js b/src/Web/wwwroot/app/settings/settingsDeleteController.js
index cc10a7d7..0e80a1bf 100644
--- a/src/Web/wwwroot/app/settings/settingsDeleteController.js
+++ b/src/Web/wwwroot/app/settings/settingsDeleteController.js
@@ -1,7 +1,8 @@
angular
.module('bit.settings')
- .controller('settingsDeleteController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, authService, toastr) {
+ .controller('settingsDeleteController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, authService, toastr, $analytics) {
+ $analytics.eventTrack('settingsDeleteController', { category: 'Modal' });
$scope.submit = function (model) {
var request = {
masterPasswordHash: cryptoService.hashPassword(model.masterPassword)
@@ -10,6 +11,7 @@
$scope.submitPromise = apiService.accounts.postDelete(request, function () {
$uibModalInstance.dismiss('cancel');
authService.logOut();
+ $analytics.eventTrack('Deleted Account');
$state.go('frontend.login.info').then(function () {
toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted');
});
diff --git a/src/Web/wwwroot/app/settings/settingsSessionsController.js b/src/Web/wwwroot/app/settings/settingsSessionsController.js
index c649c914..27c69e78 100644
--- a/src/Web/wwwroot/app/settings/settingsSessionsController.js
+++ b/src/Web/wwwroot/app/settings/settingsSessionsController.js
@@ -1,7 +1,8 @@
angular
.module('bit.settings')
- .controller('settingsSessionsController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, authService, toastr) {
+ .controller('settingsSessionsController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, authService, toastr, $analytics) {
+ $analytics.eventTrack('settingsSessionsController', { category: 'Modal' });
$scope.submit = function (model) {
var request = {
masterPasswordHash: cryptoService.hashPassword(model.masterPassword)
@@ -10,6 +11,7 @@
$scope.submitPromise = apiService.accounts.putSecurityStamp(request, function () {
$uibModalInstance.dismiss('cancel');
authService.logOut();
+ $analytics.eventTrack('Deauthorized Sessions');
$state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'All Sessions Deauthorized');
});
diff --git a/src/Web/wwwroot/app/settings/settingsTwoFactorController.js b/src/Web/wwwroot/app/settings/settingsTwoFactorController.js
index b76da478..1422b7ed 100644
--- a/src/Web/wwwroot/app/settings/settingsTwoFactorController.js
+++ b/src/Web/wwwroot/app/settings/settingsTwoFactorController.js
@@ -1,7 +1,8 @@
angular
.module('bit.settings')
- .controller('settingsTwoFactorController', function ($scope, apiService, $uibModalInstance, cryptoService, authService, $q, toastr) {
+ .controller('settingsTwoFactorController', function ($scope, apiService, $uibModalInstance, cryptoService, authService, $q, toastr, $analytics) {
+ $analytics.eventTrack('settingsTwoFactorController', { category: 'Modal' });
var _issuer = 'bitwarden',
_profile = authService.getUserProfile(),
_masterPasswordHash;
@@ -39,15 +40,17 @@
var request = {
enabled: !currentlyEnabled,
token: model ? model.token : null,
- masterPasswordHash: _masterPasswordHash,
+ masterPasswordHash: _masterPasswordHash
};
$scope.updatePromise = apiService.accounts.putTwoFactor({}, request, function (response) {
if (response.TwoFactorEnabled) {
+ $analytics.eventTrack('Enabled Two-step Login');
toastr.success('Two-step login has been enabled.');
if (_profile.extended) _profile.extended.twoFactorEnabled = true;
}
else {
+ $analytics.eventTrack('Disabled Two-step Login');
toastr.success('Two-step login has been disabled.');
if (_profile.extended) _profile.extended.twoFactorEnabled = false;
}
diff --git a/src/Web/wwwroot/app/tools/toolsAuditsController.js b/src/Web/wwwroot/app/tools/toolsAuditsController.js
index 0cbafe91..5e0eb679 100644
--- a/src/Web/wwwroot/app/tools/toolsAuditsController.js
+++ b/src/Web/wwwroot/app/tools/toolsAuditsController.js
@@ -1,7 +1,8 @@
angular
.module('bit.tools')
- .controller('toolsAuditsController', function ($scope, apiService, $uibModalInstance, toastr) {
+ .controller('toolsAuditsController', function ($scope, apiService, $uibModalInstance, toastr, $analytics) {
+ $analytics.eventTrack('toolsAuditsController', { category: 'Modal' });
$scope.close = function () {
$uibModalInstance.dismiss('cancel');
};
diff --git a/src/Web/wwwroot/app/tools/toolsExportController.js b/src/Web/wwwroot/app/tools/toolsExportController.js
index e285b00e..697ee3f4 100644
--- a/src/Web/wwwroot/app/tools/toolsExportController.js
+++ b/src/Web/wwwroot/app/tools/toolsExportController.js
@@ -1,7 +1,8 @@
angular
.module('bit.tools')
- .controller('toolsExportController', function ($scope, apiService, authService, $uibModalInstance, cryptoService, cipherService, $q, toastr) {
+ .controller('toolsExportController', function ($scope, apiService, authService, $uibModalInstance, cryptoService, cipherService, $q, toastr, $analytics) {
+ $analytics.eventTrack('toolsExportController', { category: 'Modal' });
$scope.export = function (model) {
$scope.startedExport = true;
apiService.sites.list({ expand: ['folder'] }, function (sites) {
@@ -36,6 +37,7 @@
document.body.removeChild(a);
}
+ $analytics.eventTrack('Exported Data');
toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!');
$scope.close();
}
@@ -56,7 +58,7 @@
function makeFileName() {
var now = new Date();
var dateString =
- now.getFullYear() + '' + padNumber((now.getMonth() + 1), 2) + '' + padNumber(now.getDate(), 2) +
+ now.getFullYear() + '' + padNumber(now.getMonth() + 1, 2) + '' + padNumber(now.getDate(), 2) +
padNumber(now.getHours(), 2) + '' + padNumber(now.getMinutes(), 2) +
padNumber(now.getSeconds(), 2);
diff --git a/src/Web/wwwroot/app/tools/toolsImportController.js b/src/Web/wwwroot/app/tools/toolsImportController.js
index 8adcfd57..8c0c3687 100644
--- a/src/Web/wwwroot/app/tools/toolsImportController.js
+++ b/src/Web/wwwroot/app/tools/toolsImportController.js
@@ -1,7 +1,8 @@
angular
.module('bit.tools')
- .controller('toolsImportController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, toastr, importService) {
+ .controller('toolsImportController', function ($scope, $state, apiService, $uibModalInstance, cryptoService, cipherService, toastr, importService, $analytics) {
+ $analytics.eventTrack('toolsImportController', { category: 'Modal' });
$scope.model = { source: 'local' };
$scope.import = function (model) {
@@ -18,6 +19,7 @@
}, function () {
$uibModalInstance.dismiss('cancel');
$state.go('backend.vault').then(function () {
+ $analytics.eventTrack('Imported Data', { label: model.source });
toastr.success('Data has been successfully imported into your vault.', 'Import Success');
});
}, importError);
diff --git a/src/Web/wwwroot/app/vault/vaultAddFolderController.js b/src/Web/wwwroot/app/vault/vaultAddFolderController.js
index 92fc9d3f..536407a4 100644
--- a/src/Web/wwwroot/app/vault/vaultAddFolderController.js
+++ b/src/Web/wwwroot/app/vault/vaultAddFolderController.js
@@ -1,11 +1,13 @@
angular
.module('bit.vault')
- .controller('vaultAddFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService) {
+ .controller('vaultAddFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, $analytics) {
+ $analytics.eventTrack('vaultAddFolderController', { category: 'Modal' });
$scope.savePromise = null;
$scope.save = function (model) {
var folder = cipherService.encryptFolder(model);
$scope.savePromise = apiService.folders.post(folder, function (response) {
+ $analytics.eventTrack('Created Folder');
var decFolder = cipherService.decryptFolder(response);
$uibModalInstance.close(decFolder);
}).$promise;
diff --git a/src/Web/wwwroot/app/vault/vaultAddSiteController.js b/src/Web/wwwroot/app/vault/vaultAddSiteController.js
index 93ea30f6..c88c30a7 100644
--- a/src/Web/wwwroot/app/vault/vaultAddSiteController.js
+++ b/src/Web/wwwroot/app/vault/vaultAddSiteController.js
@@ -1,7 +1,8 @@
angular
.module('bit.vault')
- .controller('vaultAddSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, folders, selectedFolder) {
+ .controller('vaultAddSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, folders, selectedFolder, $analytics) {
+ $analytics.eventTrack('vaultAddSiteController', { category: 'Modal' });
$scope.folders = folders;
$scope.site = {
folderId: selectedFolder ? selectedFolder.id : null
@@ -11,6 +12,7 @@
$scope.save = function (model) {
var site = cipherService.encryptSite(model);
$scope.savePromise = apiService.sites.post(site, function (siteResponse) {
+ $analytics.eventTrack('Created Site');
var decSite = cipherService.decryptSite(siteResponse);
$uibModalInstance.close(decSite);
}).$promise;
@@ -18,6 +20,7 @@
$scope.generatePassword = function () {
if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) {
+ $analytics.eventTrack('Generated Password From Add');
$scope.site.password = passwordService.generatePassword({ length: 10, special: true });
}
};
@@ -36,7 +39,7 @@
function selectPassword(e) {
var target = $(e.trigger).parent().prev();
- if (target.attr('type') == 'text') {
+ if (target.attr('type') === 'text') {
target.select();
}
}
diff --git a/src/Web/wwwroot/app/vault/vaultEditFolderController.js b/src/Web/wwwroot/app/vault/vaultEditFolderController.js
index e23bfb4a..438bfe43 100644
--- a/src/Web/wwwroot/app/vault/vaultEditFolderController.js
+++ b/src/Web/wwwroot/app/vault/vaultEditFolderController.js
@@ -1,7 +1,8 @@
angular
.module('bit.vault')
- .controller('vaultEditFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, folderId) {
+ .controller('vaultEditFolderController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, folderId, $analytics) {
+ $analytics.eventTrack('vaultEditFolderController', { category: 'Modal' });
$scope.folder = {};
apiService.folders.get({ id: folderId }, function (folder) {
@@ -12,6 +13,7 @@
$scope.save = function (model) {
var folder = cipherService.encryptFolder(model);
$scope.savePromise = apiService.folders.put({ id: folderId }, folder, function (response) {
+ $analytics.eventTrack('Edited Folder');
var decFolder = cipherService.decryptFolder(response);
$uibModalInstance.close(decFolder);
}).$promise;
diff --git a/src/Web/wwwroot/app/vault/vaultEditSiteController.js b/src/Web/wwwroot/app/vault/vaultEditSiteController.js
index 0fc210d1..aed9e756 100644
--- a/src/Web/wwwroot/app/vault/vaultEditSiteController.js
+++ b/src/Web/wwwroot/app/vault/vaultEditSiteController.js
@@ -1,7 +1,8 @@
angular
.module('bit.vault')
- .controller('vaultEditSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, siteId, folders) {
+ .controller('vaultEditSiteController', function ($scope, apiService, $uibModalInstance, cryptoService, cipherService, passwordService, siteId, folders, $analytics) {
+ $analytics.eventTrack('vaultEditSiteController', { category: 'Modal' });
$scope.folders = folders;
$scope.site = {};
@@ -12,6 +13,7 @@
$scope.save = function (model) {
var site = cipherService.encryptSite(model);
$scope.savePromise = apiService.sites.put({ id: siteId }, site, function (siteResponse) {
+ $analytics.eventTrack('Edited Site');
var decSite = cipherService.decryptSite(siteResponse);
$uibModalInstance.close(decSite);
}).$promise;
@@ -19,6 +21,7 @@
$scope.generatePassword = function () {
if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) {
+ $analytics.eventTrack('Generated Password From Edit');
$scope.site.password = passwordService.generatePassword({ length: 10, special: true });
}
};
@@ -37,7 +40,7 @@
function selectPassword(e) {
var target = $(e.trigger).parent().prev();
- if (target.attr('type') == 'text') {
+ if (target.attr('type') === 'text') {
target.select();
}
}