1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-22 16:29:09 +01:00

Added analytics telemetry throughout the application. Make sure angulartics bundles before the ga dependency.

This commit is contained in:
Kyle Spearrin 2016-08-11 20:43:05 -04:00
parent ffbf25b62f
commit 92e0537bed
18 changed files with 76 additions and 23 deletions

View File

@ -289,6 +289,7 @@ gulp.task('dist:js:lib', function () {
.src([ .src([
paths.libDir + 'sjcl/sjcl.js', paths.libDir + 'sjcl/sjcl.js',
paths.libDir + 'sjcl/*.js', paths.libDir + 'sjcl/*.js',
paths.libDir + 'angulartics/angulartics.js',
paths.libDir + '**/*.js', paths.libDir + '**/*.js',
'!' + paths.libDir + '**/*.min.js', '!' + paths.libDir + '**/*.min.js',
'!' + paths.libDir + 'angular/**/*', '!' + paths.libDir + 'angular/**/*',

View File

@ -47,3 +47,24 @@
/// <reference path="app/vault/vaultEditFolderController.js" /> /// <reference path="app/vault/vaultEditFolderController.js" />
/// <reference path="app/vault/vaultEditSiteController.js" /> /// <reference path="app/vault/vaultEditSiteController.js" />
/// <reference path="app/vault/vaultmodule.js" /> /// <reference path="app/vault/vaultmodule.js" />
/// <reference path="lib/admin-lte/js/app.js" />
/// <reference path="lib/angular/angular.js" />
/// <reference path="lib/angular-bootstrap/angular-bootstrap-tpls.js" />
/// <reference path="lib/angular-bootstrap-show-errors/showErrors.js" />
/// <reference path="lib/angular-cookies/angular-cookies.js" />
/// <reference path="lib/angular-jwt/angular-jwt.js" />
/// <reference path="lib/angular-md5/angular-md5.js" />
/// <reference path="lib/angular-messages/angular-messages.js" />
/// <reference path="lib/angular-resource/angular-resource.js" />
/// <reference path="lib/angular-toastr/angular-toastr.js" />
/// <reference path="lib/angular-toastr/angular-toastr.tpls.js" />
/// <reference path="lib/angular-ui-router/angular-ui-router.js" />
/// <reference path="lib/bootstrap/js/bootstrap.min.js" />
/// <reference path="lib/clipboard/clipboard.js" />
/// <reference path="lib/jquery/jquery.js" />
/// <reference path="lib/ngclipboard/ngclipboard.js" />
/// <reference path="lib/ngstorage/ngStorage.js" />
/// <reference path="lib/papaparse/papaparse.js" />
/// <reference path="lib/sjcl/bitArray.js" />
/// <reference path="lib/sjcl/cbc.js" />
/// <reference path="lib/sjcl/sjcl.js" />

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.accounts') .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); var rememberedEmail = $cookies.get(appSettings.rememberdEmailCookieName);
if (rememberedEmail) { if (rememberedEmail) {
$scope.model = { $scope.model = {
@ -29,9 +29,11 @@ angular
var profile = authService.getUserProfile(); var profile = authService.getUserProfile();
if (profile.twoFactor) { if (profile.twoFactor) {
$analytics.eventTrack('Logged In To Two-step');
$state.go('frontend.login.twoFactor'); $state.go('frontend.login.twoFactor');
} }
else { else {
$analytics.eventTrack('Logged In');
$state.go('backend.vault'); $state.go('backend.vault');
} }
}); });
@ -42,6 +44,7 @@ angular
$scope.twoFactorPromise = authService.logInTwoFactor(model.code, "Authenticator"); $scope.twoFactorPromise = authService.logInTwoFactor(model.code, "Authenticator");
$scope.twoFactorPromise.then(function () { $scope.twoFactorPromise.then(function () {
$analytics.eventTrack('Logged In From Two-step');
$state.go('backend.vault'); $state.go('backend.vault');
}); });
}; };

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLogoutController', function ($scope, authService, $state) { .controller('accountsLogoutController', function ($scope, authService, $state, $analytics) {
authService.logOut(); authService.logOut();
$analytics.eventTrack('Logged Out');
$state.go('frontend.login.info'); $state.go('frontend.login.info');
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService) { .controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService, $analytics) {
var params = $location.search(); var params = $location.search();
$scope.success = false; $scope.success = false;
@ -11,7 +11,7 @@ angular
$scope.registerPromise = null; $scope.registerPromise = null;
$scope.register = function (form) { $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); validationService.addError(form, 'ConfirmMasterPassword', 'Master password confirmation does not match.', true);
return; return;
} }
@ -26,6 +26,7 @@ angular
$scope.registerPromise = apiService.accounts.register(request, function () { $scope.registerPromise = apiService.accounts.register(request, function () {
$scope.success = true; $scope.success = true;
$analytics.eventTrack('Registered');
}).$promise; }).$promise;
}; };
}); });

View File

