diff --git a/src/app/config.js b/src/app/config.js index 0c4abe83..7b70adba 100644 --- a/src/app/config.js +++ b/src/app/config.js @@ -150,6 +150,12 @@ angular controller: 'organizationBillingController', 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 .state('frontend', { diff --git a/src/app/organization/organizationVaultController.js b/src/app/organization/organizationVaultController.js new file mode 100644 index 00000000..84ce96a1 --- /dev/null +++ b/src/app/organization/organizationVaultController.js @@ -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; + } + }); + }; + }); diff --git a/src/app/organization/views/organizationVault.html b/src/app/organization/views/organizationVault.html new file mode 100644 index 00000000..360aa9e6 --- /dev/null +++ b/src/app/organization/views/organizationVault.html @@ -0,0 +1,112 @@ +
+

+ Org Vault + {{subvaults.length}} subvaults, {{logins.length}} logins +

+
+
+
+

Loading...

+
+
+
+

+ + {{subvault.name}} {{subvaultLogins.length}} logins +

+
+ +
+
+
+
+

No logins in this subvault.

+
+
+ + + + + + + +
+ + + {{login.name}} +
{{login.username}}
+
+
+
+
+
+
+

+ + Orphaned {{orphanedLogins.length}} logins +

+
+
+
+

No orphaned logins.

+
+
+ + + + + + + +
+ + + {{login.name}} +
{{login.username}}
+
+
+
+
+
diff --git a/src/app/services/apiService.js b/src/app/services/apiService.js index 225a62f2..0238ede7 100644 --- a/src/app/services/apiService.js +++ b/src/app/services/apiService.js @@ -26,6 +26,7 @@ getFullDetails: { url: _apiUri + '/ciphers/:id/full-details', method: 'GET', params: { id: '@id' } }, list: { 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: {} }, favorite: { url: _apiUri + '/ciphers/:id/favorite', method: 'POST', params: { id: '@id' } }, putPartial: { url: _apiUri + '/ciphers/:id/partial', method: 'POST', params: { id: '@id' } }, diff --git a/src/app/views/organizationLayout.html b/src/app/views/organizationLayout.html index 7050b718..c46146be 100644 --- a/src/app/views/organizationLayout.html +++ b/src/app/views/organizationLayout.html @@ -46,6 +46,11 @@ Subvaults +
  • + + Vault + +
  • Billing diff --git a/src/index.html b/src/index.html index 11db7dea..52d9e491 100644 --- a/src/index.html +++ b/src/index.html @@ -144,6 +144,7 @@ +