mirror of
https://github.com/bitwarden/browser.git
synced 2024-10-30 08:10:34 +01:00
re-worked change password, email, and update key
This commit is contained in:
parent
dad3cd9414
commit
747b5608e8
@ -312,56 +312,5 @@ angular
|
||||
};
|
||||
};
|
||||
|
||||
_service.updateKey = function (masterPasswordHash, success, error) {
|
||||
var madeEncKey = cryptoService.makeEncKey(null);
|
||||
encKey = madeEncKey.encKey;
|
||||
var encKeyEnc = madeEncKey.encKeyEnc;
|
||||
|
||||
var reencryptedLogins = [];
|
||||
var loginsPromise = apiService.logins.list({}, function (encryptedLogins) {
|
||||
var filteredEncryptedLogins = [];
|
||||
for (var i = 0; i < encryptedLogins.Data.length; i++) {
|
||||
if (encryptedLogins.Data[i].OrganizationId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredEncryptedLogins.push(encryptedLogins.Data[i]);
|
||||
}
|
||||
|
||||
var unencryptedLogins = _service.decryptLogins(filteredEncryptedLogins);
|
||||
reencryptedLogins = _service.encryptLogins(unencryptedLogins, encKey);
|
||||
}).$promise;
|
||||
|
||||
var reencryptedFolders = [];
|
||||
var foldersPromise = apiService.folders.list({}, function (encryptedFolders) {
|
||||
var unencryptedFolders = _service.decryptFolders(encryptedFolders.Data);
|
||||
reencryptedFolders = _service.encryptFolders(unencryptedFolders, encKey);
|
||||
}).$promise;
|
||||
|
||||
var privateKey = cryptoService.getPrivateKey('raw'),
|
||||
reencryptedPrivateKey = null;
|
||||
if (privateKey) {
|
||||
reencryptedPrivateKey = cryptoService.encrypt(privateKey, encKey, 'raw');
|
||||
}
|
||||
|
||||
return $q.all([loginsPromise, foldersPromise]).then(function () {
|
||||
var request = {
|
||||
masterPasswordHash: masterPasswordHash,
|
||||
ciphers: reencryptedLogins,
|
||||
folders: reencryptedFolders,
|
||||
privateKey: reencryptedPrivateKey,
|
||||
key: encKeyEnc
|
||||
};
|
||||
|
||||
return apiService.accounts.putKey(request).$promise;
|
||||
}, error).then(function () {
|
||||
cryptoService.setEncKey(encKey, null, true);
|
||||
return success();
|
||||
}, function () {
|
||||
cryptoService.clearEncKey();
|
||||
error();
|
||||
});
|
||||
};
|
||||
|
||||
return _service;
|
||||
});
|
||||
|
@ -2,49 +2,39 @@
|
||||
.module('bit.settings')
|
||||
|
||||
.controller('settingsChangeEmailController', function ($scope, $state, apiService, $uibModalInstance, cryptoService,
|
||||
cipherService, authService, $q, toastr, $analytics) {
|
||||
authService, toastr, $analytics, validationService) {
|
||||
$analytics.eventTrack('settingsChangeEmailController', { category: 'Modal' });
|
||||
|
||||
var _masterPasswordHash,
|
||||
_masterPassword,
|
||||
_newEmail;
|
||||
|
||||
$scope.token = function (model) {
|
||||
$scope.token = function (model, form) {
|
||||
var encKey = cryptoService.getEncKey();
|
||||
if (!encKey) {
|
||||
validationService.addError(form, null,
|
||||
'You cannot change your email until you update your encryption key.', true);
|
||||
return;
|
||||
}
|
||||
|
||||
_masterPassword = model.masterPassword;
|
||||
_newEmail = model.newEmail.toLowerCase();
|
||||
|
||||
cryptoService.hashPassword(_masterPassword).then(function (hash) {
|
||||
$scope.tokenPromise = cryptoService.hashPassword(_masterPassword).then(function (hash) {
|
||||
_masterPasswordHash = hash;
|
||||
|
||||
var encKey = cryptoService.getEncKey();
|
||||
if (encKey) {
|
||||
$scope.tokenPromise = requestToken();
|
||||
}
|
||||
else {
|
||||
// User is not using an enc key, let's make them one
|
||||
$scope.tokenPromise = cipherService.updateKey(_masterPasswordHash, function () {
|
||||
return requestToken();
|
||||
}, function (err) {
|
||||
toastr.error('Something went wrong.', 'Oh No!');
|
||||
});
|
||||
}
|
||||
var request = {
|
||||
newEmail: _newEmail,
|
||||
masterPasswordHash: _masterPasswordHash
|
||||
};
|
||||
|
||||
return apiService.accounts.emailToken(request, function () {
|
||||
$scope.tokenSent = true;
|
||||
}).$promise;
|
||||
});
|
||||
};
|
||||
|
||||
function requestToken() {
|
||||
var request = {
|
||||
newEmail: _newEmail,
|
||||
masterPasswordHash: _masterPasswordHash
|
||||
};
|
||||
|
||||
return apiService.accounts.emailToken(request, function () {
|
||||
$scope.tokenSent = true;
|
||||
}).$promise;
|
||||
}
|
||||
|
||||
$scope.confirm = function (model) {
|
||||
$scope.processing = true;
|
||||
|
||||
$scope.confirmPromise = cryptoService.makeKeyAndHash(_newEmail, _masterPassword).then(function (result) {
|
||||
var encKey = cryptoService.getEncKey();
|
||||
var newEncKey = cryptoService.encrypt(encKey.key, result.key, 'raw');
|
||||
@ -64,9 +54,6 @@
|
||||
return $state.go('frontend.login.info');
|
||||
}).then(function () {
|
||||
toastr.success('Please log back in.', 'Email Changed');
|
||||
}, function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
toastr.error('Something went wrong. Try again.', 'Oh No!');
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2,12 +2,19 @@
|
||||
.module('bit.settings')
|
||||
|
||||
.controller('settingsChangePasswordController', function ($scope, $state, apiService, $uibModalInstance,
|
||||
cryptoService, authService, cipherService, validationService, toastr, $analytics) {
|
||||
cryptoService, authService, validationService, toastr, $analytics) {
|
||||
$analytics.eventTrack('settingsChangePasswordController', { category: 'Modal' });
|
||||
|
||||
$scope.save = function (model, form) {
|
||||
var error = false;
|
||||
|
||||
var encKey = cryptoService.getEncKey();
|
||||
if (!encKey) {
|
||||
validationService.addError(form, null,
|
||||
'You cannot change your master password until you update your encryption key.', true);
|
||||
error = true;
|
||||
}
|
||||
|
||||
if ($scope.model.newMasterPassword.length < 8) {
|
||||
validationService.addError(form, 'NewMasterPasswordHash',
|
||||
'Master password must be at least 8 characters long.', true);
|
||||
@ -23,27 +30,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.processing = true;
|
||||
|
||||
var encKey = cryptoService.getEncKey();
|
||||
if (encKey) {
|
||||
$scope.savePromise = changePassword(model);
|
||||
}
|
||||
else {
|
||||
// User is not using an enc key, let's make them one
|
||||
$scope.savePromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) {
|
||||
return cipherService.updateKey(hash);
|
||||
}).then(function () {
|
||||
return changePassword(model);
|
||||
}, function (err) {
|
||||
toastr.error('Something went wrong.', 'Oh No!');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function changePassword(model) {
|
||||
var makeResult;
|
||||
return authService.getUserProfile().then(function (profile) {
|
||||
$scope.savePromise = authService.getUserProfile().then(function (profile) {
|
||||
return cryptoService.makeKeyAndHash(profile.email, model.newMasterPassword);
|
||||
}).then(function (result) {
|
||||
makeResult = result;
|
||||
@ -66,11 +54,8 @@
|
||||
return $state.go('frontend.login.info');
|
||||
}).then(function () {
|
||||
toastr.success('Please log back in.', 'Master Password Changed');
|
||||
}, function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
toastr.error('Something went wrong.', 'Oh No!');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.close = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
|
@ -1,8 +1,8 @@
|
||||
angular
|
||||
.module('bit.settings')
|
||||
|
||||
.controller('settingsUpdateKeyController', function ($scope, $state, apiService, $uibModalInstance,
|
||||
cryptoService, authService, cipherService, validationService, toastr, $analytics) {
|
||||
.controller('settingsUpdateKeyController', function ($scope, $state, apiService, $uibModalInstance, cipherService,
|
||||
cryptoService, authService, validationService, toastr, $analytics, $q) {
|
||||
$analytics.eventTrack('settingsUpdateKeyController', { category: 'Modal' });
|
||||
|
||||
$scope.save = function (form) {
|
||||
@ -13,27 +13,68 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.processing = true;
|
||||
$scope.savePromise = cryptoService.hashPassword($scope.masterPassword).then(function (hash) {
|
||||
return cipherService.updateKey(hash, function () {
|
||||
return null;
|
||||
}, function () {
|
||||
return null;
|
||||
});
|
||||
return updateKey(hash);
|
||||
}).then(function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
authService.logOut();
|
||||
$analytics.eventTrack('Key Updated');
|
||||
return $state.go('frontend.login.info');
|
||||
}, function (e) {
|
||||
throw e ? e : 'Error occurred.';
|
||||
}).then(function () {
|
||||
toastr.success('Please log back in. If you are using other bitwarden applications, ' +
|
||||
'log out and back in to those as well.', 'Key Updated', { timeOut: 10000 });
|
||||
}, function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
toastr.error('Something went wrong.', 'Oh No!');
|
||||
});
|
||||
};
|
||||
|
||||
function updateKey(masterPasswordHash) {
|
||||
var madeEncKey = cryptoService.makeEncKey(null);
|
||||
|
||||
var reencryptedLogins = [];
|
||||
var loginsPromise = apiService.logins.list({}, function (encryptedLogins) {
|
||||
var filteredEncryptedLogins = [];
|
||||
for (var i = 0; i < encryptedLogins.Data.length; i++) {
|
||||
if (encryptedLogins.Data[i].OrganizationId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredEncryptedLogins.push(encryptedLogins.Data[i]);
|
||||
}
|
||||
|
||||
var unencryptedLogins = cipherService.decryptLogins(filteredEncryptedLogins);
|
||||
reencryptedLogins = cipherService.encryptLogins(unencryptedLogins, madeEncKey.encKey);
|
||||
}).$promise;
|
||||
|
||||
var reencryptedFolders = [];
|
||||
var foldersPromise = apiService.folders.list({}, function (encryptedFolders) {
|
||||
var unencryptedFolders = cipherService.decryptFolders(encryptedFolders.Data);
|
||||
reencryptedFolders = cipherService.encryptFolders(unencryptedFolders, madeEncKey.encKey);
|
||||
}).$promise;
|
||||
|
||||
var privateKey = cryptoService.getPrivateKey('raw'),
|
||||
reencryptedPrivateKey = null;
|
||||
if (privateKey) {
|
||||
reencryptedPrivateKey = cryptoService.encrypt(privateKey, madeEncKey.encKey, 'raw');
|
||||
}
|
||||
|
||||
return $q.all([loginsPromise, foldersPromise]).then(function () {
|
||||
var request = {
|
||||
masterPasswordHash: masterPasswordHash,
|
||||
ciphers: reencryptedLogins,
|
||||
folders: reencryptedFolders,
|
||||
privateKey: reencryptedPrivateKey,
|
||||
key: madeEncKey.encKeyEnc
|
||||
};
|
||||
|
||||
return apiService.accounts.putKey(request).$promise;
|
||||
}, function () {
|
||||
throw 'Error while encrypting data.';
|
||||
}).then(function () {
|
||||
cryptoService.setEncKey(madeEncKey.encKey, null, true);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.close = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
|
@ -2,7 +2,8 @@
|
||||
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="changeEmailModelLabel"><i class="fa fa-at"></i> Change Email</h4>
|
||||
</div>
|
||||
<form name="changeEmailForm" ng-submit="changeEmailForm.$valid && token(model)" api-form="tokenPromise" ng-show="!tokenSent && !processing">
|
||||
<form name="changeEmailForm" ng-submit="changeEmailForm.$valid && token(model, changeEmailForm)" api-form="tokenPromise"
|
||||
ng-show="!tokenSent">
|
||||
<div class="modal-body">
|
||||
<p>Below you can change your account's email address.</p>
|
||||
<div class="callout callout-danger validation-errors" ng-show="changeEmailForm.$errors">
|
||||
@ -29,26 +30,28 @@
|
||||
</div>
|
||||
</form>
|
||||
<form name="changeEmailConfirmForm" ng-submit="changeEmailConfirmForm.$valid && confirm(model)" api-form="confirmPromise"
|
||||
ng-show="tokenSent && !processing">
|
||||
ng-show="tokenSent">
|
||||
<div class="modal-body">
|
||||
<p>We have emailed a verification code to <b>{{model.newEmail}}</b>. Please check your email for this code and enter it below to finalize your the email address change.</p>
|
||||
<div class="callout callout-warning">
|
||||
<h4><i class="fa fa-warning"></i> Warning</h4>
|
||||
Proceeding will log you out of your current session, requiring you to log back in.
|
||||
</div>
|
||||
<div class="callout callout-danger validation-errors" ng-show="changeEmailConfirmForm.$errors">
|
||||
<h4>Errors have occurred</h4>
|
||||
<ul>
|
||||
<li ng-repeat="e in changeEmailConfirmForm.$errors">{{e}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group" show-errors>
|
||||
<label for="token">Code</label>
|
||||
<input type="number" id="token" name="Token" ng-model="model.token" class="form-control" required api-field />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-flat">
|
||||
Change Email
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="changeEmailConfirmForm.$loading">
|
||||
<i class="fa fa-refresh fa-spin loading-icon" ng-show="changeEmailConfirmForm.$loading"></i>Change Email
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="processing" class="modal-body text-center">
|
||||
<p><i class="fa fa-cog fa-spin fa-3x"></i></p>
|
||||
<p>Please wait. We are now changing your email and reencrypting all of your data. Do not close this window. You will be automatically logged out when this process has finished.</p>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="changePasswrdModelLabel"><i class="fa fa-key"></i> Change Password</h4>
|
||||
</div>
|
||||
<form name="changePasswordForm" ng-submit="changePasswordForm.$valid && save(model, changePasswordForm)" api-form="savePromise" ng-show="!processing">
|
||||
<form name="changePasswordForm" ng-submit="changePasswordForm.$valid && save(model, changePasswordForm)" api-form="savePromise">
|
||||
<div class="modal-body">
|
||||
<p>Below you can change your account's master password.</p>
|
||||
<p>We recommend that you change your master password immediately if you believe that your credentials have been compromised.</p>
|
||||
@ -34,13 +34,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-flat">
|
||||
Change Password
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="changePasswordForm.$loading">
|
||||
<i class="fa fa-refresh fa-spin loading-icon" ng-show="changePasswordForm.$loading"></i>Change Password
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="processing" class="modal-body text-center">
|
||||
<p><i class="fa fa-cog fa-spin fa-3x"></i></p>
|
||||
<p>Please wait. We are now changing your password and reencrypting all of your data. Do not close this window. You will be automatically logged out when this process has finished.</p>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><i class="fa fa-key"></i> Update Encryption Key</h4>
|
||||
</div>
|
||||
<form name="form" ng-submit="form.$valid && save(form)" api-form="savePromise" ng-show="!processing">
|
||||
<form name="form" ng-submit="form.$valid && save(form)" api-form="savePromise">
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
This is <b>NOT</b> a security notification indicating that anything is wrong or has been compromised on your
|
||||
@ -39,16 +39,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-flat">
|
||||
Update Key
|
||||
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="form.$loading">
|
||||
<i class="fa fa-refresh fa-spin loading-icon" ng-show="form.$loading"></i>Update Key
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="processing" class="modal-body text-center">
|
||||
<p><i class="fa fa-cog fa-spin fa-3x"></i></p>
|
||||
<p>
|
||||
Please wait. We are now generating a new encryption key and reencrypting all of your data. Do not close this window.
|
||||
You will be automatically logged out when this process has finished.
|
||||
</p>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user