@ -18,7 +18,7 @@ angular
} }
var key = cryptoService.makeKey(value, profile.email, true); var key = cryptoService.makeKey(value, profile.email, true);
var valid = key == cryptoService.getKey(true); var valid = key === cryptoService.getKey(true);
ngModel.$setValidity('masterPassword', valid); ngModel.$setValidity('masterPassword', valid);
return valid ? value : undefined; return valid ? value : undefined;
}); });
@ -30,7 +30,7 @@ angular
} }
var key = cryptoService.makeKey(value, profile.email, true); var key = cryptoService.makeKey(value, profile.email, true);
var valid = key == cryptoService.getKey(true); var valid = key === cryptoService.getKey(true);
ngModel.$setValidity('masterPassword', valid); ngModel.$setValidity('masterPassword', valid);
return value; return value;

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.settings') .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, var _masterPasswordHash,
_newMasterPasswordHash, _newMasterPasswordHash,
_newKey; _newKey;
@ -48,6 +49,7 @@
$scope.confirmPromise = apiService.accounts.email(request, function () { $scope.confirmPromise = apiService.accounts.email(request, function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
$analytics.eventTrack('Changed Email');
authService.logOut(); authService.logOut();
$state.go('frontend.login.info').then(function () { $state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'Email Changed'); toastr.success('Please log back in.', 'Email Changed');

View File

@ -2,9 +2,10 @@
.module('bit.settings') .module('bit.settings')
.controller('settingsChangePasswordController', function ($scope, $state, apiService, $uibModalInstance, .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) { $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); validationService.addError(form, 'ConfirmNewMasterPassword', 'New master password confirmation does not match.', true);
return; return;
} }
@ -36,6 +37,7 @@
$scope.savePromise = apiService.accounts.putPassword(request, function () { $scope.savePromise = apiService.accounts.putPassword(request, function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
authService.logOut(); authService.logOut();
$analytics.eventTrack('Changed Password');
$state.go('frontend.login.info').then(function () { $state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'Master Password Changed'); toastr.success('Please log back in.', 'Master Password Changed');
}); });

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.settings') .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) { $scope.submit = function (model) {
var request = { var request = {
masterPasswordHash: cryptoService.hashPassword(model.masterPassword) masterPasswordHash: cryptoService.hashPassword(model.masterPassword)
@ -10,6 +11,7 @@
$scope.submitPromise = apiService.accounts.postDelete(request, function () { $scope.submitPromise = apiService.accounts.postDelete(request, function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
authService.logOut(); authService.logOut();
$analytics.eventTrack('Deleted Account');
$state.go('frontend.login.info').then(function () { $state.go('frontend.login.info').then(function () {
toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted'); toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted');
}); });

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.settings') .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) { $scope.submit = function (model) {
var request = { var request = {
masterPasswordHash: cryptoService.hashPassword(model.masterPassword) masterPasswordHash: cryptoService.hashPassword(model.masterPassword)
@ -10,6 +11,7 @@
$scope.submitPromise = apiService.accounts.putSecurityStamp(request, function () { $scope.submitPromise = apiService.accounts.putSecurityStamp(request, function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
authService.logOut(); authService.logOut();
$analytics.eventTrack('Deauthorized Sessions');
$state.go('frontend.login.info').then(function () { $state.go('frontend.login.info').then(function () {
toastr.success('Please log back in.', 'All Sessions Deauthorized'); toastr.success('Please log back in.', 'All Sessions Deauthorized');
}); });

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.settings') .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', var _issuer = 'bitwarden',
_profile = authService.getUserProfile(), _profile = authService.getUserProfile(),
_masterPasswordHash; _masterPasswordHash;
@ -39,15 +40,17 @@
var request = { var request = {
enabled: !currentlyEnabled, enabled: !currentlyEnabled,
token: model ? model.token : null, token: model ? model.token : null,
masterPasswordHash: _masterPasswordHash, masterPasswordHash: _masterPasswordHash
}; };
$scope.updatePromise = apiService.accounts.putTwoFactor({}, request, function (response) { $scope.updatePromise = apiService.accounts.putTwoFactor({}, request, function (response) {
if (response.TwoFactorEnabled) { if (response.TwoFactorEnabled) {
$analytics.eventTrack('Enabled Two-step Login');
toastr.success('Two-step login has been enabled.'); toastr.success('Two-step login has been enabled.');
if (_profile.extended) _profile.extended.twoFactorEnabled = true; if (_profile.extended) _profile.extended.twoFactorEnabled = true;
} }
else { else {
$analytics.eventTrack('Disabled Two-step Login');
toastr.success('Two-step login has been disabled.'); toastr.success('Two-step login has been disabled.');
if (_profile.extended) _profile.extended.twoFactorEnabled = false; if (_profile.extended) _profile.extended.twoFactorEnabled = false;
} }

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.tools') .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 () { $scope.close = function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
}; };

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.tools') .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.export = function (model) {
$scope.startedExport = true; $scope.startedExport = true;
apiService.sites.list({ expand: ['folder'] }, function (sites) { apiService.sites.list({ expand: ['folder'] }, function (sites) {
@ -36,6 +37,7 @@
document.body.removeChild(a); document.body.removeChild(a);
} }
$analytics.eventTrack('Exported Data');
toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!'); toastr.success('Your data has been exported. Check your browser\'s downloads folder.', 'Success!');
$scope.close(); $scope.close();
} }
@ -56,7 +58,7 @@
function makeFileName() { function makeFileName() {
var now = new Date(); var now = new Date();
var dateString = 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.getHours(), 2) + '' + padNumber(now.getMinutes(), 2) +
padNumber(now.getSeconds(), 2); padNumber(now.getSeconds(), 2);

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.tools') .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.model = { source: 'local' };
$scope.import = function (model) { $scope.import = function (model) {
@ -18,6 +19,7 @@
}, function () { }, function () {
$uibModalInstance.dismiss('cancel'); $uibModalInstance.dismiss('cancel');
$state.go('backend.vault').then(function () { $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'); toastr.success('Data has been successfully imported into your vault.', 'Import Success');
}); });
}, importError); }, importError);

View File

@ -1,11 +1,13 @@
angular angular
.module('bit.vault') .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.savePromise = null;
$scope.save = function (model) { $scope.save = function (model) {
var folder = cipherService.encryptFolder(model); var folder = cipherService.encryptFolder(model);
$scope.savePromise = apiService.folders.post(folder, function (response) { $scope.savePromise = apiService.folders.post(folder, function (response) {
$analytics.eventTrack('Created Folder');
var decFolder = cipherService.decryptFolder(response); var decFolder = cipherService.decryptFolder(response);
$uibModalInstance.close(decFolder); $uibModalInstance.close(decFolder);
}).$promise; }).$promise;

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.vault') .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.folders = folders;
$scope.site = { $scope.site = {
folderId: selectedFolder ? selectedFolder.id : null folderId: selectedFolder ? selectedFolder.id : null
@ -11,6 +12,7 @@
$scope.save = function (model) { $scope.save = function (model) {
var site = cipherService.encryptSite(model); var site = cipherService.encryptSite(model);
$scope.savePromise = apiService.sites.post(site, function (siteResponse) { $scope.savePromise = apiService.sites.post(site, function (siteResponse) {
$analytics.eventTrack('Created Site');
var decSite = cipherService.decryptSite(siteResponse); var decSite = cipherService.decryptSite(siteResponse);
$uibModalInstance.close(decSite); $uibModalInstance.close(decSite);
}).$promise; }).$promise;
@ -18,6 +20,7 @@
$scope.generatePassword = function () { $scope.generatePassword = function () {
if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) { 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 }); $scope.site.password = passwordService.generatePassword({ length: 10, special: true });
} }
}; };
@ -36,7 +39,7 @@
function selectPassword(e) { function selectPassword(e) {
var target = $(e.trigger).parent().prev(); var target = $(e.trigger).parent().prev();
if (target.attr('type') == 'text') { if (target.attr('type') === 'text') {
target.select(); target.select();
} }
} }

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.vault') .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 = {}; $scope.folder = {};
apiService.folders.get({ id: folderId }, function (folder) { apiService.folders.get({ id: folderId }, function (folder) {
@ -12,6 +13,7 @@
$scope.save = function (model) { $scope.save = function (model) {
var folder = cipherService.encryptFolder(model); var folder = cipherService.encryptFolder(model);
$scope.savePromise = apiService.folders.put({ id: folderId }, folder, function (response) { $scope.savePromise = apiService.folders.put({ id: folderId }, folder, function (response) {
$analytics.eventTrack('Edited Folder');
var decFolder = cipherService.decryptFolder(response); var decFolder = cipherService.decryptFolder(response);
$uibModalInstance.close(decFolder); $uibModalInstance.close(decFolder);
}).$promise; }).$promise;

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.vault') .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.folders = folders;
$scope.site = {}; $scope.site = {};
@ -12,6 +13,7 @@
$scope.save = function (model) { $scope.save = function (model) {
var site = cipherService.encryptSite(model); var site = cipherService.encryptSite(model);
$scope.savePromise = apiService.sites.put({ id: siteId }, site, function (siteResponse) { $scope.savePromise = apiService.sites.put({ id: siteId }, site, function (siteResponse) {
$analytics.eventTrack('Edited Site');
var decSite = cipherService.decryptSite(siteResponse); var decSite = cipherService.decryptSite(siteResponse);
$uibModalInstance.close(decSite); $uibModalInstance.close(decSite);
}).$promise; }).$promise;
@ -19,6 +21,7 @@
$scope.generatePassword = function () { $scope.generatePassword = function () {
if (!$scope.site.password || confirm('Are you sure you want to overwrite the current password?')) { 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 }); $scope.site.password = passwordService.generatePassword({ length: 10, special: true });
} }
}; };
@ -37,7 +40,7 @@
function selectPassword(e) { function selectPassword(e) {
var target = $(e.trigger).parent().prev(); var target = $(e.trigger).parent().prev();
if (target.attr('type') == 'text') { if (target.attr('type') === 'text') {
target.select(); target.select();
} }
} }