diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.html index 80750dc0d8..2ee5ea5037 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.html @@ -6,19 +6,31 @@ [text]="'projects' | i18n" route="projects" [relativeTo]="route.parent" - > + > +
+ {{ organizationCounts?.projects }} +
+ + > +
+ {{ organizationCounts?.secrets }} +
+ + > +
+ {{ organizationCounts?.serviceAccounts }} +
+ org.canAccessSecretsManager; - protected isAdmin$ = this.route.params.pipe( - concatMap( - async (params) => (await this.organizationService.get(params.organizationId))?.isAdmin, - ), - ); + protected isAdmin$: Observable; + protected isOrgEnabled$: Observable; + protected organizationCounts: OrganizationCounts; + private destroy$: Subject = new Subject(); constructor( protected route: ActivatedRoute, private organizationService: OrganizationService, + private countService: CountService, + private projectService: ProjectService, + private secretService: SecretService, + private serviceAccountService: ServiceAccountService, + private portingApiService: SecretsManagerPortingApiService, ) {} + + ngOnInit() { + const org$ = this.route.params.pipe( + concatMap((params) => this.organizationService.get(params.organizationId)), + distinctUntilChanged(), + takeUntil(this.destroy$), + ); + + this.isAdmin$ = org$.pipe( + map((org) => org?.isAdmin), + takeUntil(this.destroy$), + ); + + this.isOrgEnabled$ = org$.pipe( + map((org) => org?.enabled), + takeUntil(this.destroy$), + ); + + combineLatest([ + org$, + this.projectService.project$.pipe(startWith(null)), + this.secretService.secret$.pipe(startWith(null)), + this.serviceAccountService.serviceAccount$.pipe(startWith(null)), + this.portingApiService.imports$.pipe(startWith(null)), + ]) + .pipe( + filter(([org]) => org?.enabled), + switchMap(([org]) => this.countService.getOrganizationCounts(org.id)), + takeUntil(this.destroy$), + ) + .subscribe((organizationCounts) => { + this.organizationCounts = { + projects: organizationCounts.projects, + secrets: organizationCounts.secrets, + serviceAccounts: organizationCounts.serviceAccounts, + }; + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/models/view/counts.view.ts b/bitwarden_license/bit-web/src/app/secrets-manager/models/view/counts.view.ts new file mode 100644 index 0000000000..1520c772ec --- /dev/null +++ b/bitwarden_license/bit-web/src/app/secrets-manager/models/view/counts.view.ts @@ -0,0 +1,17 @@ +export type OrganizationCounts = { + projects: number; + secrets: number; + serviceAccounts: number; +}; + +export type ProjectCounts = { + secrets: number; + people: number; + serviceAccounts: number; +}; + +export type ServiceAccountCounts = { + projects: number; + people: number; + accessTokens: number; +}; diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html index 29cbf78464..a82e35afb6 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.html @@ -54,7 +54,7 @@ [projects]="view.latestProjects" >
- {{ "showingPortionOfTotal" | i18n: view.latestProjects.length : view.allProjects.length }} + {{ "showingPortionOfTotal" | i18n: view.latestProjects.length : view.counts.projects }} {{ "viewAll" | i18n }}
@@ -72,7 +72,7 @@ [secrets]="view.latestSecrets" >
- {{ "showingPortionOfTotal" | i18n: view.latestSecrets.length : view.allSecrets.length }} + {{ "showingPortionOfTotal" | i18n: view.latestSecrets.length : view.counts.secrets }} {{ "viewAll" | i18n }}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts index 4c057e5698..7073b4c289 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts @@ -21,6 +21,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { DialogService } from "@bitwarden/components"; +import { OrganizationCounts } from "../models/view/counts.view"; import { ProjectListView } from "../models/view/project-list.view"; import { SecretListView } from "../models/view/secret-list.view"; import { @@ -51,6 +52,7 @@ import { ServiceAccountOperation, } from "../service-accounts/dialog/service-account-dialog.component"; import { ServiceAccountService } from "../service-accounts/service-account.service"; +import { CountService } from "../shared/counts/count.service"; import { SecretsListComponent } from "../shared/secrets-list.component"; import { SMOnboardingTasks, SMOnboardingTasksService } from "./sm-onboarding-tasks.service"; @@ -87,11 +89,13 @@ export class OverviewComponent implements OnInit, OnDestroy { latestProjects: ProjectListView[]; latestSecrets: SecretListView[]; tasks: OrganizationTasks; + counts: OrganizationCounts; }>; constructor( private route: ActivatedRoute, private projectService: ProjectService, + private countService: CountService, private secretService: SecretService, private serviceAccountService: ServiceAccountService, private dialogService: DialogService, @@ -148,10 +152,19 @@ export class OverviewComponent implements OnInit, OnDestroy { share(), ); + const counts$ = combineLatest([ + orgId$, + this.secretService.secret$.pipe(startWith(null)), + this.projectService.project$.pipe(startWith(null)), + ]).pipe( + switchMap(([orgId]) => this.countService.getOrganizationCounts(orgId)), + share(), + ); + this.view$ = orgId$.pipe( switchMap((orgId) => - combineLatest([projects$, secrets$, serviceAccounts$]).pipe( - switchMap(async ([projects, secrets, serviceAccounts]) => ({ + combineLatest([projects$, secrets$, serviceAccounts$, counts$]).pipe( + switchMap(async ([projects, secrets, serviceAccounts, counts]) => ({ latestProjects: this.getRecentItems(projects, this.tableSize), latestSecrets: this.getRecentItems(secrets, this.tableSize), allProjects: projects, @@ -162,6 +175,11 @@ export class OverviewComponent implements OnInit, OnDestroy { createProject: projects.length > 0, createServiceAccount: serviceAccounts.length > 0, }), + counts: { + projects: counts.projects, + secrets: counts.secrets, + serviceAccounts: counts.serviceAccounts, + }, })), ), ), diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.html index d95f4392eb..d44d7898ca 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.html @@ -3,10 +3,25 @@ {{ "projects" | i18n }} - {{ "secrets" | i18n }} + + {{ "secrets" | i18n }} +
+ {{ projectCounts?.secrets }} +
+
- {{ "people" | i18n }} - {{ "machineAccounts" | i18n }} + + {{ "people" | i18n }} +
+ {{ projectCounts?.people }} +
+
+ + {{ "machineAccounts" | i18n }} +
+ {{ projectCounts?.serviceAccounts }} +
+
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts index 07ca32600a..fb7f2d7452 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project.component.ts @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; +import { ActivatedRoute } from "@angular/router"; import { combineLatest, filter, @@ -13,11 +13,13 @@ import { } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; -import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { DialogService } from "@bitwarden/components"; +import { ProjectCounts } from "../../models/view/counts.view"; import { ProjectView } from "../../models/view/project.view"; +import { SecretService } from "../../secrets/secret.service"; +import { AccessPolicyService } from "../../shared/access-policies/access-policy.service"; +import { CountService } from "../../shared/counts/count.service"; import { OperationType, ProjectDialogComponent, @@ -31,6 +33,7 @@ import { ProjectService } from "../project.service"; }) export class ProjectComponent implements OnInit, OnDestroy { protected project$: Observable; + protected projectCounts: ProjectCounts; private organizationId: string; private projectId: string; @@ -40,11 +43,11 @@ export class ProjectComponent implements OnInit, OnDestroy { constructor( private route: ActivatedRoute, private projectService: ProjectService, - private router: Router, + private secretService: SecretService, + private accessPolicyService: AccessPolicyService, private dialogService: DialogService, - private platformUtilsService: PlatformUtilsService, - private i18nService: I18nService, private organizationService: OrganizationService, + private countService: CountService, ) {} ngOnInit(): void { @@ -62,13 +65,23 @@ export class ProjectComponent implements OnInit, OnDestroy { const organization$ = this.route.params.pipe( concatMap((params) => this.organizationService.get$(params.organizationId)), ); + const projectCounts$ = combineLatest([ + this.route.params, + this.secretService.secret$.pipe(startWith(null)), + this.accessPolicyService.accessPolicy$.pipe(startWith(null)), + ]).pipe(switchMap(([params]) => this.countService.getProjectCounts(params.projectId))); - combineLatest([projectId$, organization$]) + combineLatest([projectId$, organization$, projectCounts$]) .pipe(takeUntil(this.destroy$)) - .subscribe(([projectId, organization]) => { + .subscribe(([projectId, organization, projectCounts]) => { this.organizationId = organization.id; this.projectId = projectId; this.organizationEnabled = organization.enabled; + this.projectCounts = { + secrets: projectCounts.secrets, + people: projectCounts.people, + serviceAccounts: projectCounts.serviceAccounts, + }; }); } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts index 31394f7fec..4603368882 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts @@ -8,6 +8,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { DialogService } from "@bitwarden/components"; +import { ServiceAccountPeopleAccessPoliciesView } from "../../models/view/access-policies/service-account-people-access-policies.view"; import { AccessPolicySelectorService } from "../../shared/access-policies/access-policy-selector/access-policy-selector.service"; import { ApItemValueType, @@ -179,7 +180,7 @@ export class ServiceAccountPeopleComponent implements OnInit, OnDestroy { private async updateServiceAccountPeopleAccessPolicies( serviceAccountId: string, selectedPolicies: ApItemValueType[], - ) { + ): Promise { const serviceAccountPeopleView = convertToPeopleAccessPoliciesView(selectedPolicies); return await this.accessPolicyService.putServiceAccountPeopleAccessPolicies( serviceAccountId, diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.html index 00b5201a65..c9ce8d8c64 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.html +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-account.component.html @@ -10,9 +10,24 @@ - {{ "projects" | i18n }} - {{ "people" | i18n }} - {{ "accessTokens" | i18n }} + + {{ "projects" | i18n }} +
+ {{ serviceAccountCounts?.projects }} +
+
+ + {{ "people" | i18n }} +
+ {{ serviceAccountCounts?.people }} +
+
+ + {{ "accessTokens" | i18n }} +
+ {{ serviceAccountCounts?.accessTokens }} +
+
{{ "eventLogs" | i18n }}