mirror of
https://github.com/bitwarden/web
synced 2025-12-11 13:53:17 +00:00
org vault listing
This commit is contained in:
@@ -150,6 +150,12 @@ angular
|
|||||||
controller: 'organizationBillingController',
|
controller: 'organizationBillingController',
|
||||||
data: { pageTitle: 'Organization Billing' }
|
data: { pageTitle: 'Organization Billing' }
|
||||||
})
|
})
|
||||||
|
.state('backend.org.vault', {
|
||||||
|
url: '/organization/:orgId/vault',
|
||||||
|
templateUrl: 'app/organization/views/organizationVault.html',
|
||||||
|
controller: 'organizationVaultController',
|
||||||
|
data: { pageTitle: 'Organization Vault' }
|
||||||
|
})
|
||||||
|
|
||||||
// Frontend
|
// Frontend
|
||||||
.state('frontend', {
|
.state('frontend', {
|
||||||
|
|||||||
85
src/app/organization/organizationVaultController.js
Normal file
85
src/app/organization/organizationVaultController.js
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
angular
|
||||||
|
.module('bit.vault')
|
||||||
|
|
||||||
|
.controller('organizationVaultController', function ($scope, apiService, cipherService, $analytics, $q, $state,
|
||||||
|
$localStorage, $uibModal, $filter) {
|
||||||
|
$scope.logins = [];
|
||||||
|
$scope.subvaults = [];
|
||||||
|
$scope.folders = [];
|
||||||
|
$scope.loading = true;
|
||||||
|
|
||||||
|
$scope.$on('$viewContentLoaded', function () {
|
||||||
|
var subvaultPromise = apiService.subvaults.listOrganization({ orgId: $state.params.orgId }, function (subvaults) {
|
||||||
|
var decSubvaults = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < subvaults.Data.length; i++) {
|
||||||
|
var decSubvault = cipherService.decryptSubvault(subvaults.Data[i], null, true);
|
||||||
|
decSubvault.collapsed = $localStorage.collapsedSubvaults &&
|
||||||
|
decSubvault.id in $localStorage.collapsedSubvaults;
|
||||||
|
decSubvaults.push(decSubvault);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.subvaults = decSubvaults;
|
||||||
|
}).$promise;
|
||||||
|
|
||||||
|
var cipherPromise = apiService.ciphers.listOrganizationDetails({ organizationId: $state.params.orgId },
|
||||||
|
function (ciphers) {
|
||||||
|
var decLogins = [];
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.logins = decLogins;
|
||||||
|
}).$promise;
|
||||||
|
|
||||||
|
$q.all([subvaultPromise, cipherPromise]).then(function () {
|
||||||
|
$scope.loading = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.filterBySubvault = function (subvault) {
|
||||||
|
return function (cipher) {
|
||||||
|
return cipher.subvaultIds.indexOf(subvault.id) > -1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.filterByOrphaned = function () {
|
||||||
|
return function (cipher) {
|
||||||
|
return !cipher.subvaultIds || !cipher.subvaultIds.length;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.collapseExpand = function (subvault) {
|
||||||
|
if (!$localStorage.collapsedOrgSubvaults) {
|
||||||
|
$localStorage.collapsedOrgSubvaults = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subvault.id in $localStorage.collapsedOrgSubvaults) {
|
||||||
|
delete $localStorage.collapsedOrgSubvaults[subvault.id];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$localStorage.collapsedOrgSubvaults[subvault.id] = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.editSubvaults = function (login) {
|
||||||
|
var modal = $uibModal.open({
|
||||||
|
animation: true,
|
||||||
|
templateUrl: 'app/vault/views/vaultLoginSubvaults.html',
|
||||||
|
controller: 'vaultOrganizationLoginSubvaultsController',
|
||||||
|
resolve: {
|
||||||
|
loginId: function () { return login.id; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.result.then(function (response) {
|
||||||
|
if (response.subvaultIds) {
|
||||||
|
login.subvaultIds = response.subvaultIds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
112
src/app/organization/views/organizationVault.html
Normal file
112
src/app/organization/views/organizationVault.html
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<section class="content-header">
|
||||||
|
<h1>
|
||||||
|
Org<span class="hidden-xs">anization</span> Vault
|
||||||
|
<small>{{subvaults.length}} subvaults, {{logins.length}} logins</small>
|
||||||
|
</h1>
|
||||||
|
</section>
|
||||||
|
<section class="content">
|
||||||
|
<div ng-show="loading && !subvaults.length">
|
||||||
|
<p>Loading...</p>
|
||||||
|
</div>
|
||||||
|
<div class="box" ng-class="{'collapsed-box': subvault.collapsed}" ng-repeat="subvault in subvaults | orderBy: ['name']"
|
||||||
|
ng-show="subvaults.length && (!main.searchVaultText || subvaultLogins.length)">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">
|
||||||
|
<i class="fa fa-share-alt-square"></i>
|
||||||
|
{{subvault.name}} <small>{{subvaultLogins.length}} logins</small>
|
||||||
|
</h3>
|
||||||
|
<div class="box-tools">
|
||||||
|
<button type="button" class="btn btn-box-tool" data-widget="collapse" title="Collapse/Expand"
|
||||||
|
ng-click="collapseExpand(subvault)">
|
||||||
|
<i class="fa" ng-class="{'fa-minus': !subvault.collapsed, 'fa-plus': subvault.collapsed}"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body" ng-class="{'no-padding': subvaultLogins.length}">
|
||||||
|
<div ng-show="!subvaultLogins.length">
|
||||||
|
<p>No logins in this subvault.</p>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive" ng-show="subvaultLogins.length">
|
||||||
|
<table class="table table-striped table-hover table-vmiddle">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="login in subvaultLogins = (logins | filter: filterBySubvault(subvault) |
|
||||||
|
filter: (main.searchVaultText || '') | orderBy: ['name', 'username'])">
|
||||||
|
<td style="width: 70px;">
|
||||||
|
<div class="btn-group dropdown-to-body">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-cog"></i> <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" ng-click="editSubvaults(login)">
|
||||||
|
<i class="fa fa-fw fa-share-alt"></i> Subvaults
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" ng-click="deleteLogin(login)" class="text-red">
|
||||||
|
<i class="fa fa-fw fa-remove"></i> Remove
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" ng-click="deleteLogin(login)" class="text-red">
|
||||||
|
<i class="fa fa-fw fa-trash"></i> Delete
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="javascript:void(0)" ng-click="editSubvaults(login)">{{login.name}}</a>
|
||||||
|
<div class="text-sm text-muted">{{login.username}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box" ng-show="!loading">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">
|
||||||
|
<i class="fa fa-sitemap"></i>
|
||||||
|
Orphaned <small>{{orphanedLogins.length}} logins</small>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body" ng-class="{'no-padding': orphanedLogins.length}">
|
||||||
|
<div ng-show="!orphanedLogins.length">
|
||||||
|
<p>No orphaned logins.</p>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive" ng-show="orphanedLogins.length">
|
||||||
|
<table class="table table-striped table-hover table-vmiddle">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="login in orphanedLogins = (logins | filter: filterByOrphaned() | orderBy: ['name', 'username'])">
|
||||||
|
<td style="width: 70px;">
|
||||||
|
<div class="btn-group dropdown-to-body">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-cog"></i> <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" ng-click="editSubvaults(login)">
|
||||||
|
<i class="fa fa-fw fa-share-alt"></i> Subvaults
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0)" ng-click="deleteLogin(login)" class="text-red">
|
||||||
|
<i class="fa fa-fw fa-trash"></i> Delete
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="javascript:void(0)" ng-click="editSubvaults(login)">{{login.name}}</a>
|
||||||
|
<div class="text-sm text-muted">{{login.username}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
getFullDetails: { url: _apiUri + '/ciphers/:id/full-details', method: 'GET', params: { id: '@id' } },
|
getFullDetails: { url: _apiUri + '/ciphers/:id/full-details', method: 'GET', params: { id: '@id' } },
|
||||||
list: { method: 'GET', params: {} },
|
list: { method: 'GET', params: {} },
|
||||||
listDetails: { url: _apiUri + '/ciphers/details', method: 'GET', params: {} },
|
listDetails: { url: _apiUri + '/ciphers/details', method: 'GET', params: {} },
|
||||||
|
listOrganizationDetails: { url: _apiUri + '/ciphers/organization-details', method: 'GET', params: {} },
|
||||||
'import': { url: _apiUri + '/ciphers/import', method: 'POST', params: {} },
|
'import': { url: _apiUri + '/ciphers/import', method: 'POST', params: {} },
|
||||||
favorite: { url: _apiUri + '/ciphers/:id/favorite', method: 'POST', params: { id: '@id' } },
|
favorite: { url: _apiUri + '/ciphers/:id/favorite', method: 'POST', params: { id: '@id' } },
|
||||||
putPartial: { url: _apiUri + '/ciphers/:id/partial', method: 'POST', params: { id: '@id' } },
|
putPartial: { url: _apiUri + '/ciphers/:id/partial', method: 'POST', params: { id: '@id' } },
|
||||||
|
|||||||
@@ -46,6 +46,11 @@
|
|||||||
<i class="fa fa-share-alt fa-fw"></i> <span>Subvaults</span>
|
<i class="fa fa-share-alt fa-fw"></i> <span>Subvaults</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li ng-class="{active: $state.is('backend.org.vault')}">
|
||||||
|
<a ui-sref="backend.org.vault({orgId: params.orgId})">
|
||||||
|
<i class="fa fa-lock fa-fw"></i> <span>Vault</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li ng-class="{active: $state.is('backend.org.billing')}" ng-if="isOrgOwner(orgProfile)">
|
<li ng-class="{active: $state.is('backend.org.billing')}" ng-if="isOrgOwner(orgProfile)">
|
||||||
<a ui-sref="backend.org.billing({orgId: params.orgId})">
|
<a ui-sref="backend.org.billing({orgId: params.orgId})">
|
||||||
<i class="fa fa-credit-card fa-fw"></i> <span>Billing</span>
|
<i class="fa fa-credit-card fa-fw"></i> <span>Billing</span>
|
||||||
|
|||||||
@@ -144,6 +144,7 @@
|
|||||||
<script src="app/organization/organizationBillingAdjustSeatsController.js"></script>
|
<script src="app/organization/organizationBillingAdjustSeatsController.js"></script>
|
||||||
<script src="app/organization/organizationDeleteController.js"></script>
|
<script src="app/organization/organizationDeleteController.js"></script>
|
||||||
<script src="app/organization/organizationBillingChangePlanController.js"></script>
|
<script src="app/organization/organizationBillingChangePlanController.js"></script>
|
||||||
|
<script src="app/organization/organizationVaultController.js"></script>
|
||||||
|
|
||||||
<script src="app/settings/settingsModule.js"></script>
|
<script src="app/settings/settingsModule.js"></script>
|
||||||
<script src="app/settings/settingsController.js"></script>
|
<script src="app/settings/settingsController.js"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user