diff --git a/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.stories.ts b/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.stories.ts index b1c1a0a906a..0ecec9d8944 100644 --- a/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.stories.ts +++ b/apps/web/src/app/layouts/product-switcher/navigation-switcher/navigation-switcher.stories.ts @@ -5,6 +5,7 @@ import { BehaviorSubject, firstValueFrom, Observable, of } from "rxjs"; import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Provider } from "@bitwarden/common/admin-console/models/domain/provider"; @@ -130,6 +131,12 @@ export default { return new I18nMockService(translations); }, }, + { + provide: PolicyService, + useValue: { + policyAppliesToUser$: () => of(false), + }, + }, ], }), applicationConfig({ diff --git a/apps/web/src/app/layouts/product-switcher/product-switcher.stories.ts b/apps/web/src/app/layouts/product-switcher/product-switcher.stories.ts index 4525105e579..0b7304a3657 100644 --- a/apps/web/src/app/layouts/product-switcher/product-switcher.stories.ts +++ b/apps/web/src/app/layouts/product-switcher/product-switcher.stories.ts @@ -5,6 +5,7 @@ import { BehaviorSubject, firstValueFrom, Observable, of } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Provider } from "@bitwarden/common/admin-console/models/domain/provider"; @@ -126,6 +127,12 @@ export default { }); }, }, + { + provide: PolicyService, + useValue: { + policyAppliesToUser$: () => of(false), + }, + }, ], }), applicationConfig({ diff --git a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts index a1ac434d590..4abd85d7991 100644 --- a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts +++ b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts @@ -7,6 +7,7 @@ import { Observable, firstValueFrom, of } from "rxjs"; import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Provider } from "@bitwarden/common/admin-console/models/domain/provider"; @@ -27,6 +28,7 @@ describe("ProductSwitcherService", () => { let accountService: FakeAccountService; let platformUtilsService: MockProxy; let activeRouteParams = convertToParamMap({ organizationId: "1234" }); + let singleOrgPolicyEnabled = false; const getLastSync = jest.fn().mockResolvedValue(new Date("2024-05-14")); const userId = Utils.newGuid() as UserId; @@ -77,6 +79,12 @@ describe("ProductSwitcherService", () => { provide: SyncService, useValue: { getLastSync }, }, + { + provide: PolicyService, + useValue: { + policyAppliesToUser$: () => of(singleOrgPolicyEnabled), + }, + }, ], }); }); @@ -184,6 +192,14 @@ describe("ProductSwitcherService", () => { expect(products.bento.find((p) => p.name === "Admin Console")).toBeDefined(); expect(products.other.find((p) => p.name === "Organizations")).toBeUndefined(); }); + + it("does not include Organizations when the user's single org policy is enabled", async () => { + singleOrgPolicyEnabled = true; + initiateService(); + const products = await firstValueFrom(service.products$); + + expect(products.other.find((p) => p.name === "Organizations")).not.toBeDefined(); + }); }); describe("Provider Portal", () => { diff --git a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts index ec0d2c2651c..53ec3b0840f 100644 --- a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts +++ b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts @@ -6,6 +6,7 @@ import { combineLatest, concatMap, filter, + firstValueFrom, map, Observable, ReplaySubject, @@ -18,10 +19,12 @@ import { canAccessOrgAdmin, OrganizationService, } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; -import { ProviderType } from "@bitwarden/common/admin-console/enums"; +import { PolicyType, ProviderType } from "@bitwarden/common/admin-console/enums"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SyncService } from "@bitwarden/common/platform/sync"; @@ -104,6 +107,7 @@ export class ProductSwitcherService { private syncService: SyncService, private accountService: AccountService, private platformUtilsService: PlatformUtilsService, + private policyService: PolicyService, ) { this.pollUntilSynced(); } @@ -235,7 +239,15 @@ export class ProductSwitcherService { if (acOrg) { bento.push(products.ac); } else { - other.push(products.orgs); + const activeUserId = await firstValueFrom( + this.accountService.activeAccount$.pipe(getUserId), + ); + const userHasSingleOrgPolicy = await firstValueFrom( + this.policyService.policyAppliesToUser$(PolicyType.SingleOrg, activeUserId), + ); + if (!userHasSingleOrgPolicy) { + other.push(products.orgs); + } } if (providers.length > 0) {