From 7f51254680cab30c7f91104fd6318d597ab476df Mon Sep 17 00:00:00 2001 From: --global <> Date: Wed, 15 Jan 2025 17:39:34 -0500 Subject: [PATCH 01/13] Removing ActiveUserState from vault-onboarding.service.ts --- .../abstraction/vault-onboarding.service.ts | 4 +++- .../services/vault-onboarding.service.ts | 14 ++++++++------ .../vault-onboarding/vault-onboarding.component.ts | 11 +++++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index 379c97672e7..c4fd4f7de91 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -2,9 +2,11 @@ // @ts-strict-ignore import { Observable } from "rxjs"; +import { UserId } from "@bitwarden/common/types/guid"; + import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { - vaultOnboardingState$: Observable; abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; + abstract getVaultOnboardingState$(userId: UserId): Observable; } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 95cb568a840..3f44c00a6b0 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -1,14 +1,13 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Injectable } from "@angular/core"; import { Observable } from "rxjs"; import { - ActiveUserState, + SingleUserState, StateProvider, UserKeyDefinition, VAULT_ONBOARDING, } from "@bitwarden/common/platform/state"; +import { UserId } from "@bitwarden/common/types/guid"; import { VaultOnboardingService as VaultOnboardingServiceAbstraction } from "./abstraction/vault-onboarding.service"; @@ -29,12 +28,15 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( @Injectable() export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { - private vaultOnboardingState: ActiveUserState; + private vaultOnboardingState: SingleUserState; vaultOnboardingState$: Observable; - constructor(private stateProvider: StateProvider) { - this.vaultOnboardingState = this.stateProvider.getActive(VAULT_ONBOARDING_KEY); + constructor(private stateProvider: StateProvider) {} + + getVaultOnboardingState$(userId: UserId): Observable { + this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); this.vaultOnboardingState$ = this.vaultOnboardingState.state$; + return this.vaultOnboardingState$; } async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index 3535d31852e..870d879773f 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -11,13 +11,14 @@ import { SimpleChanges, OnChanges, } from "@angular/core"; -import { Subject, takeUntil, Observable, firstValueFrom, fromEvent } from "rxjs"; +import { Subject, takeUntil, Observable, firstValueFrom, fromEvent, switchMap, map } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } 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 { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -60,16 +61,22 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { protected showOnboarding = false; protected extensionRefreshEnabled = false; + private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id)); + constructor( protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, private apiService: ApiService, private vaultOnboardingService: VaultOnboardingServiceAbstraction, private configService: ConfigService, + private accountService: AccountService, ) {} async ngOnInit() { - this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$; + this.onboardingTasks$ = this.activeUserId$.pipe( + switchMap((userId) => this.vaultOnboardingService.getVaultOnboardingState$(userId)), + ); + await this.setOnboardingTasks(); this.setInstallExtLink(); this.individualVaultPolicyCheck(); From 67c9019fa074f94589a4b73f44343434b9f15fbf Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 14:21:24 -0500 Subject: [PATCH 02/13] changes --- .../services/abstraction/vault-onboarding.service.ts | 2 +- .../vault-onboarding/services/vault-onboarding.service.ts | 7 ++----- .../vault-onboarding/vault-onboarding.component.ts | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index c4fd4f7de91..18a052dc16d 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -8,5 +8,5 @@ import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; - abstract getVaultOnboardingState$(userId: UserId): Observable; + abstract vaultOnboardingState$(userId: UserId): Observable; } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 3f44c00a6b0..9e79efbcddc 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -29,16 +29,13 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( @Injectable() export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { private vaultOnboardingState: SingleUserState; - vaultOnboardingState$: Observable; constructor(private stateProvider: StateProvider) {} - getVaultOnboardingState$(userId: UserId): Observable { + vaultOnboardingState$(userId: UserId): Observable { this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); - this.vaultOnboardingState$ = this.vaultOnboardingState.state$; - return this.vaultOnboardingState$; + return this.vaultOnboardingState.state$; } - async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { await this.vaultOnboardingState.update(() => { return { ...newState }; diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index 870d879773f..956b867e183 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -74,7 +74,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { async ngOnInit() { this.onboardingTasks$ = this.activeUserId$.pipe( - switchMap((userId) => this.vaultOnboardingService.getVaultOnboardingState$(userId)), + switchMap((userId) => this.vaultOnboardingService.vaultOnboardingState$(userId)), ); await this.setOnboardingTasks(); From 063a7ef37e51040ffb2447a281032b83fde11fdb Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 15:16:32 -0500 Subject: [PATCH 03/13] trying to fix tests --- .../vault-onboarding/services/vault-onboarding.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 9e79efbcddc..4cc3682b137 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -28,7 +28,7 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( @Injectable() export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { - private vaultOnboardingState: SingleUserState; + private vaultOnboardingState?: SingleUserState; constructor(private stateProvider: StateProvider) {} From 08be4a188638d18f11287230dd6b73105cab6494 Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 15:28:46 -0500 Subject: [PATCH 04/13] test fixes --- .../vault-onboarding/services/vault-onboarding.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 4cc3682b137..f1258d1d927 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -28,16 +28,16 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( @Injectable() export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { - private vaultOnboardingState?: SingleUserState; + private vaultOnboardingState?: SingleUserState = null; constructor(private stateProvider: StateProvider) {} - vaultOnboardingState$(userId: UserId): Observable { + vaultOnboardingState$(userId: UserId): Observable { this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); return this.vaultOnboardingState.state$; } async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { - await this.vaultOnboardingState.update(() => { + await this.vaultOnboardingState?.update(() => { return { ...newState }; }); } From 13089536b343e8e91620f036145793b9937d25d8 Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 18:47:59 -0500 Subject: [PATCH 05/13] test fixes --- .../vault-onboarding.component.spec.ts | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts index e017bc9b35d..296a360699b 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts @@ -7,10 +7,14 @@ import { Subject, of } from "rxjs"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; import { StateProvider } from "@bitwarden/common/platform/state"; +import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec"; +import { UserId } from "@bitwarden/common/types/guid"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; @@ -29,6 +33,7 @@ describe("VaultOnboardingComponent", () => { let setInstallExtLinkSpy: any; let individualVaultPolicyCheckSpy: any; let mockConfigService: MockProxy; + const mockAccountService: FakeAccountService = mockAccountServiceWith(Utils.newGuid() as UserId); beforeEach(() => { mockPolicyService = mock(); @@ -39,7 +44,7 @@ describe("VaultOnboardingComponent", () => { }; mockVaultOnboardingService = mock(); mockStateProvider = { - getActive: jest.fn().mockReturnValue( + getUser: jest.fn().mockReturnValue( of({ createAccount: true, importData: false, @@ -61,6 +66,7 @@ describe("VaultOnboardingComponent", () => { { provide: ApiService, useValue: mockApiService }, { provide: StateProvider, useValue: mockStateProvider }, { provide: ConfigService, useValue: mockConfigService }, + { provide: AccountService, useValue: mockAccountService }, ], }).compileComponents(); fixture = TestBed.createComponent(VaultOnboardingComponent); @@ -71,11 +77,15 @@ describe("VaultOnboardingComponent", () => { .mockReturnValue(undefined); jest.spyOn(component, "checkCreationDate").mockReturnValue(null); jest.spyOn(window, "postMessage").mockImplementation(jest.fn()); - (component as any).vaultOnboardingService.vaultOnboardingState$ = of({ - createAccount: true, - importData: false, - installExtension: false, - }); + (component as any).vaultOnboardingService.vaultOnboardingState$ = jest + .fn() + .mockImplementation(() => { + return of({ + createAccount: true, + importData: false, + installExtension: false, + }); + }); }); it("should create", () => { @@ -169,12 +179,15 @@ describe("VaultOnboardingComponent", () => { .spyOn((component as any).vaultOnboardingService, "setVaultOnboardingTasks") .mockReturnValue(Promise.resolve()); - (component as any).vaultOnboardingService.vaultOnboardingState$ = of({ - createAccount: true, - importData: false, - installExtension: false, - }); - + (component as any).vaultOnboardingService.vaultOnboardingState$ = jest + .fn() + .mockImplementation(() => { + return of({ + createAccount: true, + importData: false, + installExtension: false, + }); + }); const eventData = { data: { command: VaultOnboardingMessages.HasBwInstalled } }; (component as any).showOnboarding = true; From bdc021be2707c5d62a4d8f209904af1f3bc10e17 Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 19:10:37 -0500 Subject: [PATCH 06/13] fixing tests --- .../services/abstraction/vault-onboarding.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index 18a052dc16d..21bd3ab245f 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -8,5 +8,5 @@ import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; - abstract vaultOnboardingState$(userId: UserId): Observable; + abstract vaultOnboardingState$(userId: UserId): Observable; } From 67b1d39fef75c472283c14071d77606932edcead Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 17 Jan 2025 19:29:29 -0500 Subject: [PATCH 07/13] fxies --- .../abstraction/vault-onboarding.service.ts | 2 +- .../services/vault-onboarding.service.ts | 26 ++++++++++++++----- .../vault-onboarding.component.spec.ts | 1 + 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index 21bd3ab245f..18a052dc16d 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -8,5 +8,5 @@ import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; - abstract vaultOnboardingState$(userId: UserId): Observable; + abstract vaultOnboardingState$(userId: UserId): Observable; } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index f1258d1d927..1ecb883f49d 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from "@angular/core"; -import { Observable } from "rxjs"; +import { Injectable, OnDestroy } from "@angular/core"; +import { Observable, Subject, takeUntil } from "rxjs"; import { SingleUserState, @@ -27,17 +27,29 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( ); @Injectable() -export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { - private vaultOnboardingState?: SingleUserState = null; +export class VaultOnboardingService implements VaultOnboardingServiceAbstraction, OnDestroy { + private destroy$ = new Subject(); + private vaultOnboardingState: SingleUserState | undefined; - constructor(private stateProvider: StateProvider) {} + constructor(private stateProvider: StateProvider) { + this.stateProvider.activeUserId$.pipe(takeUntil(this.destroy$)).subscribe((userId) => { + if (userId) { + this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); + } + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } - vaultOnboardingState$(userId: UserId): Observable { + vaultOnboardingState$(userId: UserId): Observable { this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); return this.vaultOnboardingState.state$; } async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { - await this.vaultOnboardingState?.update(() => { + await this.vaultOnboardingState.update(() => { return { ...newState }; }); } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts index 296a360699b..c8b30b2d50e 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts @@ -44,6 +44,7 @@ describe("VaultOnboardingComponent", () => { }; mockVaultOnboardingService = mock(); mockStateProvider = { + activeUserId$: of(Utils.newGuid() as UserId), getUser: jest.fn().mockReturnValue( of({ createAccount: true, From e3ef0f35ba42af930cf52dc80ad09afde199ef68 Mon Sep 17 00:00:00 2001 From: --global <> Date: Tue, 21 Jan 2025 14:09:36 -0500 Subject: [PATCH 08/13] fixes --- .../abstraction/vault-onboarding.service.ts | 2 +- .../services/vault-onboarding.service.ts | 33 +++++-------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index 18a052dc16d..21bd3ab245f 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -8,5 +8,5 @@ import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; - abstract vaultOnboardingState$(userId: UserId): Observable; + abstract vaultOnboardingState$(userId: UserId): Observable; } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 1ecb883f49d..1832ee16155 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -1,5 +1,5 @@ -import { Injectable, OnDestroy } from "@angular/core"; -import { Observable, Subject, takeUntil } from "rxjs"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; import { SingleUserState, @@ -25,32 +25,17 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( clearOn: [], // do not clear tutorials }, ); - @Injectable() -export class VaultOnboardingService implements VaultOnboardingServiceAbstraction, OnDestroy { - private destroy$ = new Subject(); - private vaultOnboardingState: SingleUserState | undefined; - - constructor(private stateProvider: StateProvider) { - this.stateProvider.activeUserId$.pipe(takeUntil(this.destroy$)).subscribe((userId) => { - if (userId) { - this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); - } - }); - } +export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { + vaultOnboardingTasksState: SingleUserState | null = null; + constructor(private stateProvider: StateProvider) {} - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); + vaultOnboardingState$(userId: UserId): Observable { + this.vaultOnboardingTasksState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); + return this.vaultOnboardingTasksState.state$; } - vaultOnboardingState$(userId: UserId): Observable { - this.vaultOnboardingState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); - return this.vaultOnboardingState.state$; - } async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { - await this.vaultOnboardingState.update(() => { - return { ...newState }; - }); + await this.vaultOnboardingTasksState?.update(() => ({ ...newState })); } } From 2e1d788bfc2a506d8a62af0b6ad3483d88fcbc87 Mon Sep 17 00:00:00 2001 From: cd-bitwarden <106776772+cd-bitwarden@users.noreply.github.com> Date: Sun, 26 Jan 2025 18:04:47 -0500 Subject: [PATCH 09/13] Update apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts Co-authored-by: SmithThe4th --- .../vault-onboarding/vault-onboarding.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts index c8b30b2d50e..11d56c402ac 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts @@ -65,7 +65,7 @@ describe("VaultOnboardingComponent", () => { { provide: VaultOnboardingServiceAbstraction, useValue: mockVaultOnboardingService }, { provide: I18nService, useValue: mockI18nService }, { provide: ApiService, useValue: mockApiService }, - { provide: StateProvider, useValue: mockStateProvider }, + { provide: StateProvider, useValue: fakeStateProvider }, { provide: ConfigService, useValue: mockConfigService }, { provide: AccountService, useValue: mockAccountService }, ], From d1cf1343eeab6c09233bcbab98fde065b3939224 Mon Sep 17 00:00:00 2001 From: --global <> Date: Sun, 26 Jan 2025 19:04:14 -0500 Subject: [PATCH 10/13] suggested changes --- .../abstraction/vault-onboarding.service.ts | 4 +--- .../services/vault-onboarding.service.ts | 13 ++++++++----- .../vault-onboarding.component.spec.ts | 18 ++++++------------ .../vault-onboarding.component.ts | 18 +++++++++--------- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts index 21bd3ab245f..7d3ff32c0f8 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/abstraction/vault-onboarding.service.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { Observable } from "rxjs"; import { UserId } from "@bitwarden/common/types/guid"; @@ -7,6 +5,6 @@ import { UserId } from "@bitwarden/common/types/guid"; import { VaultOnboardingTasks } from "../vault-onboarding.service"; export abstract class VaultOnboardingService { - abstract setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise; + abstract setVaultOnboardingTasks(userId: UserId, newState: VaultOnboardingTasks): Promise; abstract vaultOnboardingState$(userId: UserId): Observable; } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts index 1832ee16155..e6f8b815484 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/services/vault-onboarding.service.ts @@ -27,15 +27,18 @@ const VAULT_ONBOARDING_KEY = new UserKeyDefinition( ); @Injectable() export class VaultOnboardingService implements VaultOnboardingServiceAbstraction { - vaultOnboardingTasksState: SingleUserState | null = null; constructor(private stateProvider: StateProvider) {} + private vaultOnboardingState(userId: UserId): SingleUserState { + return this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); + } + vaultOnboardingState$(userId: UserId): Observable { - this.vaultOnboardingTasksState = this.stateProvider.getUser(userId, VAULT_ONBOARDING_KEY); - return this.vaultOnboardingTasksState.state$; + return this.vaultOnboardingState(userId).state$; } - async setVaultOnboardingTasks(newState: VaultOnboardingTasks): Promise { - await this.vaultOnboardingTasksState?.update(() => ({ ...newState })); + async setVaultOnboardingTasks(userId: UserId, newState: VaultOnboardingTasks): Promise { + const state = this.vaultOnboardingState(userId); + await state.update(() => ({ ...newState })); } } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts index 11d56c402ac..330b2d3f2d5 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.spec.ts @@ -13,7 +13,11 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { StateProvider } from "@bitwarden/common/platform/state"; -import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec"; +import { + FakeAccountService, + FakeStateProvider, + mockAccountServiceWith, +} from "@bitwarden/common/spec"; import { UserId } from "@bitwarden/common/types/guid"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; @@ -29,11 +33,11 @@ describe("VaultOnboardingComponent", () => { let mockPolicyService: MockProxy; let mockI18nService: MockProxy; let mockVaultOnboardingService: MockProxy; - let mockStateProvider: Partial; let setInstallExtLinkSpy: any; let individualVaultPolicyCheckSpy: any; let mockConfigService: MockProxy; const mockAccountService: FakeAccountService = mockAccountServiceWith(Utils.newGuid() as UserId); + const fakeStateProvider = new FakeStateProvider(mockAccountService); beforeEach(() => { mockPolicyService = mock(); @@ -43,16 +47,6 @@ describe("VaultOnboardingComponent", () => { getProfile: jest.fn(), }; mockVaultOnboardingService = mock(); - mockStateProvider = { - activeUserId$: of(Utils.newGuid() as UserId), - getUser: jest.fn().mockReturnValue( - of({ - createAccount: true, - importData: false, - installExtension: false, - }), - ), - }; mockConfigService = mock(); // eslint-disable-next-line @typescript-eslint/no-floating-promises diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index 956b867e183..0c9bea881da 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -11,7 +11,7 @@ import { SimpleChanges, OnChanges, } from "@angular/core"; -import { Subject, takeUntil, Observable, firstValueFrom, fromEvent, switchMap, map } from "rxjs"; +import { Subject, takeUntil, Observable, firstValueFrom, fromEvent } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; @@ -19,9 +19,11 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli import { PolicyType } 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 { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { UserId } from "@bitwarden/common/types/guid"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; @@ -61,8 +63,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { protected showOnboarding = false; protected extensionRefreshEnabled = false; - private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id)); - + private activeId: UserId; constructor( protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, @@ -73,9 +74,8 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { ) {} async ngOnInit() { - this.onboardingTasks$ = this.activeUserId$.pipe( - switchMap((userId) => this.vaultOnboardingService.vaultOnboardingState$(userId)), - ); + this.activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); + this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$(this.activeId); await this.setOnboardingTasks(); this.setInstallExtLink(); @@ -94,7 +94,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { importData: this.ciphers.length > 0, installExtension: currentTasks.installExtension, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); } } @@ -123,7 +123,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { importData: currentTasks.importData, installExtension: true, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); } } @@ -166,7 +166,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { private async saveCompletedTasks(vaultTasks: VaultOnboardingTasks) { this.showOnboarding = Object.values(vaultTasks).includes(false); - await this.vaultOnboardingService.setVaultOnboardingTasks(vaultTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, vaultTasks); } individualVaultPolicyCheck() { From 9c54d299abac995d64e6378b09a3cd60f62d1fb8 Mon Sep 17 00:00:00 2001 From: --global <> Date: Tue, 28 Jan 2025 17:28:28 -0500 Subject: [PATCH 11/13] suggested changes --- .../vault-onboarding.component.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index 0c9bea881da..dd17998f516 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -23,7 +23,6 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { UserId } from "@bitwarden/common/types/guid"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; @@ -63,7 +62,6 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { protected showOnboarding = false; protected extensionRefreshEnabled = false; - private activeId: UserId; constructor( protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, @@ -74,8 +72,8 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { ) {} async ngOnInit() { - this.activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$(this.activeId); + const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); + this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$(activeId); await this.setOnboardingTasks(); this.setInstallExtLink(); @@ -88,13 +86,14 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { async ngOnChanges(changes: SimpleChanges) { if (this.showOnboarding && changes?.ciphers) { + const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); const currentTasks = await firstValueFrom(this.onboardingTasks$); const updatedTasks = { createAccount: true, importData: this.ciphers.length > 0, installExtension: currentTasks.installExtension, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, updatedTasks); } } @@ -117,13 +116,14 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { async getMessages(event: any) { if (event.data.command === VaultOnboardingMessages.HasBwInstalled && this.showOnboarding) { + const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); const currentTasks = await firstValueFrom(this.onboardingTasks$); const updatedTasks = { createAccount: currentTasks.createAccount, importData: currentTasks.importData, installExtension: true, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, updatedTasks); } } @@ -166,7 +166,8 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { private async saveCompletedTasks(vaultTasks: VaultOnboardingTasks) { this.showOnboarding = Object.values(vaultTasks).includes(false); - await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, vaultTasks); + const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); + await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, vaultTasks); } individualVaultPolicyCheck() { From 500cf8087b677e3fc1e959f03799beb27334c4ed Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 31 Jan 2025 11:13:02 -0500 Subject: [PATCH 12/13] undoing suggested changes --- .../vault-onboarding/vault-onboarding.component.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index dd17998f516..64490b9c179 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -62,6 +62,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { protected showOnboarding = false; protected extensionRefreshEnabled = false; + private activeId: UserId; constructor( protected platformUtilsService: PlatformUtilsService, protected policyService: PolicyService, @@ -72,8 +73,8 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { ) {} async ngOnInit() { - const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$(activeId); + this.activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); + this.onboardingTasks$ = this.vaultOnboardingService.vaultOnboardingState$(this.activeId); await this.setOnboardingTasks(); this.setInstallExtLink(); @@ -86,14 +87,13 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { async ngOnChanges(changes: SimpleChanges) { if (this.showOnboarding && changes?.ciphers) { - const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); const currentTasks = await firstValueFrom(this.onboardingTasks$); const updatedTasks = { createAccount: true, importData: this.ciphers.length > 0, installExtension: currentTasks.installExtension, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); } } @@ -116,14 +116,13 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { async getMessages(event: any) { if (event.data.command === VaultOnboardingMessages.HasBwInstalled && this.showOnboarding) { - const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); const currentTasks = await firstValueFrom(this.onboardingTasks$); const updatedTasks = { createAccount: currentTasks.createAccount, importData: currentTasks.importData, installExtension: true, }; - await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, updatedTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, updatedTasks); } } @@ -166,8 +165,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { private async saveCompletedTasks(vaultTasks: VaultOnboardingTasks) { this.showOnboarding = Object.values(vaultTasks).includes(false); - const activeId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - await this.vaultOnboardingService.setVaultOnboardingTasks(activeId, vaultTasks); + await this.vaultOnboardingService.setVaultOnboardingTasks(this.activeId, vaultTasks); } individualVaultPolicyCheck() { From c19adaccb2556a95b99cd0b5e00d73e22f948934 Mon Sep 17 00:00:00 2001 From: --global <> Date: Fri, 31 Jan 2025 11:53:25 -0500 Subject: [PATCH 13/13] fixing issue --- .../vault-onboarding/vault-onboarding.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index 64490b9c179..0c9bea881da 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -23,6 +23,7 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { UserId } from "@bitwarden/common/types/guid"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { VaultOnboardingMessages } from "@bitwarden/common/vault/enums/vault-onboarding.enum"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";