renaming org vault logins to ciphers

This commit is contained in:
Kyle Spearrin 2017-10-11 15:54:47 -04:00
parent 2963516d5c
commit 7f6ee21a8e
11 changed files with 146 additions and 126 deletions

View File

@ -57,8 +57,8 @@ angular
$scope.$broadcast('vaultAddFolder');
};
$scope.addOrganizationLogin = function () {
$scope.$broadcast('organizationVaultAddLogin');
$scope.addOrganizationCipher = function () {
$scope.$broadcast('organizationVaultAddCipher');
};
$scope.addOrganizationCollection = function () {

View File

@ -1,10 +1,17 @@
angular
.module('bit.organization')
.controller('organizationVaultAddLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
cipherService, passwordService, $analytics, authService, orgId, $uibModal) {
$analytics.eventTrack('organizationVaultAddLoginController', { category: 'Modal' });
$scope.login = {};
.controller('organizationVaultAddCipherController', function ($scope, apiService, $uibModalInstance, cryptoService,
cipherService, passwordService, $analytics, authService, orgId, $uibModal, constants) {
$analytics.eventTrack('organizationVaultAddCipherController', { category: 'Modal' });
$scope.constants = constants;
$scope.selectedType = constants.cipherType.login.toString();
$scope.cipher = {
type: constants.cipherType.login,
secureNote: {
type: '0'
}
};
$scope.hideFolders = $scope.hideFavorite = $scope.fromOrg = true;
authService.getUserProfile().then(function (userProfile) {
@ -12,40 +19,44 @@
$scope.useTotp = orgProfile.useTotp;
});
$scope.typeChanged = function () {
$scope.cipher.type = parseInt($scope.selectedType);
};
$scope.savePromise = null;
$scope.save = function (model) {
model.organizationId = orgId;
var login = cipherService.encryptLogin(model);
$scope.savePromise = apiService.ciphers.postAdmin(login, function (loginResponse) {
$analytics.eventTrack('Created Organization Login');
var decLogin = cipherService.decryptLogin(loginResponse);
$uibModalInstance.close(decLogin);
$scope.save = function () {
$scope.cipher.organizationId = orgId;
var cipher = cipherService.encryptCipher($scope.cipher);
$scope.savePromise = apiService.ciphers.postAdmin(cipher, function (cipherResponse) {
$analytics.eventTrack('Created Organization Cipher');
var decCipher = cipherService.decryptCipherPreview(cipherResponse);
$uibModalInstance.close(decCipher);
}).$promise;
};
$scope.generatePassword = function () {
if (!$scope.login.password || confirm('Are you sure you want to overwrite the current password?')) {
if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) {
$analytics.eventTrack('Generated Password From Add');
$scope.login.password = passwordService.generatePassword({ length: 12, special: true });
$scope.cipher.login.password = passwordService.generatePassword({ length: 12, special: true });
}
};
$scope.addField = function () {
if (!$scope.login.fields) {
$scope.login.fields = [];
if (!$scope.cipher.fields) {
$scope.cipher.fields = [];
}
$scope.login.fields.push({
type: '0',
$scope.cipher.fields.push({
type: constants.fieldType.text.toString(),
name: null,
value: null
});
};
$scope.removeField = function (field) {
var index = $scope.login.fields.indexOf(field);
var index = $scope.cipher.fields.indexOf(field);
if (index > -1) {
$scope.login.fields.splice(index, 1);
$scope.cipher.fields.splice(index, 1);
}
};

View File

@ -2,16 +2,16 @@
.module('bit.organization')
.controller('organizationVaultAttachmentsController', function ($scope, apiService, $uibModalInstance, cryptoService,
cipherService, loginId, $analytics, validationService, toastr, $timeout) {
cipherService, cipherId, $analytics, validationService, toastr, $timeout) {
$analytics.eventTrack('organizationVaultAttachmentsController', { category: 'Modal' });
$scope.login = {};
$scope.cipher = {};
$scope.loading = true;
$scope.isPremium = true;
$scope.canUseAttachments = true;
var closing = false;
apiService.ciphers.getAdmin({ id: loginId }, function (login) {
$scope.login = cipherService.decryptLogin(login);
apiService.ciphers.getAdmin({ id: cipherId }, function (cipher) {
$scope.cipher = cipherService.decryptCipher(cipher);
$scope.loading = false;
}, function () {
$scope.loading = false;
@ -24,12 +24,12 @@
return;
}
var key = cryptoService.getOrgKey($scope.login.organizationId);
var key = cryptoService.getOrgKey($scope.cipher.organizationId);
$scope.savePromise = cipherService.encryptAttachmentFile(key, files[0]).then(function (encValue) {
var fd = new FormData();
var blob = new Blob([encValue.data], { type: 'application/octet-stream' });
fd.append('data', blob, encValue.fileName);
return apiService.ciphers.postAttachment({ id: loginId }, fd).$promise;
return apiService.ciphers.postAttachment({ id: cipherId }, fd).$promise;
}).then(function (response) {
$analytics.eventTrack('Added Attachment');
toastr.success('The attachment has been added.');
@ -47,7 +47,7 @@
$scope.download = function (attachment) {
attachment.loading = true;
var key = cryptoService.getOrgKey($scope.login.organizationId);
var key = cryptoService.getOrgKey($scope.cipher.organizationId);
cipherService.downloadAndDecryptAttachment(key, attachment, true).then(function (res) {
$timeout(function () {
attachment.loading = false;
@ -65,12 +65,12 @@
}
attachment.loading = true;
apiService.ciphers.delAttachment({ id: loginId, attachmentId: attachment.id }).$promise.then(function () {
apiService.ciphers.delAttachment({ id: cipherId, attachmentId: attachment.id }).$promise.then(function () {
attachment.loading = false;
$analytics.eventTrack('Deleted Organization Attachment');
var index = $scope.login.attachments.indexOf(attachment);
var index = $scope.cipher.attachments.indexOf(attachment);
if (index > -1) {
$scope.login.attachments.splice(index, 1);
$scope.cipher.attachments.splice(index, 1);
}
}, function () {
toastr.error('Cannot delete attachment.');
@ -89,6 +89,6 @@
e.preventDefault();
closing = true;
$uibModalInstance.close(!!$scope.login.attachments && $scope.login.attachments.length > 0);
$uibModalInstance.close(!!$scope.cipher.attachments && $scope.cipher.attachments.length > 0);
});
});

View File

@ -1,9 +1,9 @@
angular
.module('bit.organization')
.controller('organizationVaultLoginCollectionsController', function ($scope, apiService, $uibModalInstance, cipherService,
.controller('organizationVaultCipherCollectionsController', function ($scope, apiService, $uibModalInstance, cipherService,
cipher, $analytics, collections) {
$analytics.eventTrack('organizationVaultLoginCollectionsController', { category: 'Modal' });
$analytics.eventTrack('organizationVaultCipherCollectionsController', { category: 'Modal' });
$scope.cipher = {};
$scope.collections = [];
$scope.selectedCollections = {};
@ -69,7 +69,7 @@
$scope.submitPromise = apiService.ciphers.putCollectionsAdmin({ id: cipher.id }, request)
.$promise.then(function (response) {
$analytics.eventTrack('Edited Login Collections');
$analytics.eventTrack('Edited Cipher Collections');
$uibModalInstance.close({
action: 'collectionsEdit',
collectionIds: request.collectionIds

View File

@ -3,7 +3,7 @@
.controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state,
$localStorage, $uibModal, $filter, authService) {
$scope.logins = [];
$scope.ciphers = [];
$scope.collections = [];
$scope.loading = true;
@ -27,16 +27,14 @@
var cipherPromise = apiService.ciphers.listOrganizationDetails({ organizationId: $state.params.orgId },
function (ciphers) {
var decLogins = [];
var decCiphers = [];
for (var i = 0; i < ciphers.Data.length; i++) {
if (ciphers.Data[i].Type === 1) {
var decLogin = cipherService.decryptLoginPreview(ciphers.Data[i]);
decLogins.push(decLogin);
}
var decCipher = cipherService.decryptCipherPreview(ciphers.Data[i]);
decCiphers.push(decCipher);
}
$scope.logins = decLogins;
$scope.ciphers = decCiphers;
}).$promise;
$q.all([collectionPromise, cipherPromise]).then(function () {
@ -77,55 +75,55 @@
}
};
$scope.editLogin = function (login) {
$scope.editCipher = function (cipher) {
var editModel = $uibModal.open({
animation: true,
templateUrl: 'app/vault/views/vaultEditLogin.html',
controller: 'organizationVaultEditLoginController',
templateUrl: 'app/vault/views/vaultEditCipher.html',
controller: 'organizationVaultEditCipherController',
resolve: {
loginId: function () { return login.id; },
cipherId: function () { return cipher.id; },
orgId: function () { return $state.params.orgId; }
}
});
editModel.result.then(function (returnVal) {
if (returnVal.action === 'edit') {
login.name = returnVal.data.name;
login.username = returnVal.data.username;
cipher.name = returnVal.data.name;
cipher.subTitle = returnVal.data.login.username;
}
else if (returnVal.action === 'delete') {
var index = $scope.logins.indexOf(login);
var index = $scope.ciphers.indexOf(cipher);
if (index > -1) {
$scope.logins.splice(index, 1);
$scope.ciphers.splice(index, 1);
}
}
});
};
$scope.$on('organizationVaultAddLogin', function (event, args) {
$scope.addLogin();
$scope.$on('organizationVaultAddCipher', function (event, args) {
$scope.addCipher();
});
$scope.addLogin = function () {
$scope.addCipher = function () {
var addModel = $uibModal.open({
animation: true,
templateUrl: 'app/vault/views/vaultAddLogin.html',
controller: 'organizationVaultAddLoginController',
templateUrl: 'app/vault/views/vaultAddCipher.html',
controller: 'organizationVaultAddCipherController',
resolve: {
orgId: function () { return $state.params.orgId; }
}
});
addModel.result.then(function (addedLogin) {
$scope.logins.push(addedLogin);
addModel.result.then(function (addedCipher) {
$scope.ciphers.push(addedCipher);
});
};
$scope.editCollections = function (cipher) {
var modal = $uibModal.open({
animation: true,
templateUrl: 'app/organization/views/organizationVaultLoginCollections.html',
controller: 'organizationVaultLoginCollectionsController',
templateUrl: 'app/organization/views/organizationVaultCipherCollections.html',
controller: 'organizationVaultCipherCollectionsController',
resolve: {
cipher: function () { return cipher; },
collections: function () { return $scope.collections; }
@ -139,9 +137,9 @@
});
};
$scope.attachments = function (login) {
$scope.attachments = function (cipher) {
authService.getUserProfile().then(function (profile) {
return !!profile.organizations[login.organizationId].maxStorageGb;
return !!profile.organizations[cipher.organizationId].maxStorageGb;
}).then(function (useStorage) {
if (!useStorage) {
$uibModal.open({
@ -149,7 +147,7 @@
templateUrl: 'app/views/paidOrgRequired.html',
controller: 'paidOrgRequiredController',
resolve: {
orgId: function () { return login.organizationId; }
orgId: function () { return cipher.organizationId; }
}
});
return;
@ -160,18 +158,18 @@
templateUrl: 'app/vault/views/vaultAttachments.html',
controller: 'organizationVaultAttachmentsController',
resolve: {
loginId: function () { return login.id; }
cipherId: function () { return cipher.id; }
}
});
attachmentModel.result.then(function (hasAttachments) {
login.hasAttachments = hasAttachments;
cipher.hasAttachments = hasAttachments;
});
});
};
$scope.removeLogin = function (login, collection) {
if (!confirm('Are you sure you want to remove this login (' + login.name + ') from the ' +
$scope.removeCipher = function (cipher, collection) {
if (!confirm('Are you sure you want to remove this item (' + cipher.name + ') from the ' +
'collection (' + collection.name + ') ?')) {
return;
}
@ -180,28 +178,28 @@
collectionIds: []
};
for (var i = 0; i < login.collectionIds.length; i++) {
if (login.collectionIds[i] !== collection.id) {
request.collectionIds.push(login.collectionIds[i]);
for (var i = 0; i < cipher.collectionIds.length; i++) {
if (cipher.collectionIds[i] !== collection.id) {
request.collectionIds.push(cipher.collectionIds[i]);
}
}
apiService.ciphers.putCollections({ id: login.id }, request).$promise.then(function (response) {
$analytics.eventTrack('Removed Login From Collection');
login.collectionIds = request.collectionIds;
apiService.ciphers.putCollections({ id: cipher.id }, request).$promise.then(function (response) {
$analytics.eventTrack('Removed Cipher From Collection');
cipher.collectionIds = request.collectionIds;
});
};
$scope.deleteLogin = function (login) {
if (!confirm('Are you sure you want to delete this login (' + login.name + ')?')) {
$scope.deleteCipher = function (cipher) {
if (!confirm('Are you sure you want to delete this item (' + cipher.name + ')?')) {
return;
}
apiService.ciphers.delAdmin({ id: login.id }, function () {
$analytics.eventTrack('Deleted Login');
var index = $scope.logins.indexOf(login);
apiService.ciphers.delAdmin({ id: cipher.id }, function () {
$analytics.eventTrack('Deleted Cipher');
var index = $scope.ciphers.indexOf(cipher);
if (index > -1) {
$scope.logins.splice(index, 1);
$scope.ciphers.splice(index, 1);
}
});
};

View File

@ -1,52 +1,53 @@
angular
.module('bit.organization')
.controller('organizationVaultEditLoginController', function ($scope, apiService, $uibModalInstance, cryptoService,
cipherService, passwordService, loginId, $analytics, orgId, $uibModal) {
$analytics.eventTrack('organizationVaultEditLoginController', { category: 'Modal' });
$scope.login = {};
.controller('organizationVaultEditCipherController', function ($scope, apiService, $uibModalInstance, cryptoService,
cipherService, passwordService, cipherId, $analytics, orgId, $uibModal, constants) {
$analytics.eventTrack('organizationVaultEditCipherController', { category: 'Modal' });
$scope.cipher = {};
$scope.hideFolders = $scope.hideFavorite = $scope.fromOrg = true;
$scope.constants = constants;
apiService.ciphers.getAdmin({ id: loginId }, function (login) {
$scope.login = cipherService.decryptLogin(login);
$scope.useTotp = $scope.login.organizationUseTotp;
apiService.ciphers.getAdmin({ id: cipherId }, function (cipher) {
$scope.cipher = cipherService.decryptCipher(cipher);
$scope.useTotp = $scope.cipher.organizationUseTotp;
});
$scope.save = function (model) {
var login = cipherService.encryptLogin(model);
$scope.savePromise = apiService.ciphers.putAdmin({ id: loginId }, login, function (loginResponse) {
$analytics.eventTrack('Edited Organization Login');
var decLogin = cipherService.decryptLogin(loginResponse);
var cipher = cipherService.encryptCipher(model, $scope.cipher.type);
$scope.savePromise = apiService.ciphers.putAdmin({ id: cipherId }, cipher, function (cipherResponse) {
$analytics.eventTrack('Edited Organization Cipher');
var decCipher = cipherService.decryptCipher(cipherResponse);
$uibModalInstance.close({
action: 'edit',
data: decLogin
data: decCipher
});
}).$promise;
};
$scope.generatePassword = function () {
if (!$scope.login.password || confirm('Are you sure you want to overwrite the current password?')) {
if (!$scope.cipher.login.password || confirm('Are you sure you want to overwrite the current password?')) {
$analytics.eventTrack('Generated Password From Edit');
$scope.login.password = passwordService.generatePassword({ length: 12, special: true });
$scope.cipher.login.password = passwordService.generatePassword({ length: 12, special: true });
}
};
$scope.addField = function () {
if (!$scope.login.fields) {
$scope.login.fields = [];
if (!$scope.cipher.login.fields) {
$scope.cipher.login.fields = [];
}
$scope.login.fields.push({
type: '0',
$scope.cipher.fields.push({
type: constants.fieldType.text.toString(),
name: null,
value: null
});
};
$scope.removeField = function (field) {
var index = $scope.login.fields.indexOf(field);
var index = $scope.cipher.fields.indexOf(field);
if (index > -1) {
$scope.login.fields.splice(index, 1);
$scope.cipher.fields.splice(index, 1);
}
};
@ -70,15 +71,15 @@
}
$scope.delete = function () {
if (!confirm('Are you sure you want to delete this login (' + $scope.login.name + ')?')) {
if (!confirm('Are you sure you want to delete this item (' + $scope.cipher.name + ')?')) {
return;
}
apiService.ciphers.delAdmin({ id: $scope.login.id }, function () {
$analytics.eventTrack('Deleted Organization Login From Edit');
apiService.ciphers.delAdmin({ id: $scope.cipher.id }, function () {
$analytics.eventTrack('Deleted Organization Cipher From Edit');
$uibModalInstance.close({
action: 'delete',
data: $scope.login.id
data: $scope.cipher.id
});
});
};

View File

@ -5,7 +5,7 @@
<span ng-pluralize
count="collections.length > 0 ? collections.length - 1 : 0"
when="{'1': '{} collection', 'other': '{} collections'}"></span>,
<span ng-pluralize count="logins.length" when="{'1': '{} login', 'other': '{} logins'}"></span>
<span ng-pluralize count="ciphers.length" when="{'1': '{} item', 'other': '{} items'}"></span>
</small>
</h1>
</section>
@ -13,12 +13,12 @@
<p ng-show="loading && !collections.length">Loading...</p>
<div class="box" ng-class="{'collapsed-box': collection.collapsed}" ng-repeat="collection in collections |
orderBy: collectionSort track by collection.id"
ng-show="collections.length && (!main.searchVaultText || collectionLogins.length)">
ng-show="collections.length && (!main.searchVaultText || collectionCiphers.length)">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa" ng-class="{'fa-cubes': collection.id, 'fa-sitemap': !collection.id}"></i>
{{collection.name}}
<small ng-pluralize count="collectionLogins.length" when="{'1': '{} login', 'other': '{} logins'}"></small>
<small ng-pluralize count="collectionCiphers.length" when="{'1': '{} item', 'other': '{} items'}"></small>
</h3>
<div class="box-tools">
<button type="button" class="btn btn-box-tool" data-widget="collapse" title="Collapse/Expand"
@ -27,14 +27,14 @@
</button>
</div>
</div>
<div class="box-body" ng-class="{'no-padding': collectionLogins.length}">
<div ng-show="!collectionLogins.length && collection.id">No logins in this collection.</div>
<div ng-show="!collectionLogins.length && !collection.id">No unassigned logins.</div>
<div class="table-responsive" ng-show="collectionLogins.length">
<div class="box-body" ng-class="{'no-padding': collectionCiphers.length}">
<div ng-show="!collectionCiphers.length && collection.id">No items in this collection.</div>
<div ng-show="!collectionCiphers.length && !collection.id">No unassigned items.</div>
<div class="table-responsive" ng-show="collectionCiphers.length">
<table class="table table-striped table-hover table-vmiddle">
<tbody>
<tr ng-repeat="login in collectionLogins = (logins | filter: filterByCollection(collection) |
filter: (main.searchVaultText || '') | orderBy: ['name', 'username']) track by login.id">
<tr ng-repeat="cipher in collectionCiphers = (ciphers | filter: filterByCollection(collection) |
filter: (main.searchVaultText || '') | orderBy: ['name', 'subTitle']) track by cipher.id">
<td style="width: 70px;">
<div class="btn-group" data-append-to="body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
@ -42,37 +42,42 @@
</button>
<ul class="dropdown-menu">
<li>
<a href="#" stop-click ng-click="editLogin(login)">
<a href="#" stop-click ng-click="editCipher(cipher)">
<i class="fa fa-fw fa-pencil"></i> Edit
</a>
</li>
<li>
<a href="#" stop-click ng-click="attachments(login)">
<a href="#" stop-click ng-click="attachments(cipher)">
<i class="fa fa-fw fa-paperclip"></i> Attachments
</a>
</li>
<li>
<a href="#" stop-click ng-click="editCollections(login)">
<a href="#" stop-click ng-click="editCollections(cipher)">
<i class="fa fa-fw fa-cubes"></i> Collections
</a>
</li>
<li>
<a href="#" stop-click ng-click="removeLogin(login, collection)" class="text-red"
<a href="#" stop-click ng-click="removeCipher(cipher, collection)" class="text-red"
ng-if="collection.id">
<i class="fa fa-fw fa-remove"></i> Remove
</a>
</li>
<li>
<a href="#" stop-click ng-click="deleteLogin(login)" class="text-red">
<a href="#" stop-click ng-click="deleteCipher(cipher)" class="text-red">
<i class="fa fa-fw fa-trash"></i> Delete
</a>
</li>
</ul>
</div>
</td>
<td class="vault-icon">
<i class="fa fa-fw fa-lg {{::cipher.icon}}" ng-if="!cipher.meta.image"></i>
<img alt="" ng-if="cipher.meta.image" ng-src="{{cipher.meta.image}}"
fallback-src="images/fa-globe.png" />
</td>
<td>
<a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a>
<div class="text-sm text-muted">{{login.username}}</div>
<a href="#" stop-click ng-click="editCipher(cipher)">{{cipher.name}}</a>
<div class="text-sm text-muted">{{cipher.subTitle}}</div>
</td>
</tr>
</tbody>

View File

@ -4,7 +4,7 @@
</div>
<form name="form" ng-submit="form.$valid && submit()" api-form="submitPromise" autocomplete="off">
<div class="modal-body">
<p>Edit the collections that this login is being shared with.</p>
<p>Edit the collections that this item is being shared with.</p>
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
<h4>Errors have occurred</h4>
<ul>

View File

@ -271,7 +271,8 @@ angular
function setLoginIcon(cipher, uri, setImage) {
if (uri) {
var hostnameUri = uri;
var hostnameUri = uri,
isWebsite = false;
if (hostnameUri.indexOf('androidapp://') === 0) {
cipher.icon = 'fa-android';
@ -282,9 +283,13 @@ angular
else if (hostnameUri.indexOf('://') === -1 && hostnameUri.indexOf('http://') !== 0 &&
hostnameUri.indexOf('https://') !== 0) {
hostnameUri = "http://" + hostnameUri;
isWebsite = true;
}
else {
isWebsite = hostnameUri.indexOf('http') === 0 && hostnameUri.indexOf('.') > 0;
}
if (setImage && !cipher.icon && hostnameUri.indexOf('.') > 0) {
if (setImage && isWebsite) {
try {
var url = new URL(hostnameUri);
cipher.meta.image = 'https://icons.bitwarden.com?url=' + url.hostname;

View File

@ -53,8 +53,8 @@
</a>
<ul class="treeview-menu" ng-class="{'menu-open': $state.includes('backend.org.vault')}">
<li>
<a href="#" stop-click ng-click="addOrganizationLogin()">
<i class="fa fa-plus-circle fa-fw"></i> New Login
<a href="#" stop-click ng-click="addOrganizationCipher()">
<i class="fa fa-plus-circle fa-fw"></i> New Item
</a>
</li>
</ul>

View File

@ -250,9 +250,9 @@
<script src="app/organization/organizationBillingChangePlanController.js"></script>
<script src="app/organization/organizationBillingVerifyBankController.js"></script>
<script src="app/organization/organizationVaultController.js"></script>
<script src="app/organization/organizationVaultAddLoginController.js"></script>
<script src="app/organization/organizationVaultEditLoginController.js"></script>
<script src="app/organization/organizationVaultLoginCollectionsController.js"></script>
<script src="app/organization/organizationVaultAddCipherController.js"></script>
<script src="app/organization/organizationVaultEditCipherController.js"></script>
<script src="app/organization/organizationVaultCipherCollectionsController.js"></script>
<script src="app/organization/organizationVaultAttachmentsController.js"></script>
<script src="app/organization/organizationGroupsController.js"></script>
<script src="app/organization/organizationGroupsAddController.js"></script>