diff --git a/apps/browser/src/admin-console/background/service-factories/organization-service.factory.ts b/apps/browser/src/admin-console/background/service-factories/organization-service.factory.ts index c77508b0f888..b1c9c118113e 100644 --- a/apps/browser/src/admin-console/background/service-factories/organization-service.factory.ts +++ b/apps/browser/src/admin-console/background/service-factories/organization-service.factory.ts @@ -6,10 +6,7 @@ import { factory, } from "../../../platform/background/service-factories/factory-options"; import { stateProviderFactory } from "../../../platform/background/service-factories/state-provider.factory"; -import { - stateServiceFactory, - StateServiceInitOptions, -} from "../../../platform/background/service-factories/state-service.factory"; +import { StateServiceInitOptions } from "../../../platform/background/service-factories/state-service.factory"; import { BrowserOrganizationService } from "../../services/browser-organization.service"; type OrganizationServiceFactoryOptions = FactoryOptions; @@ -25,10 +22,6 @@ export function organizationServiceFactory( cache, "organizationService", opts, - async () => - new BrowserOrganizationService( - await stateServiceFactory(cache, opts), - await stateProviderFactory(cache, opts), - ), + async () => new BrowserOrganizationService(await stateProviderFactory(cache, opts)), ); } diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 13895262179f..80afca11ef34 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -421,9 +421,9 @@ function getBgService(service: keyof MainBackground) { { provide: OrganizationService, useFactory: (stateService: StateServiceAbstraction, stateProvider: StateProvider) => { - return new BrowserOrganizationService(stateService, stateProvider); + return new BrowserOrganizationService(stateProvider); }, - deps: [StateServiceAbstraction, StateProvider], + deps: [StateProvider], }, { provide: VaultFilterService, diff --git a/apps/browser/src/vault/popup/components/vault/current-tab.component.ts b/apps/browser/src/vault/popup/components/vault/current-tab.component.ts index 5bf770a2187c..6a7e56a556bd 100644 --- a/apps/browser/src/vault/popup/components/vault/current-tab.component.ts +++ b/apps/browser/src/vault/popup/components/vault/current-tab.component.ts @@ -256,7 +256,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy { const otherTypes: CipherType[] = []; const dontShowCards = await this.stateService.getDontShowCardsCurrentTab(); const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab(); - this.showOrganizations = this.organizationService.hasOrganizations(); + this.showOrganizations = await this.organizationService.hasOrganizations(); if (!dontShowCards) { otherTypes.push(CipherType.Card); } diff --git a/apps/browser/src/vault/popup/components/vault/vault-items.component.ts b/apps/browser/src/vault/popup/components/vault/vault-items.component.ts index 60a8f4b78e7b..96d5fe170b02 100644 --- a/apps/browser/src/vault/popup/components/vault/vault-items.component.ts +++ b/apps/browser/src/vault/popup/components/vault/vault-items.component.ts @@ -74,7 +74,7 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn async ngOnInit() { this.searchTypeSearch = !this.platformUtilsService.isSafari(); - this.showOrganizations = this.organizationService.hasOrganizations(); + this.showOrganizations = await this.organizationService.hasOrganizations(); this.vaultFilter = this.vaultFilterService.getVaultFilter(); // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe this.route.queryParams.pipe(first()).subscribe(async (params) => { diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts index d1c46e9e0b2b..830db1357e6f 100644 --- a/apps/cli/src/bw.ts +++ b/apps/cli/src/bw.ts @@ -364,7 +364,7 @@ export class Main { this.providerService = new ProviderService(this.stateService); - this.organizationService = new OrganizationService(this.stateService, this.stateProvider); + this.organizationService = new OrganizationService(this.stateProvider); this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService); diff --git a/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts b/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts index 16050a1555f4..f6968daca9f2 100644 --- a/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts +++ b/apps/web/src/app/admin-console/organizations/guards/is-paid-org.guard.ts @@ -17,7 +17,7 @@ export class IsPaidOrgGuard implements CanActivate { ) {} async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - const org = this.organizationService.get(route.params.organizationId); + const org = await this.organizationService.get(route.params.organizationId); if (org == null) { return this.router.createUrlTree(["/"]); diff --git a/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.spec.ts b/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.spec.ts index 4a03f6a8c1e3..b240e6dd93c9 100644 --- a/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.spec.ts +++ b/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.spec.ts @@ -57,7 +57,7 @@ describe("Organization Permissions Guard", () => { }); it("blocks navigation if organization does not exist", async () => { - organizationService.get.mockReturnValue(null); + organizationService.get.mockResolvedValue(null); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -66,7 +66,7 @@ describe("Organization Permissions Guard", () => { it("permits navigation if no permissions are specified", async () => { const org = orgFactory(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -81,7 +81,7 @@ describe("Organization Permissions Guard", () => { }; const org = orgFactory(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -104,7 +104,7 @@ describe("Organization Permissions Guard", () => { }); const org = orgFactory(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -124,7 +124,7 @@ describe("Organization Permissions Guard", () => { }), }); const org = orgFactory(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -141,7 +141,7 @@ describe("Organization Permissions Guard", () => { type: OrganizationUserType.Admin, enabled: false, }); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); @@ -153,7 +153,7 @@ describe("Organization Permissions Guard", () => { type: OrganizationUserType.Owner, enabled: false, }); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const actual = await organizationPermissionsGuard.canActivate(route, state); diff --git a/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.ts b/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.ts index 76df518cf7ad..63b89284ec60 100644 --- a/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.ts +++ b/apps/web/src/app/admin-console/organizations/guards/org-permissions.guard.ts @@ -28,7 +28,7 @@ export class OrganizationPermissionsGuard implements CanActivate { await this.syncService.fullSync(false); } - const org = this.organizationService.get(route.params.organizationId); + const org = await this.organizationService.get(route.params.organizationId); if (org == null) { return this.router.createUrlTree(["/"]); } diff --git a/apps/web/src/app/admin-console/organizations/guards/org-redirect.guard.ts b/apps/web/src/app/admin-console/organizations/guards/org-redirect.guard.ts index 61d79f8bd5d0..bbfb51ed9492 100644 --- a/apps/web/src/app/admin-console/organizations/guards/org-redirect.guard.ts +++ b/apps/web/src/app/admin-console/organizations/guards/org-redirect.guard.ts @@ -16,7 +16,7 @@ export class OrganizationRedirectGuard implements CanActivate { ) {} async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - const org = this.organizationService.get(route.params.organizationId); + const org = await this.organizationService.get(route.params.organizationId); const customRedirect = route.data?.autoRedirectCallback; if (customRedirect) { diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts index 5262b3f64abe..84a5318c0ede 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts @@ -146,7 +146,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy { this.tabIndex = this.params.initialTab ?? MemberDialogTab.Role; this.title = this.i18nService.t(this.editMode ? "editMember" : "inviteMember"); - const organization$ = of(this.organizationService.get(this.params.organizationId)).pipe( + const organization$ = of(await this.organizationService.get(this.params.organizationId)).pipe( shareReplay({ refCount: true, bufferSize: 1 }), ); const groups$ = organization$.pipe( diff --git a/apps/web/src/app/admin-console/organizations/members/people.component.ts b/apps/web/src/app/admin-console/organizations/members/people.component.ts index afe07aaad1b0..85a46d697b19 100644 --- a/apps/web/src/app/admin-console/organizations/members/people.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/people.component.ts @@ -143,7 +143,7 @@ export class PeopleComponent async ngOnInit() { const organization$ = this.route.params.pipe( - map((params) => this.organizationService.get(params.organizationId)), + concatMap(async (params) => await this.organizationService.get(params.organizationId)), shareReplay({ refCount: true, bufferSize: 1 }), ); diff --git a/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts b/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts index 51f34481d36c..10db2384e3d6 100644 --- a/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts +++ b/apps/web/src/app/admin-console/organizations/reporting/reports-home.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; -import { filter, map, Observable, startWith } from "rxjs"; +import { filter, map, Observable, startWith, concatMap } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; @@ -30,7 +30,7 @@ export class ReportsHomeComponent implements OnInit { ); this.reports$ = this.route.params.pipe( - map((params) => this.organizationService.get(params.organizationId)), + concatMap(async (params) => await this.organizationService.get(params.organizationId)), map((org) => this.buildReports(org.isFreeOrg)), ); } diff --git a/apps/web/src/app/admin-console/organizations/settings/two-factor-setup.component.ts b/apps/web/src/app/admin-console/organizations/settings/two-factor-setup.component.ts index 58953cf0a21f..f6ea374639d4 100644 --- a/apps/web/src/app/admin-console/organizations/settings/two-factor-setup.component.ts +++ b/apps/web/src/app/admin-console/organizations/settings/two-factor-setup.component.ts @@ -36,9 +36,9 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent { async ngOnInit() { this.route.params .pipe( - tap((params) => { + tap(async (params) => { this.organizationId = params.organizationId; - this.organization = this.organizationService.get(this.organizationId); + this.organization = await this.organizationService.get(this.organizationId); }), concatMap(async () => await super.ngOnInit()), takeUntil(this.destroy$), diff --git a/apps/web/src/app/billing/organizations/organization-plans.component.ts b/apps/web/src/app/billing/organizations/organization-plans.component.ts index 70b91a0d0da2..f3ddea22b824 100644 --- a/apps/web/src/app/billing/organizations/organization-plans.component.ts +++ b/apps/web/src/app/billing/organizations/organization-plans.component.ts @@ -150,7 +150,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy { async ngOnInit() { if (this.organizationId) { - this.organization = this.organizationService.get(this.organizationId); + this.organization = await this.organizationService.get(this.organizationId); this.billing = await this.organizationApiService.getBilling(this.organizationId); this.sub = await this.organizationApiService.getSubscription(this.organizationId); } diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts index c4c6bde9b7f7..7c7ad690e6a8 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts @@ -94,7 +94,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy return; } this.loading = true; - this.userOrg = this.organizationService.get(this.organizationId); + this.userOrg = await this.organizationService.get(this.organizationId); if (this.userOrg.canViewSubscription) { this.sub = await this.organizationApiService.getSubscription(this.organizationId); this.lineItems = this.sub?.subscription?.items; diff --git a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts index 5a9a8eb08125..1b66f5400afe 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts @@ -110,7 +110,7 @@ export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDest return; } this.loading = true; - this.userOrg = this.organizationService.get(this.organizationId); + this.userOrg = await this.organizationService.get(this.organizationId); if (this.userOrg.canViewSubscription) { const subscriptionResponse = await this.organizationApiService.getSubscription( this.organizationId, diff --git a/apps/web/src/app/vault/components/collection-dialog/collection-dialog.component.ts b/apps/web/src/app/vault/components/collection-dialog/collection-dialog.component.ts index b10d6b1e28eb..d39f74ae3ac1 100644 --- a/apps/web/src/app/vault/components/collection-dialog/collection-dialog.component.ts +++ b/apps/web/src/app/vault/components/collection-dialog/collection-dialog.component.ts @@ -139,7 +139,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy { } async loadOrg(orgId: string, collectionIds: string[]) { - const organization$ = of(this.organizationService.get(orgId)).pipe( + const organization$ = of(await this.organizationService.get(orgId)).pipe( shareReplay({ refCount: true, bufferSize: 1 }), ); const groups$ = organization$.pipe( diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts index 7894677b69c0..46921a6d7be1 100644 --- a/apps/web/src/app/vault/individual-vault/vault.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault.component.ts @@ -520,7 +520,7 @@ export class VaultComponent implements OnInit, OnDestroy { this.messagingService.send("premiumRequired"); return; } else if (cipher.organizationId != null) { - const org = this.organizationService.get(cipher.organizationId); + const org = await this.organizationService.get(cipher.organizationId); if (org != null && (org.maxStorageGb == null || org.maxStorageGb === 0)) { this.messagingService.send("upgradeOrganization", { organizationId: cipher.organizationId, @@ -699,7 +699,7 @@ export class VaultComponent implements OnInit, OnDestroy { } async deleteCollection(collection: CollectionView): Promise { - const organization = this.organizationService.get(collection.organizationId); + const organization = await this.organizationService.get(collection.organizationId); if (!collection.canDelete(organization)) { this.platformUtilsService.showToast( "error", diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/guards/sm-org-enabled.guard.ts b/bitwarden_license/bit-web/src/app/secrets-manager/guards/sm-org-enabled.guard.ts index 3ff4d998a3de..a1f7564156c6 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/guards/sm-org-enabled.guard.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/guards/sm-org-enabled.guard.ts @@ -16,7 +16,7 @@ export const organizationEnabledGuard: CanActivateFn = async (route: ActivatedRo await syncService.fullSync(false); } - const org = orgService.get(route.params.organizationId); + const org = await orgService.get(route.params.organizationId); if (org == null || !org.canAccessSecretsManager) { return createUrlTreeFromSnapshot(route, ["/"]); } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts index 90faf165381c..cd117819a9fe 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/layout/navigation.component.ts @@ -14,7 +14,7 @@ export class NavigationComponent { protected readonly logo = SecretsManagerLogo; protected orgFilter = (org: Organization) => org.canAccessSecretsManager; protected isAdmin$ = this.route.params.pipe( - map((params) => this.organizationService.get(params.organizationId)?.isAdmin), + map(async (params) => (await this.organizationService.get(params.organizationId))?.isAdmin), ); constructor( 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 c916d6f48b4e..89fc1f1d5375 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 @@ -11,6 +11,7 @@ import { distinctUntilChanged, take, share, + concatMap, } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; @@ -100,7 +101,7 @@ export class OverviewComponent implements OnInit, OnDestroy { orgId$ .pipe( - map((orgId) => this.organizationService.get(orgId)), + concatMap(async (orgId) => await this.organizationService.get(orgId)), takeUntil(this.destroy$), ) .subscribe((org) => { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts index ebfb006c0ad8..07d50b28ee18 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts @@ -63,7 +63,9 @@ export class ProjectSecretsComponent { switchMap(async ([_, params]) => { this.organizationId = params.organizationId; this.projectId = params.projectId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; + this.organizationEnabled = ( + await this.organizationService.get(params.organizationId) + )?.enabled; return await this.getSecretsByProject(); }), ); 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 d24ff7a3b092..700be8e5d098 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 @@ -13,6 +13,7 @@ import { } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { DialogService } from "@bitwarden/components"; @@ -34,6 +35,7 @@ export class ProjectComponent implements OnInit, OnDestroy { private organizationId: string; private projectId: string; + private organizations: Organization[]; private organizationEnabled: boolean; private destroy$ = new Subject(); @@ -70,10 +72,14 @@ export class ProjectComponent implements OnInit, OnDestroy { }), ); + this.organizationService.organizations$.pipe(takeUntil(this.destroy$)).subscribe((orgs) => { + this.organizations = orgs; + }); + this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => { this.organizationId = params.organizationId; this.projectId = params.projectId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; + this.organizationEnabled = this.organizations[params.organizationId]?.enabled; }); } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts index 83541a37697c..831ee4df9bc9 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/projects/projects.component.ts @@ -51,7 +51,9 @@ export class ProjectsComponent implements OnInit { ]).pipe( switchMap(async ([params]) => { this.organizationId = params.organizationId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; + this.organizationEnabled = ( + await this.organizationService.get(params.organizationId) + )?.enabled; return await this.getProjects(); }), diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts index e944fbce0c70..b1bd91a04fbe 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/dialog/secret-dialog.component.ts @@ -87,7 +87,7 @@ export class SecretDialogComponent implements OnInit { this.formGroup.get("project").setValue(this.data.projectId); } - if (this.organizationService.get(this.data.organizationId)?.isAdmin) { + if ((await this.organizationService.get(this.data.organizationId))?.isAdmin) { this.formGroup.get("project").removeValidators(Validators.required); this.formGroup.get("project").updateValueAndValidity(); } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts index 64bbf479d882..a7413c9b59fd 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts @@ -47,7 +47,9 @@ export class SecretsComponent implements OnInit { combineLatestWith(this.route.params), switchMap(async ([_, params]) => { this.organizationId = params.organizationId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; + this.organizationEnabled = ( + await this.organizationService.get(params.organizationId) + )?.enabled; return await this.getSecrets(); }), diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts index a5e3cd29d247..d015cccd99d2 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts @@ -46,7 +46,9 @@ export class ServiceAccountsComponent implements OnInit { ]).pipe( switchMap(async ([params]) => { this.organizationId = params.organizationId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; + this.organizationEnabled = ( + await this.organizationService.get(params.organizationId) + )?.enabled; return await this.getServiceAccounts(); }), diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts index 482d2bb06b46..7ce6620afa46 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts @@ -26,7 +26,7 @@ describe("AccessPolicySelectorService", () => { describe("showAccessRemovalWarning", () => { it("returns false when current user is admin", async () => { const org = orgFactory(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = []; @@ -38,7 +38,7 @@ describe("AccessPolicySelectorService", () => { it("returns false when current user is owner", async () => { const org = orgFactory(); org.type = OrganizationUserType.Owner; - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = []; @@ -49,7 +49,7 @@ describe("AccessPolicySelectorService", () => { it("returns true when current user isn't owner/admin and all policies are removed", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = []; @@ -60,7 +60,7 @@ describe("AccessPolicySelectorService", () => { it("returns true when current user isn't owner/admin and user policy is set to canRead", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = []; selectedPolicyValues.push( @@ -77,7 +77,7 @@ describe("AccessPolicySelectorService", () => { it("returns false when current user isn't owner/admin and user policy is set to canReadWrite", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ @@ -93,7 +93,7 @@ describe("AccessPolicySelectorService", () => { it("returns true when current user isn't owner/admin and a group Read policy is submitted that the user is a member of", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ @@ -111,7 +111,7 @@ describe("AccessPolicySelectorService", () => { it("returns false when current user isn't owner/admin and a group ReadWrite policy is submitted that the user is a member of", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ @@ -129,7 +129,7 @@ describe("AccessPolicySelectorService", () => { it("returns true when current user isn't owner/admin and a group ReadWrite policy is submitted that the user is not a member of", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ @@ -147,7 +147,7 @@ describe("AccessPolicySelectorService", () => { it("returns false when current user isn't owner/admin, user policy is set to CanRead, and user is in read write group", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ @@ -169,7 +169,7 @@ describe("AccessPolicySelectorService", () => { it("returns true when current user isn't owner/admin, user policy is set to CanRead, and user is not in ReadWrite group", async () => { const org = setupUserOrg(); - organizationService.get.calledWith(org.id).mockReturnValue(org); + organizationService.get.calledWith(org.id).mockResolvedValue(org); const selectedPolicyValues: ApItemValueType[] = [ createApItemValueType({ diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts index 4a90172d45bf..b219bfd33d2e 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts @@ -17,7 +17,7 @@ export class AccessPolicySelectorService { organizationId: string, selectedPoliciesValues: ApItemValueType[], ): Promise { - const organization = this.organizationService.get(organizationId); + const organization = await this.organizationService.get(organizationId); if (organization.isOwner || organization.isAdmin) { return false; } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts index 6cb5722be048..b91948e02cea 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/new-menu.component.ts @@ -1,6 +1,6 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; -import { Subject, takeUntil } from "rxjs"; +import { Subject, takeUntil, concatMap } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { DialogService } from "@bitwarden/components"; @@ -34,10 +34,15 @@ export class NewMenuComponent implements OnInit, OnDestroy { ) {} ngOnInit() { - this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params: any) => { - this.organizationId = params.organizationId; - this.organizationEnabled = this.organizationService.get(params.organizationId)?.enabled; - }); + this.route.params + .pipe( + concatMap(async (params) => await this.organizationService.get(params.organizationId)), + takeUntil(this.destroy$), + ) + .subscribe((org) => { + this.organizationId = org.id; + this.organizationEnabled = org?.enabled; + }); } ngOnDestroy(): void { diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts index ee94a78bb83d..454576df9f73 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/org-suspended.component.ts @@ -1,6 +1,6 @@ import { Component } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; -import { map } from "rxjs"; +import { concatMap } from "rxjs"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Icon, Icons } from "@bitwarden/components"; @@ -16,6 +16,6 @@ export class OrgSuspendedComponent { protected NoAccess: Icon = Icons.NoAccess; protected organizationName$ = this.route.params.pipe( - map((params) => this.organizationService.get(params.organizationId)?.name), + concatMap(async (params) => (await this.organizationService.get(params.organizationId))?.name), ); } diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index b833a3b929c4..7834c8cc541c 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -704,7 +704,7 @@ import { ModalService } from "./modal.service"; { provide: OrganizationServiceAbstraction, useClass: OrganizationService, - deps: [StateServiceAbstraction, StateProvider], + deps: [StateProvider], }, { provide: InternalOrganizationServiceAbstraction, diff --git a/libs/angular/src/tools/export/components/export-scope-callout.component.ts b/libs/angular/src/tools/export/components/export-scope-callout.component.ts index 48651d822abf..545dfe4560aa 100644 --- a/libs/angular/src/tools/export/components/export-scope-callout.component.ts +++ b/libs/angular/src/tools/export/components/export-scope-callout.component.ts @@ -34,7 +34,7 @@ export class ExportScopeCalloutComponent implements OnInit { ) {} async ngOnInit(): Promise { - if (!this.organizationService.hasOrganizations()) { + if (!(await this.organizationService.hasOrganizations())) { return; } @@ -48,7 +48,7 @@ export class ExportScopeCalloutComponent implements OnInit { ? { title: "exportingOrganizationVaultTitle", description: "exportingOrganizationVaultDesc", - scopeIdentifier: this.organizationService.get(organizationId).name, + scopeIdentifier: (await this.organizationService.get(organizationId)).name, } : { title: "exportingPersonalVaultTitle", diff --git a/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts b/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts index 06fe8efc87ee..1423e061a11a 100644 --- a/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts +++ b/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts @@ -97,8 +97,7 @@ export abstract class OrganizationService { memberOrganizations$: Observable; get$: (id: string) => Observable; - get: (id: string) => Organization; - getByIdentifier: (identifier: string) => Organization; + get: (id: string) => Promise; getAll: (userId?: string) => Promise; /** * @deprecated For the CLI only @@ -106,7 +105,7 @@ export abstract class OrganizationService { */ getFromState: (id: string) => Promise; canManageSponsorships: () => Promise; - hasOrganizations: () => boolean; + hasOrganizations: () => Promise; } export abstract class InternalOrganizationServiceAbstraction extends OrganizationService { diff --git a/libs/common/src/admin-console/services/organization/organization.service.spec.ts b/libs/common/src/admin-console/services/organization/organization.service.spec.ts index a4b7e9588868..82a7ddd26f31 100644 --- a/libs/common/src/admin-console/services/organization/organization.service.spec.ts +++ b/libs/common/src/admin-console/services/organization/organization.service.spec.ts @@ -1,9 +1,7 @@ -import { MockProxy, mock, any, mockClear } from "jest-mock-extended"; -import { BehaviorSubject, firstValueFrom } from "rxjs"; +import { firstValueFrom } from "rxjs"; import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../../spec"; import { FakeActiveUserState } from "../../../../spec/fake-state"; -import { StateService } from "../../../platform/abstractions/state.service"; import { Utils } from "../../../platform/misc/utils"; import { UserId } from "../../../types/guid"; import { OrganizationData } from "../../models/data/organization.data"; @@ -13,27 +11,11 @@ import { OrganizationService, ORGANIZATIONS } from "./organization.service"; describe("Organization Service", () => { let organizationService: OrganizationService; - let stateService: MockProxy; - let activeAccount: BehaviorSubject; - let activeAccountUnlocked: BehaviorSubject; - const mockUserId = Utils.newGuid() as UserId; let accountService: FakeAccountService; let stateProvider: FakeStateProvider; let activeUserOrganizationsState: FakeActiveUserState>; - const resetStateService = async ( - customizeStateService: (stateService: MockProxy) => void, - ) => { - mockClear(stateService); - stateService = mock(); - stateService.activeAccount$ = activeAccount; - stateService.activeAccountUnlocked$ = activeAccountUnlocked; - customizeStateService(stateService); - organizationService = new OrganizationService(stateService, stateProvider); - await new Promise((r) => setTimeout(r, 50)); - }; - function prepareStateProvider(): void { accountService = mockAccountServiceWith(mockUserId); stateProvider = new FakeStateProvider(accountService); @@ -45,29 +27,11 @@ describe("Organization Service", () => { } beforeEach(() => { - activeAccount = new BehaviorSubject("123"); - activeAccountUnlocked = new BehaviorSubject(true); - - stateService = mock(); - stateService.activeAccount$ = activeAccount; - stateService.activeAccountUnlocked$ = activeAccountUnlocked; - - stateService.getOrganizations.calledWith(any()).mockResolvedValue({ - "1": organizationData("1", "Test Org"), - }); - prepareStateProvider(); - - organizationService = new OrganizationService(stateService, stateProvider); - + organizationService = new OrganizationService(stateProvider); seedTestData(); }); - afterEach(() => { - activeAccount.complete(); - activeAccountUnlocked.complete(); - }); - it("getAll", async () => { const orgs = await organizationService.getAll(); expect(orgs).toHaveLength(1); @@ -81,34 +45,25 @@ describe("Organization Service", () => { describe("canManageSponsorships", () => { it("can because one is available", async () => { - await resetStateService((stateService) => { - stateService.getOrganizations.mockResolvedValue({ - "1": { ...organizationData("1", "Org"), familySponsorshipAvailable: true }, - }); + activeUserOrganizationsState.nextState({ + "1": { ...organizationData("1", "Test Org"), familySponsorshipAvailable: true }, }); - const result = await organizationService.canManageSponsorships(); expect(result).toBe(true); }); it("can because one is used", async () => { - await resetStateService((stateService) => { - stateService.getOrganizations.mockResolvedValue({ - "1": { ...organizationData("1", "Test Org"), familySponsorshipFriendlyName: "Something" }, - }); + activeUserOrganizationsState.nextState({ + "1": { ...organizationData("1", "Test Org"), familySponsorshipFriendlyName: "Something" }, }); - const result = await organizationService.canManageSponsorships(); expect(result).toBe(true); }); it("can not because one isn't available or taken", async () => { - await resetStateService((stateService) => { - stateService.getOrganizations.mockResolvedValue({ - "1": { ...organizationData("1", "Org"), familySponsorshipFriendlyName: null }, - }); + activeUserOrganizationsState.nextState({ + "1": { ...organizationData("1", "Test Org"), familySponsorshipFriendlyName: null }, }); - const result = await organizationService.canManageSponsorships(); expect(result).toBe(false); }); @@ -116,7 +71,7 @@ describe("Organization Service", () => { describe("get", () => { it("exists", async () => { - const result = organizationService.get("1"); + const result = await organizationService.get("1"); expect(result).toEqual({ id: "1", @@ -126,62 +81,67 @@ describe("Organization Service", () => { }); it("does not exist", async () => { - const result = organizationService.get("2"); + const result = await organizationService.get("2"); expect(result).toBe(undefined); }); }); - it("upsert", async () => { - await organizationService.upsert(organizationData("2", "Test 2")); - - expect(await firstValueFrom(organizationService.organizations$)).toEqual([ - { - id: "1", - name: "Test Org", - identifier: "test", - }, - { - id: "2", - name: "Test 2", - identifier: "test", - }, - ]); - }); - - describe("getByIdentifier", () => { - it("exists", async () => { - const result = organizationService.getByIdentifier("test"); - - expect(result).toEqual({ - id: "1", - name: "Test Org", - identifier: "test", - }); + describe("upsert", () => { + it("Replaces an existing organization in state", async () => { + await organizationService.upsert(organizationData("1", "UPDATED")); + expect(await firstValueFrom(organizationService.organizations$)).toEqual([ + { + id: "1", + name: "UPDATED", + identifier: "test", + }, + ]); }); - - it("does not exist", async () => { - const result = organizationService.getByIdentifier("blah"); - - expect(result).toBeUndefined(); + it("Adds a new organization to state if input does not exist", async () => { + await organizationService.upsert(organizationData("2", "Test 2")); + expect(await firstValueFrom(organizationService.organizations$)).toEqual([ + { + id: "1", + name: "Test Org", + identifier: "test", + }, + { + id: "2", + name: "Test 2", + identifier: "test", + }, + ]); }); }); describe("delete", () => { - it("exists", async () => { + it("deletes one organization from state for the active user", async () => { await organizationService.delete("1"); - - expect(stateService.getOrganizations).toHaveBeenCalledTimes(2); - - expect(stateService.setOrganizations).toHaveBeenCalledTimes(1); + expect((await firstValueFrom(organizationService.organizations$)).length).toBe(0); }); + it("ignores requests with invalid organization ids", async () => { + const originalOrganizationCount = (await firstValueFrom(organizationService.organizations$)) + .length; + await organizationService.delete("BADID"); + expect((await firstValueFrom(organizationService.organizations$)).length).toBe( + originalOrganizationCount, + ); + }); + }); - it("does not exist", async () => { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - organizationService.delete("1"); - - expect(stateService.getOrganizations).toHaveBeenCalledTimes(2); + describe("replace", () => { + it("replaces all organization data in state", async () => { + await organizationService.replace({ + "2": organizationData("2", "Test Org 2"), + }); + expect(await firstValueFrom(organizationService.organizations$)).toEqual([ + { + id: "2", + name: "Test Org 2", + identifier: "test", + }, + ]); }); }); diff --git a/libs/common/src/admin-console/services/organization/organization.service.ts b/libs/common/src/admin-console/services/organization/organization.service.ts index 2c2c8b4e36a6..47dc6ac51c4a 100644 --- a/libs/common/src/admin-console/services/organization/organization.service.ts +++ b/libs/common/src/admin-console/services/organization/organization.service.ts @@ -1,8 +1,8 @@ -import { BehaviorSubject, concatMap, map, Observable } from "rxjs"; +import { firstValueFrom, map, Observable } from "rxjs"; import { Jsonify } from "type-fest"; -import { StateService } from "../../../platform/abstractions/state.service"; import { KeyDefinition, ORGANIZATIONS_DISK, StateProvider } from "../../../platform/state"; +import { UserId } from "../../../types/guid"; import { InternalOrganizationServiceAbstraction, isMember, @@ -19,91 +19,65 @@ export const ORGANIZATIONS = KeyDefinition.record( ); export class OrganizationService implements InternalOrganizationServiceAbstraction { - // marked for removal during AC-2009 - protected _organizations = new BehaviorSubject([]); - // marked for removal during AC-2009 - organizations$ = this._organizations.asObservable(); - // marked for removal during AC-2009 - memberOrganizations$ = this.organizations$.pipe(map((orgs) => orgs.filter(isMember))); + organizations$: Observable; + memberOrganizations$: Observable; - activeUserOrganizations$: Observable; - activeUserMemberOrganizations$: Observable; - - constructor( - private stateService: StateService, - private stateProvider: StateProvider, - ) { - this.activeUserOrganizations$ = this.stateProvider + constructor(private stateProvider: StateProvider) { + this.organizations$ = this.stateProvider .getActive(ORGANIZATIONS) - .state$.pipe(map((data) => Object.values(data).map((o) => new Organization(o)))); - - this.activeUserMemberOrganizations$ = this.activeUserOrganizations$.pipe( - map((orgs) => orgs.filter(isMember)), - ); - - this.stateService.activeAccountUnlocked$ - .pipe( - concatMap(async (unlocked) => { - if (!unlocked) { - this._organizations.next([]); - return; - } - - const data = await this.stateService.getOrganizations(); - this.updateObservables(data); - }), - ) - .subscribe(); + .state$.pipe(map((data) => Object.values(data ?? {})?.map((o) => new Organization(o)))); + this.memberOrganizations$ = this.organizations$.pipe(map((orgs) => orgs.filter(isMember))); } get$(id: string): Observable { return this.organizations$.pipe(map((orgs) => orgs.find((o) => o.id === id))); } - async getAll(userId?: string): Promise { - const organizationsMap = await this.stateService.getOrganizations({ userId: userId }); - return Object.values(organizationsMap || {}).map((o) => new Organization(o)); + async getAll(userId?: UserId): Promise { + const orgs = userId + ? await firstValueFrom( + this.stateProvider + .getUser(userId, ORGANIZATIONS) + .state$.pipe(map((data) => Object.values(data ?? {})?.map((o) => new Organization(o)))), + ) + : await firstValueFrom(this.organizations$); + return orgs; } async canManageSponsorships(): Promise { - const organizations = this._organizations.getValue(); + const organizations = await firstValueFrom(this.organizations$); return organizations.some( (o) => o.familySponsorshipAvailable || o.familySponsorshipFriendlyName !== null, ); } - hasOrganizations(): boolean { - const organizations = this._organizations.getValue(); + async hasOrganizations(): Promise { + const organizations = await firstValueFrom(this.organizations$); return organizations.length > 0; } async upsert(organization: OrganizationData): Promise { - let organizations = await this.stateService.getOrganizations(); - if (organizations == null) { - organizations = {}; - } - - organizations[organization.id] = organization; - - await this.replace(organizations); + await this.stateProvider.getActive(ORGANIZATIONS).update((organizations) => { + if (organizations == null) { + organizations = {}; + } + organizations[organization.id] = organization; + return organizations; + }); } async delete(id: string): Promise { - const organizations = await this.stateService.getOrganizations(); - if (organizations == null) { - return; - } - - if (organizations[id] == null) { - return; - } - - delete organizations[id]; - await this.replace(organizations); + await this.stateProvider.getActive(ORGANIZATIONS).update((organizations) => { + if (organizations == null || organizations[id] == null) { + return organizations; + } + delete organizations[id]; + return organizations; + }); } - get(id: string): Organization { - const organizations = this._organizations.getValue(); + async get(id: string): Promise { + const organizations = await firstValueFrom(this.organizations$); return organizations.find((organization) => organization.id === id); } @@ -113,8 +87,8 @@ export class OrganizationService implements InternalOrganizationServiceAbstracti * @param id id of the organization */ async getFromState(id: string): Promise { - const organizationsMap = await this.stateService.getOrganizations(); - const organization = organizationsMap[id]; + const organizationsMap = await firstValueFrom(this.organizations$); + const organization = organizationsMap.find((x) => x.id === id); if (organization == null) { return null; } @@ -122,19 +96,12 @@ export class OrganizationService implements InternalOrganizationServiceAbstracti return new Organization(organization); } - getByIdentifier(identifier: string): Organization { - const organizations = this._organizations.getValue(); - - return organizations.find((organization) => organization.identifier === identifier); - } - async replace(organizations: { [id: string]: OrganizationData }) { - await this.stateService.setOrganizations(organizations); - this.updateObservables(organizations); - } - - private updateObservables(organizationsMap: { [id: string]: OrganizationData }) { - const organizations = Object.values(organizationsMap || {}).map((o) => new Organization(o)); - this._organizations.next(organizations); + await this.stateProvider.getActive(ORGANIZATIONS).update(() => { + const updatedOrganizations: Record = { + ...organizations, + }; + return updatedOrganizations; + }); } } diff --git a/libs/importer/src/components/import.component.ts b/libs/importer/src/components/import.component.ts index 796f02c77614..dfbe8d8c5e98 100644 --- a/libs/importer/src/components/import.component.ts +++ b/libs/importer/src/components/import.component.ts @@ -207,7 +207,7 @@ export class ImportComponent implements OnInit, OnDestroy { this.setImportOptions(); await this.initializeOrganizations(); - if (this.organizationId && this.canAccessImportExport(this.organizationId)) { + if (this.organizationId && (await this.canAccessImportExport(this.organizationId))) { this.handleOrganizationImportInit(); } else { this.handleImportInit(); @@ -359,7 +359,7 @@ export class ImportComponent implements OnInit, OnDestroy { importContents, this.organizationId, this.formGroup.controls.targetSelector.value, - this.canAccessImportExport(this.organizationId) && this._isFromAC, + (await this.canAccessImportExport(this.organizationId)) && this._isFromAC, ); //No errors, display success message @@ -379,11 +379,11 @@ export class ImportComponent implements OnInit, OnDestroy { } } - private canAccessImportExport(organizationId?: string): boolean { + private async canAccessImportExport(organizationId?: string): Promise { if (!organizationId) { return false; } - return this.organizationService.get(this.organizationId)?.canAccessImportExport; + return (await this.organizationService.get(this.organizationId))?.canAccessImportExport; } getFormatInstructionTitle() {