shared vault listing conversion to ciphers

This commit is contained in:
Kyle Spearrin 2017-10-07 13:45:33 -04:00
parent 3b71760f9e
commit 7c93c82d24
3 changed files with 78 additions and 78 deletions

View File

@ -74,7 +74,7 @@ angular
var key = null; var key = null;
if (encryptedCipher.OrganizationId) { if (encryptedCipher.OrganizationId) {
key = cryptoService.getOrgKey(encryptedLogin.OrganizationId); key = cryptoService.getOrgKey(encryptedCipher.OrganizationId);
} }
var cipher = { var cipher = {

View File

@ -3,7 +3,7 @@
.controller('vaultSharedController', function ($scope, apiService, cipherService, $analytics, $q, $localStorage, .controller('vaultSharedController', function ($scope, apiService, cipherService, $analytics, $q, $localStorage,
$uibModal, $filter, $rootScope, authService, cryptoService) { $uibModal, $filter, $rootScope, authService, cryptoService) {
$scope.logins = []; $scope.ciphers = [];
$scope.collections = []; $scope.collections = [];
$scope.loading = true; $scope.loading = true;
@ -22,16 +22,16 @@
}).$promise; }).$promise;
var cipherPromise = apiService.ciphers.listDetails({}, function (ciphers) { var cipherPromise = apiService.ciphers.listDetails({}, function (ciphers) {
var decLogins = []; var decCiphers = [];
for (var i = 0; i < ciphers.Data.length; i++) { for (var i = 0; i < ciphers.Data.length; i++) {
if (ciphers.Data[i].Type === 1) { if (ciphers.Data[i].Type === 1) {
var decLogin = cipherService.decryptLoginPreview(ciphers.Data[i]); var decCipher = cipherService.decryptCipherPreview(ciphers.Data[i]);
decLogins.push(decLogin); decCiphers.push(decCipher);
} }
} }
if (decLogins.length) { if (decCiphers.length) {
$scope.collections.push({ $scope.collections.push({
id: null, id: null,
name: 'Unassigned', name: 'Unassigned',
@ -39,7 +39,7 @@
}); });
} }
$scope.logins = decLogins; $scope.ciphers = decCiphers;
}).$promise; }).$promise;
$q.all([collectionPromise, cipherPromise]).then(function () { $q.all([collectionPromise, cipherPromise]).then(function () {
@ -49,29 +49,29 @@
$scope.clipboardError = function (e) { $scope.clipboardError = function (e) {
alert('Your web browser does not support easy clipboard copying. ' + alert('Your web browser does not support easy clipboard copying. ' +
'Edit the login and copy it manually instead.'); 'Edit the item and copy it manually instead.');
}; };
$scope.attachments = function (login) { $scope.attachments = function (cipher) {
authService.getUserProfile().then(function (profile) { authService.getUserProfile().then(function (profile) {
return { return {
isPremium: profile.premium, isPremium: profile.premium,
orgUseStorage: login.organizationId && !!profile.organizations[login.organizationId].maxStorageGb orgUseStorage: cipher.organizationId && !!profile.organizations[cipher.organizationId].maxStorageGb
}; };
}).then(function (perms) { }).then(function (perms) {
if (login.organizationId && !perms.orgUseStorage) { if (cipher.organizationId && !perms.orgUseStorage) {
$uibModal.open({ $uibModal.open({
animation: true, animation: true,
templateUrl: 'app/views/paidOrgRequired.html', templateUrl: 'app/views/paidOrgRequired.html',
controller: 'paidOrgRequiredController', controller: 'paidOrgRequiredController',
resolve: { resolve: {
orgId: function () { return login.organizationId; } orgId: function () { return cipher.organizationId; }
} }
}); });
return; return;
} }
if (!login.organizationId && !perms.isPremium) { if (!cipher.organizationId && !perms.isPremium) {
$uibModal.open({ $uibModal.open({
animation: true, animation: true,
templateUrl: 'app/views/premiumRequired.html', templateUrl: 'app/views/premiumRequired.html',
@ -80,7 +80,7 @@
return; return;
} }
if (!login.organizationId && !cryptoService.getEncKey()) { if (!cipher.organizationId && !cryptoService.getEncKey()) {
toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable'); toastr.error('You cannot use this feature until you update your encryption key.', 'Feature Unavailable');
return; return;
} }
@ -90,12 +90,12 @@
templateUrl: 'app/vault/views/vaultAttachments.html', templateUrl: 'app/vault/views/vaultAttachments.html',
controller: 'vaultAttachmentsController', controller: 'vaultAttachmentsController',
resolve: { resolve: {
loginId: function () { return login.id; } loginId: function () { return cipher.id; }
} }
}); });
attachmentModel.result.then(function (hasAttachments) { attachmentModel.result.then(function (hasAttachments) {
login.hasAttachments = hasAttachments; cipher.hasAttachments = hasAttachments;
}); });
}); });
}; };
@ -133,62 +133,62 @@
} }
}; };
$scope.editLogin = function (login) { $scope.editCipher = function (cipher) {
var editModel = $uibModal.open({ var editModel = $uibModal.open({
animation: true, animation: true,
templateUrl: 'app/vault/views/vaultEditLogin.html', templateUrl: 'app/vault/views/vaultEditCipher.html',
controller: 'vaultEditLoginController', controller: 'vaultEditCipherController',
resolve: { resolve: {
loginId: function () { return login.id; } cipherId: function () { return cipher.id; }
} }
}); });
editModel.result.then(function (returnVal) { editModel.result.then(function (returnVal) {
var rootLogin = findRootLogin(login) || {}; var rootCipher = findRootCipher(cipher) || { meta: {} };
if (returnVal.action === 'edit') { if (returnVal.action === 'edit') {
login.folderId = rootLogin.folderId = returnVal.data.folderId; cipher.folderId = rootCipher.folderId = returnVal.data.folderId;
login.name = rootLogin.name = returnVal.data.name; cipher.name = rootCipher.name = returnVal.data.name;
login.username = rootLogin.username = returnVal.data.username; cipher.subTitle = rootCipher.subTitle = returnVal.data.login.username;
login.password = rootLogin.password = returnVal.data.password; cipher.meta.password = rootCipher.meta.password = returnVal.data.login.password;
login.favorite = rootLogin.favorite = returnVal.data.favorite; cipher.favorite = rootCipher.favorite = returnVal.data.favorite;
} }
else if (returnVal.action === 'partialEdit') { else if (returnVal.action === 'partialEdit') {
login.folderId = rootLogin.folderId = returnVal.data.folderId; cipher.folderId = rootCipher.folderId = returnVal.data.folderId;
login.favorite = rootLogin.favorite = returnVal.data.favorite; cipher.favorite = rootCipher.favorite = returnVal.data.favorite;
} }
else if (returnVal.action === 'delete') { else if (returnVal.action === 'delete') {
var index = $scope.logins.indexOf(login); var index = $scope.ciphers.indexOf(cipher);
if (index > -1) { if (index > -1) {
$scope.logins.splice(index, 1); $scope.ciphers.splice(index, 1);
} }
removeRootLogin(rootLogin); removeRootCipher(rootCipher);
} }
}); });
}; };
$scope.editCollections = function (login) { $scope.editCollections = function (cipher) {
var modal = $uibModal.open({ var modal = $uibModal.open({
animation: true, animation: true,
templateUrl: 'app/vault/views/vaultLoginCollections.html', templateUrl: 'app/vault/views/vaultLoginCollections.html',
controller: 'vaultLoginCollectionsController', controller: 'vaultLoginCollectionsController',
resolve: { resolve: {
loginId: function () { return login.id; } loginId: function () { return cipher.id; }
} }
}); });
modal.result.then(function (response) { modal.result.then(function (response) {
if (response.collectionIds) { if (response.collectionIds) {
login.collectionIds = response.collectionIds; cipher.collectionIds = response.collectionIds;
// TODO: if there are no collectionIds now, it is possible that the user no longer has access to this login // TODO: if there are no collectionIds now, it is possible that the user no longer has access to this cipher
// which means it should be removed by calling removeRootLogin(findRootLogin(login)) // which means it should be removed by calling removeRootCipher(findRootCipher(cipher))
} }
}); });
}; };
$scope.removeLogin = function (login, collection) { $scope.removeCipher = function (cipher, collection) {
if (!confirm('Are you sure you want to remove this login (' + login.name + ') from the ' + if (!confirm('Are you sure you want to remove this item (' + cipher.name + ') from the ' +
'collection (' + collection.name + ') ?')) { 'collection (' + collection.name + ') ?')) {
return; return;
} }
@ -197,34 +197,34 @@
collectionIds: [] collectionIds: []
}; };
for (var i = 0; i < login.collectionIds.length; i++) { for (var i = 0; i < cipher.collectionIds.length; i++) {
if (login.collectionIds[i] !== collection.id) { if (cipher.collectionIds[i] !== collection.id) {
request.collectionIds.push(login.collectionIds[i]); request.collectionIds.push(cipher.collectionIds[i]);
} }
} }
apiService.ciphers.putCollections({ id: login.id }, request).$promise.then(function (response) { apiService.ciphers.putCollections({ id: cipher.id }, request).$promise.then(function (response) {
$analytics.eventTrack('Removed From Collection'); $analytics.eventTrack('Removed From Collection');
login.collectionIds = request.collectionIds; cipher.collectionIds = request.collectionIds;
// TODO: if there are no collectionIds now, it is possible that the user no longer has access to this login // TODO: if there are no collectionIds now, it is possible that the user no longer has access to this cipher
// which means it should be removed by calling removeRootLogin(findRootLogin(login)) // which means it should be removed by calling removeRootCipher(findRootCipher(cipher))
}); });
}; };
function findRootLogin(login) { function findRootCipher(cipher) {
if ($rootScope.vaultCiphers) { if ($rootScope.vaultCiphers) {
var rootLogins = $filter('filter')($rootScope.vaultCiphers, { id: login.id }); var rootCiphers = $filter('filter')($rootScope.vaultCiphers, { id: cipher.id });
if (rootLogins && rootLogins.length) { if (rootCiphers && rootCiphers.length) {
return rootLogins[0]; return rootCiphers[0];
} }
} }
return null; return null;
} }
function removeRootLogin(rootLogin) { function removeRootCipher(rootCipher) {
if (rootLogin && rootLogin.id) { if (rootCipher && rootCipher.id) {
var index = $rootScope.vaultCiphers.indexOf(rootLogin); var index = $rootScope.vaultCiphers.indexOf(rootCipher);
if (index > -1) { if (index > -1) {
$rootScope.vaultCiphers.splice(index, 1); $rootScope.vaultCiphers.splice(index, 1);
} }

View File

@ -3,18 +3,18 @@
Shared Shared
<small> <small>
<span ng-pluralize <span ng-pluralize
count="collections.length > 0 && logins.length ? collections.length - 1 : collections.length" count="collections.length > 0 && ciphers.length ? collections.length - 1 : collections.length"
when="{'1': '{} collection', 'other': '{} collections'}"></span>, 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> </small>
</h1> </h1>
</section> </section>
<section class="content"> <section class="content">
<p ng-show="loading && !collections.length">Loading...</p> <p ng-show="loading && !collections.length">Loading...</p>
<div class="callout callout-default" style="background: #fff;" ng-show="!loading && !collections.length && !logins.length"> <div class="callout callout-default" style="background: #fff;" ng-show="!loading && !collections.length && !ciphers.length">
<h4>Nothing shared <i class="fa fa-frown-o"></i></h4> <h4>Nothing shared <i class="fa fa-frown-o"></i></h4>
<p> <p>
You do not have any logins or collections being shared with you. You do not have any items or collections being shared with you.
To start sharing, create an organization or ask an existing organization to invite you. To start sharing, create an organization or ask an existing organization to invite you.
</p> </p>
<a ui-sref="backend.user.settingsCreateOrg" class="btn btn-default btn-flat"> <a ui-sref="backend.user.settingsCreateOrg" class="btn btn-default btn-flat">
@ -28,7 +28,7 @@
<h3 class="box-title"> <h3 class="box-title">
<i class="fa" ng-class="{'fa-cubes': collection.id, 'fa-sitemap': !collection.id}"></i> <i class="fa" ng-class="{'fa-cubes': collection.id, 'fa-sitemap': !collection.id}"></i>
{{collection.name}} {{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> </h3>
<div class="box-tools"> <div class="box-tools">
<button type="button" class="btn btn-box-tool" data-widget="collapse" title="Collapse/Expand" <button type="button" class="btn btn-box-tool" data-widget="collapse" title="Collapse/Expand"
@ -37,20 +37,20 @@
</button> </button>
</div> </div>
</div> </div>
<div class="box-body" ng-class="{'no-padding': collectionLogins.length}"> <div class="box-body" ng-class="{'no-padding': collectionCiphers.length}">
<div ng-show="!collectionLogins.length && collection.id"> <div ng-show="!collectionCiphers.length && collection.id">
<p>No logins in this collection.</p> <p>No items in this collection.</p>
<p> <p>
Share a login to this collection by selecting <i class="fa fa-share-alt"></i> <b>Share</b> or Share an item to this collection by selecting <i class="fa fa-share-alt"></i> <b>Share</b> or
<i class="fa fa-cubes"></i> <b>Collections</b> from the login's options (<i class="fa fa-cog"></i>) menu. <i class="fa fa-cubes"></i> <b>Collections</b> from the item's options (<i class="fa fa-cog"></i>) menu.
</p> </p>
</div> </div>
<div ng-show="!collectionLogins.length && !collection.id">No unassigned logins.</div> <div ng-show="!collectionCiphers.length && !collection.id">No unassigned items.</div>
<div class="table-responsive" ng-show="collectionLogins.length"> <div class="table-responsive" ng-show="collectionCiphers.length">
<table class="table table-striped table-hover table-vmiddle"> <table class="table table-striped table-hover table-vmiddle">
<tbody> <tbody>
<tr ng-repeat="login in collectionLogins = (logins | filter: filterByCollection(collection) | <tr ng-repeat="cipher in collectionCiphers = (ciphers | filter: filterByCollection(collection) |
orderBy: ['name', 'username']) track by login.id"> orderBy: ['name', 'subTitle']) track by cipher.id">
<td style="width: 70px;"> <td style="width: 70px;">
<div class="btn-group" data-append-to="body"> <div class="btn-group" data-append-to="body">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
@ -58,28 +58,28 @@
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <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 <i class="fa fa-fw fa-pencil"></i> Edit
</a> </a>
</li> </li>
<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 <i class="fa fa-fw fa-paperclip"></i> Attachments
</a> </a>
</li> </li>
<li ng-show="login.edit"> <li ng-show="cipher.edit">
<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 <i class="fa fa-fw fa-cubes"></i> Collections
</a> </a>
</li> </li>
<li ng-show="login.password"> <li ng-show="cipher.meta.password">
<a href="#" stop-click ngclipboard ngclipboard-error="clipboardError(e)" <a href="#" stop-click ngclipboard ngclipboard-error="clipboardError(e)"
data-clipboard-text="{{login.password}}"> data-clipboard-text="{{cipher.meta.password}}">
<i class="fa fa-fw fa-clipboard"></i> Copy Password <i class="fa fa-fw fa-clipboard"></i> Copy Password
</a> </a>
</li> </li>
<li ng-show="login.edit"> <li ng-show="cipher.edit">
<a href="#" stop-click ng-click="removeLogin(login, collection)" <a href="#" stop-click ng-click="removeCipher(cipher, collection)"
ng-if="collection.id" class="text-red"> ng-if="collection.id" class="text-red">
<i class="fa fa-fw fa-remove"></i> Remove <i class="fa fa-fw fa-remove"></i> Remove
</a> </a>
@ -88,11 +88,11 @@
</div> </div>
</td> </td>
<td> <td>
<a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a> <a href="#" stop-click ng-click="editCipher(cipher)">{{cipher.name}}</a>
<i class="fa fa-star text-muted" title="Favorite" ng-show="login.favorite"></i> <i class="fa fa-star text-muted" title="Favorite" ng-show="cipher.favorite"></i>
<i class="fa fa-paperclip text-muted" title="Attachments" ng-if="login.hasAttachments" <i class="fa fa-paperclip text-muted" title="Attachments" ng-if="cipher.hasAttachments"
stop-prop></i><br /> stop-prop></i><br />
<div class="text-sm text-muted">{{login.username}}</div> <div class="text-sm text-muted">{{cipher.subTitle}}</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>