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([
paths.libDir + 'sjcl/sjcl.js',
paths.libDir + 'sjcl/*.js',
paths.libDir + 'angulartics/angulartics.js',
paths.libDir + '**/*.js',
'!' + paths.libDir + '**/*.min.js',
'!' + paths.libDir + 'angular/**/*',

View File

@ -47,3 +47,24 @@
/// <reference path="app/vault/vaultEditFolderController.js" />
/// <reference path="app/vault/vaultEditSiteController.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
.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');
});
};

View File

@ -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');
});

View File

@ -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;
};
});

View File

@ -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;

View File

@ -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');

View File

@ -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');
});

View File

@ -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');
});

View File

@ -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');
});

View File

@ -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;
}

View File

@ -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');
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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();
}
}