1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 15:23:33 +00:00

Migrate OrganizationService to StateProvider (#7895)

This commit is contained in:
Addison Beck
2024-03-18 11:58:33 -05:00
committed by GitHub
parent 087d174194
commit c7abdb9879
47 changed files with 855 additions and 380 deletions

View File

@@ -1,4 +1,5 @@
import { OrganizationService as AbstractOrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import {
FactoryOptions,
@@ -6,11 +7,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 { BrowserOrganizationService } from "../../services/browser-organization.service";
import { StateServiceInitOptions } from "../../../platform/background/service-factories/state-service.factory";
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 OrganizationService(await stateProviderFactory(cache, opts)),
);
}

View File

@@ -1,12 +0,0 @@
import { BehaviorSubject } from "rxjs";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { browserSession, sessionSync } from "../../platform/decorators/session-sync-observable";
@browserSession
export class BrowserOrganizationService extends OrganizationService {
@sessionSync({ initializer: Organization.fromJSON, initializeAs: "array" })
protected _organizations: BehaviorSubject<Organization[]>;
}

View File

@@ -20,6 +20,7 @@ import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
@@ -182,7 +183,6 @@ import {
VaultExportServiceAbstraction,
} from "@bitwarden/vault-export-core";
import { BrowserOrganizationService } from "../admin-console/services/browser-organization.service";
import ContextMenusBackground from "../autofill/background/context-menus.background";
import NotificationBackground from "../autofill/background/notification.background";
import OverlayBackground from "../autofill/background/overlay.background";
@@ -502,10 +502,7 @@ export default class MainBackground {
this.stateProvider,
);
this.syncNotifierService = new SyncNotifierService();
this.organizationService = new BrowserOrganizationService(
this.stateService,
this.stateProvider,
);
this.organizationService = new OrganizationService(this.stateProvider);
this.policyService = new PolicyService(this.stateProvider, this.organizationService);
this.autofillSettingsService = new AutofillSettingsService(
this.stateProvider,

View File

@@ -98,7 +98,6 @@ import { DialogService } from "@bitwarden/components";
import { ImportServiceAbstraction } from "@bitwarden/importer/core";
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
import { BrowserOrganizationService } from "../../admin-console/services/browser-organization.service";
import { UnauthGuardService } from "../../auth/popup/services";
import { AutofillService } from "../../autofill/services/abstractions/autofill.service";
import MainBackground from "../../background/main.background";
@@ -398,13 +397,6 @@ function getBgService<T>(service: keyof MainBackground) {
useFactory: getBgService<NotificationsService>("notificationsService"),
deps: [],
},
{
provide: OrganizationService,
useFactory: (stateService: StateServiceAbstraction, stateProvider: StateProvider) => {
return new BrowserOrganizationService(stateService, stateProvider);
},
deps: [StateServiceAbstraction, StateProvider],
},
{
provide: VaultFilterService,
useClass: VaultFilterService,

View File

@@ -275,7 +275,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
const dontShowIdentities = !(await firstValueFrom(
this.vaultSettingsService.showIdentitiesCurrentTab$,
));
this.showOrganizations = this.organizationService.hasOrganizations();
this.showOrganizations = await this.organizationService.hasOrganizations();
if (!dontShowCards) {
otherTypes.push(CipherType.Card);
}

View File

@@ -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) => {

View File

@@ -410,7 +410,7 @@ export class Main {
this.providerService = new ProviderService(this.stateProvider);
this.organizationService = new OrganizationService(this.stateService, this.stateProvider);
this.organizationService = new OrganizationService(this.stateProvider);
this.organizationUserService = new OrganizationUserServiceImplementation(this.apiService);

View File

@@ -22,6 +22,7 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
@@ -153,6 +154,7 @@ export class AppComponent implements OnInit, OnDestroy {
private biometricStateService: BiometricStateService,
private stateEventRunnerService: StateEventRunnerService,
private providerService: ProviderService,
private organizationService: InternalOrganizationServiceAbstraction,
) {}
ngOnInit() {

View File

@@ -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(["/"]);

View File

@@ -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);

View File

@@ -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(["/"]);
}

View File

@@ -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) {

View File

@@ -143,7 +143,7 @@ export class PeopleComponent
async ngOnInit() {
const organization$ = this.route.params.pipe(
map((params) => this.organizationService.get(params.organizationId)),
concatMap((params) => this.organizationService.get$(params.organizationId)),
shareReplay({ refCount: true, bufferSize: 1 }),
);

View File

@@ -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";
@@ -28,7 +28,7 @@ export class ReportsHomeComponent implements OnInit {
);
this.reports$ = this.route.params.pipe(
map((params) => this.organizationService.get(params.organizationId)),
concatMap((params) => this.organizationService.get$(params.organizationId)),
map((org) => this.buildReports(org.isFreeOrg)),
);
}

View File

@@ -1,6 +1,6 @@
import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { concatMap, takeUntil } from "rxjs";
import { concatMap, takeUntil, map } from "rxjs";
import { tap } from "rxjs/operators";
import { ModalService } from "@bitwarden/angular/services/modal.service";
@@ -42,9 +42,14 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent {
async ngOnInit() {
this.route.params
.pipe(
tap((params) => {
this.organizationId = params.organizationId;
this.organization = this.organizationService.get(this.organizationId);
concatMap((params) =>
this.organizationService
.get$(params.organizationId)
.pipe(map((organization) => ({ params, organization }))),
),
tap(async (mapResponse) => {
this.organizationId = mapResponse.params.organizationId;
this.organization = mapResponse.organization;
}),
concatMap(async () => await super.ngOnInit()),
takeUntil(this.destroy$),

View File

@@ -11,7 +11,7 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
@@ -92,7 +92,7 @@ export class AppComponent implements OnDestroy, OnInit {
private biometricStateService: BiometricStateService,
private stateEventRunnerService: StateEventRunnerService,
private paymentMethodWarningService: PaymentMethodWarningService,
private organizationService: OrganizationService,
private organizationService: InternalOrganizationServiceAbstraction,
) {}
ngOnInit() {

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -139,9 +139,9 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
}
async loadOrg(orgId: string, collectionIds: string[]) {
const organization$ = of(this.organizationService.get(orgId)).pipe(
shareReplay({ refCount: true, bufferSize: 1 }),
);
const organization$ = this.organizationService
.get$(orgId)
.pipe(shareReplay({ refCount: true, bufferSize: 1 }));
const groups$ = organization$.pipe(
switchMap((organization) => {
if (!organization.useGroups) {

View File

@@ -518,7 +518,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,
@@ -697,7 +697,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
async deleteCollection(collection: CollectionView): Promise<void> {
const organization = this.organizationService.get(collection.organizationId);
const organization = await this.organizationService.get(collection.organizationId);
if (!collection.canDelete(organization)) {
this.platformUtilsService.showToast(
"error",