From 92e0537bed1af7111b2af2975d814b1a384fe6b7 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Thu, 11 Aug 2016 20:43:05 -0400 Subject: [PATCH] Added analytics telemetry throughout the application. Make sure angulartics bundles before the ga dependency. --- src/Web/gulpfile.js | 1 + src/Web/wwwroot/_references.js | 21 +++++++++++++++++++ .../app/accounts/accountsLoginController.js | 5 ++++- .../app/accounts/accountsLogoutController.js | 3 ++- .../accounts/accountsRegisterController.js | 5 +++-- .../app/directives/masterPasswordDirective.js | 4 ++-- .../settings/settingsChangeEmailController.js | 4 +++- .../settingsChangePasswordController.js | 6 ++++-- .../app/settings/settingsDeleteController.js | 4 +++- .../settings/settingsSessionsController.js | 4 +++- .../settings/settingsTwoFactorController.js | 7 +++++-- .../app/tools/toolsAuditsController.js | 3 ++- .../app/tools/toolsExportController.js | 6 ++++-- .../app/tools/toolsImportController.js | 4 +++- .../app/vault/vaultAddFolderController.js | 4 +++- .../app/vault/vaultAddSiteController.js | 7 +++++-- .../app/vault/vaultEditFolderController.js | 4 +++- .../app/vault/vaultEditSiteController.js | 7 +++++-- 18 files changed, 76 insertions(+), 23 deletions(-) diff --git a/src/Web/gulpfile.js b/src/Web/gulpfile.js index 1ce68a2e0e..48e95ef112 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 f6998200c6..6c5d79bce2 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 01a1883f79..1e4ed23655 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 ff513bd4dd..418e968921 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 3dd71776ec..dd48a964ad 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 7c5eb8fe36..271a910890 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 eefb1d7e96..1ce1bba59f 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 f00519dd7b..82676442d3 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 cc10a7d722..0e80a1bf18 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 c649c91490..27c69e78c9 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 b76da478a2..1422b7ed80 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 0cbafe91ae..5e0eb6798c 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 e285b00e63..697ee3f455 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 8adcfd57a6..8c0c368785 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 92fc9d3f84..536407a491 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 93ea30f6ce..c88c30a767 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 e23bfb4a26..438bfe439c 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 0fc210d1f1..aed9e75680 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(); } }