mirror of
https://github.com/bitwarden/browser
synced 2026-02-11 14:04:03 +00:00
Rename ActiveUserState -> UserState
These classes need to handle storage update calls to more than just the active user. The interface will expand to support this
This commit is contained in:
@@ -64,7 +64,6 @@ import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
||||
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
||||
import { ActiveUserStateProvider } from "@bitwarden/common/platform/abstractions/active-user-state.provider";
|
||||
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||
import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction";
|
||||
@@ -80,6 +79,7 @@ import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/comm
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { UserStateProvider } from "@bitwarden/common/platform/abstractions/user-state.provider";
|
||||
import { ValidationService as ValidationServiceAbstraction } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||
import { flagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
@@ -92,7 +92,7 @@ import { ConsoleLogService } from "@bitwarden/common/platform/services/console-l
|
||||
import { CryptoService } from "@bitwarden/common/platform/services/crypto.service";
|
||||
import { EncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/encrypt.service.implementation";
|
||||
import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/multithread-encrypt.service.implementation";
|
||||
import { DefaultActiveUserStateProvider } from "@bitwarden/common/platform/services/default-active-user-state.provider";
|
||||
import { DefaultUserStateProvider } from "@bitwarden/common/platform/services/default-user-state.provider";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/services/environment.service";
|
||||
import { FileUploadService } from "@bitwarden/common/platform/services/file-upload/file-upload.service";
|
||||
import { StateService } from "@bitwarden/common/platform/services/state.service";
|
||||
@@ -303,7 +303,7 @@ import { AbstractThemingService } from "./theming/theming.service.abstraction";
|
||||
CryptoServiceAbstraction,
|
||||
I18nServiceAbstraction,
|
||||
CipherServiceAbstraction,
|
||||
ActiveUserStateProvider,
|
||||
UserStateProvider,
|
||||
StateServiceAbstraction,
|
||||
],
|
||||
},
|
||||
@@ -722,8 +722,8 @@ import { AbstractThemingService } from "./theming/theming.service.abstraction";
|
||||
deps: [CryptoServiceAbstraction],
|
||||
},
|
||||
{
|
||||
provide: ActiveUserStateProvider,
|
||||
useClass: DefaultActiveUserStateProvider,
|
||||
provide: UserStateProvider,
|
||||
useClass: DefaultUserStateProvider,
|
||||
deps: [
|
||||
// TODO: Do other storage services
|
||||
AccountServiceAbstraction,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { ActiveUserState } from "../src/platform/interfaces/active-user-state";
|
||||
import { UserState } from "../src/platform/interfaces/user-state";
|
||||
|
||||
export class TestUserState<T> implements ActiveUserState<T> {
|
||||
export class TestUserState<T> implements UserState<T> {
|
||||
private _state$: BehaviorSubject<T>;
|
||||
get state$() {
|
||||
return this._state$.asObservable();
|
||||
@@ -1,6 +0,0 @@
|
||||
import { ActiveUserState } from "../interfaces/active-user-state";
|
||||
import { KeyDefinition } from "../types/key-definition";
|
||||
|
||||
export abstract class ActiveUserStateProvider {
|
||||
create: <T>(keyDefinition: KeyDefinition<T>) => ActiveUserState<T>;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { UserState } from "../interfaces/user-state";
|
||||
import { KeyDefinition } from "../types/key-definition";
|
||||
|
||||
export abstract class UserStateProvider {
|
||||
create: <T>(keyDefinition: KeyDefinition<T>) => UserState<T>;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { DerivedActiveUserState } from "../services/default-active-user-state.provider";
|
||||
import { DerivedUserState } from "../services/default-user-state.provider";
|
||||
import { DerivedStateDefinition } from "../types/derived-state-definition";
|
||||
|
||||
export interface ActiveUserState<T> {
|
||||
export interface UserState<T> {
|
||||
readonly state$: Observable<T>;
|
||||
readonly getFromState: () => Promise<T>;
|
||||
/**
|
||||
@@ -14,5 +14,5 @@ export interface ActiveUserState<T> {
|
||||
readonly update: (configureState: (state: T) => T) => Promise<T>;
|
||||
createDerived: <TTo>(
|
||||
derivedStateDefinition: DerivedStateDefinition<T, TTo>
|
||||
) => DerivedActiveUserState<T, TTo>;
|
||||
) => DerivedUserState<T, TTo>;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { AbstractMemoryStorageService } from "../abstractions/storage.service";
|
||||
import { KeyDefinition } from "../types/key-definition";
|
||||
import { StateDefinition } from "../types/state-definition";
|
||||
|
||||
import { DefaultActiveUserStateProvider } from "./default-active-user-state.provider";
|
||||
import { DefaultUserStateProvider } from "./default-user-state.provider";
|
||||
|
||||
class TestState {
|
||||
date: Date;
|
||||
@@ -42,7 +42,7 @@ describe("DefaultStateProvider", () => {
|
||||
|
||||
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>(undefined);
|
||||
|
||||
let activeUserStateProvider: DefaultActiveUserStateProvider;
|
||||
let userStateProvider: DefaultUserStateProvider;
|
||||
|
||||
beforeEach(() => {
|
||||
mockReset(accountService);
|
||||
@@ -51,7 +51,7 @@ describe("DefaultStateProvider", () => {
|
||||
|
||||
accountService.activeAccount$ = activeAccountSubject;
|
||||
|
||||
activeUserStateProvider = new DefaultActiveUserStateProvider(
|
||||
userStateProvider = new DefaultUserStateProvider(
|
||||
accountService,
|
||||
null, // Not testing derived state
|
||||
null, // Not testing memory storage
|
||||
@@ -68,7 +68,7 @@ describe("DefaultStateProvider", () => {
|
||||
} as Jsonify<TestState>);
|
||||
});
|
||||
|
||||
const fakeDomainState = activeUserStateProvider.create(testKeyDefinition);
|
||||
const fakeDomainState = userStateProvider.create(testKeyDefinition);
|
||||
|
||||
const subscribeCallback = jest.fn<void, [TestState]>();
|
||||
const subscription = fakeDomainState.state$.subscribe(subscribeCallback);
|
||||
@@ -11,13 +11,13 @@ import {
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { AccountService } from "../../auth/abstractions/account.service";
|
||||
import { ActiveUserStateProvider } from "../abstractions/active-user-state.provider";
|
||||
import { EncryptService } from "../abstractions/encrypt.service";
|
||||
import {
|
||||
AbstractMemoryStorageService,
|
||||
AbstractStorageService,
|
||||
} from "../abstractions/storage.service";
|
||||
import { ActiveUserState } from "../interfaces/active-user-state";
|
||||
import { UserStateProvider } from "../abstractions/user-state.provider";
|
||||
import { UserState } from "../interfaces/user-state";
|
||||
import { userKeyBuilder } from "../misc/key-builders";
|
||||
import { UserKey } from "../models/domain/symmetric-crypto-key";
|
||||
import { KeyDefinition } from "../types/key-definition";
|
||||
@@ -32,7 +32,7 @@ class DerivedStateDefinition<TFrom, TTo> {
|
||||
constructor(readonly converter: (data: TFrom, context: ConverterContext) => Promise<TTo>) {}
|
||||
}
|
||||
|
||||
export class DerivedActiveUserState<TFrom, TTo> {
|
||||
export class DerivedUserState<TFrom, TTo> {
|
||||
state$: Observable<TTo>;
|
||||
|
||||
// TODO: Probably needs to take state service
|
||||
@@ -42,9 +42,9 @@ export class DerivedActiveUserState<TFrom, TTo> {
|
||||
constructor(
|
||||
private derivedStateDefinition: DerivedStateDefinition<TFrom, TTo>,
|
||||
private encryptService: EncryptService,
|
||||
private activeUserState: ActiveUserState<TFrom>
|
||||
private userState: UserState<TFrom>
|
||||
) {
|
||||
this.state$ = activeUserState.state$.pipe(
|
||||
this.state$ = userState.state$.pipe(
|
||||
switchMap(async (from) => {
|
||||
// TODO: How do I get the key?
|
||||
const convertedData = await derivedStateDefinition.converter(
|
||||
@@ -57,7 +57,7 @@ export class DerivedActiveUserState<TFrom, TTo> {
|
||||
}
|
||||
|
||||
async getFromState(): Promise<TTo> {
|
||||
const encryptedFromState = await this.activeUserState.getFromState();
|
||||
const encryptedFromState = await this.userState.getFromState();
|
||||
|
||||
const context = new ConverterContext(null, this.encryptService);
|
||||
|
||||
@@ -66,7 +66,7 @@ export class DerivedActiveUserState<TFrom, TTo> {
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultActiveUserState<T> implements ActiveUserState<T> {
|
||||
class DefaultUserState<T> implements UserState<T> {
|
||||
private seededInitial = false;
|
||||
|
||||
private formattedKey$: Observable<string>;
|
||||
@@ -154,8 +154,8 @@ class DefaultActiveUserState<T> implements ActiveUserState<T> {
|
||||
|
||||
createDerived<TTo>(
|
||||
derivedStateDefinition: DerivedStateDefinition<T, TTo>
|
||||
): DerivedActiveUserState<T, TTo> {
|
||||
return new DerivedActiveUserState<T, TTo>(derivedStateDefinition, this.encryptService, this);
|
||||
): DerivedUserState<T, TTo> {
|
||||
return new DerivedUserState<T, TTo>(derivedStateDefinition, this.encryptService, this);
|
||||
}
|
||||
|
||||
private async createKey(): Promise<string> {
|
||||
@@ -184,8 +184,8 @@ class DefaultActiveUserState<T> implements ActiveUserState<T> {
|
||||
}
|
||||
}
|
||||
|
||||
export class DefaultActiveUserStateProvider implements ActiveUserStateProvider {
|
||||
private userStateCache: Record<string, DefaultActiveUserState<unknown>> = {};
|
||||
export class DefaultUserStateProvider implements UserStateProvider {
|
||||
private userStateCache: Record<string, DefaultUserState<unknown>> = {};
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService, // Inject the lightest weight service that provides accountUserId$
|
||||
@@ -195,16 +195,16 @@ export class DefaultActiveUserStateProvider implements ActiveUserStateProvider {
|
||||
private secureStorage: AbstractStorageService
|
||||
) {}
|
||||
|
||||
create<T>(keyDefinition: KeyDefinition<T>): DefaultActiveUserState<T> {
|
||||
create<T>(keyDefinition: KeyDefinition<T>): DefaultUserState<T> {
|
||||
const locationDomainKey = `${keyDefinition.stateDefinition.storageLocation}_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
|
||||
const existingActiveUserState = this.userStateCache[locationDomainKey];
|
||||
if (existingActiveUserState != null) {
|
||||
const existingUserState = this.userStateCache[locationDomainKey];
|
||||
if (existingUserState != null) {
|
||||
// I have to cast out of the unknown generic but this should be safe if rules
|
||||
// around domain token are made
|
||||
return existingActiveUserState as DefaultActiveUserState<T>;
|
||||
return existingUserState as DefaultUserState<T>;
|
||||
}
|
||||
|
||||
const newActiveUserState = new DefaultActiveUserState<T>(
|
||||
const newUserState = new DefaultUserState<T>(
|
||||
keyDefinition,
|
||||
this.accountService,
|
||||
this.encryptService,
|
||||
@@ -212,7 +212,7 @@ export class DefaultActiveUserStateProvider implements ActiveUserStateProvider {
|
||||
this.secureStorage,
|
||||
this.diskStorage
|
||||
);
|
||||
this.userStateCache[locationDomainKey] = newActiveUserState;
|
||||
return newActiveUserState;
|
||||
this.userStateCache[locationDomainKey] = newUserState;
|
||||
return newUserState;
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,14 @@ import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { TestUserState as TestActiveUserState } from "../../../../spec/test-active-user-state";
|
||||
import { ActiveUserStateProvider } from "../../../platform/abstractions/active-user-state.provider";
|
||||
import { TestUserState } from "../../../../spec/test-active-user-state";
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "../../../platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||
import { UserStateProvider } from "../../../platform/abstractions/user-state.provider";
|
||||
import { EncString } from "../../../platform/models/domain/enc-string";
|
||||
import { ContainerService } from "../../../platform/services/container.service";
|
||||
import { DerivedActiveUserState } from "../../../platform/services/default-active-user-state.provider";
|
||||
import { DerivedUserState } from "../../../platform/services/default-user-state.provider";
|
||||
import { StateService } from "../../../platform/services/state.service";
|
||||
import { CipherService } from "../../abstractions/cipher.service";
|
||||
import { FolderData } from "../../models/data/folder.data";
|
||||
@@ -28,10 +28,9 @@ describe("Folder Service", () => {
|
||||
let stateService: SubstituteOf<StateService>;
|
||||
let activeAccount: BehaviorSubject<string>;
|
||||
let activeAccountUnlocked: BehaviorSubject<boolean>;
|
||||
const activeUserStateProvider = mock<ActiveUserStateProvider>();
|
||||
let activeUserState: TestActiveUserState<Record<string, FolderData>>;
|
||||
const derivedActiveUserState =
|
||||
mock<DerivedActiveUserState<Record<string, FolderData>, FolderView[]>>();
|
||||
const userStateProvider = mock<UserStateProvider>();
|
||||
let userState: TestUserState<Record<string, FolderData>>;
|
||||
const derivedUserState = mock<DerivedUserState<Record<string, FolderData>, FolderView[]>>();
|
||||
let folderViews$: BehaviorSubject<FolderView[]>;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -51,19 +50,19 @@ describe("Folder Service", () => {
|
||||
stateService.activeAccountUnlocked$.returns(activeAccountUnlocked);
|
||||
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);
|
||||
|
||||
activeUserState = new TestActiveUserState({});
|
||||
activeUserState.next(initialState);
|
||||
activeUserStateProvider.create.mockReturnValue(activeUserState);
|
||||
activeUserState.createDerived.mockReturnValue(derivedActiveUserState);
|
||||
userState = new TestUserState({});
|
||||
userState.next(initialState);
|
||||
userStateProvider.create.mockReturnValue(userState);
|
||||
userState.createDerived.mockReturnValue(derivedUserState);
|
||||
|
||||
folderViews$ = new BehaviorSubject([]);
|
||||
derivedActiveUserState.state$ = folderViews$;
|
||||
derivedUserState.state$ = folderViews$;
|
||||
|
||||
folderService = new FolderService(
|
||||
cryptoService,
|
||||
i18nService,
|
||||
cipherService,
|
||||
activeUserStateProvider,
|
||||
userStateProvider,
|
||||
stateService
|
||||
);
|
||||
});
|
||||
@@ -71,7 +70,7 @@ describe("Folder Service", () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
folderViews$.complete();
|
||||
activeUserState.complete();
|
||||
userState.complete();
|
||||
});
|
||||
|
||||
test("encrypt", async () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Observable, firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ActiveUserStateProvider } from "../../../platform/abstractions/active-user-state.provider";
|
||||
import { CryptoService } from "../../../platform/abstractions/crypto.service";
|
||||
import { I18nService } from "../../../platform/abstractions/i18n.service";
|
||||
import { StateService } from "../../../platform/abstractions/state.service";
|
||||
import { ActiveUserState } from "../../../platform/interfaces/active-user-state";
|
||||
import { UserStateProvider } from "../../../platform/abstractions/user-state.provider";
|
||||
import { UserState } from "../../../platform/interfaces/user-state";
|
||||
import { Utils } from "../../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { DerivedActiveUserState } from "../../../platform/services/default-active-user-state.provider";
|
||||
import { DerivedUserState } from "../../../platform/services/default-user-state.provider";
|
||||
import { CipherService } from "../../../vault/abstractions/cipher.service";
|
||||
import { InternalFolderService as InternalFolderServiceAbstraction } from "../../../vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherData } from "../../../vault/models/data/cipher.data";
|
||||
@@ -17,8 +17,8 @@ import { FolderView } from "../../../vault/models/view/folder.view";
|
||||
import { FOLDERS } from "../../types/key-definitions";
|
||||
|
||||
export class FolderService implements InternalFolderServiceAbstraction {
|
||||
folderState: ActiveUserState<Record<string, FolderData>>;
|
||||
decryptedFolderState: DerivedActiveUserState<Record<string, FolderData>, FolderView[]>;
|
||||
folderState: UserState<Record<string, FolderData>>;
|
||||
decryptedFolderState: DerivedUserState<Record<string, FolderData>, FolderView[]>;
|
||||
|
||||
folders$: Observable<Folder[]>;
|
||||
folderViews$: Observable<FolderView[]>;
|
||||
@@ -27,7 +27,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
private cryptoService: CryptoService,
|
||||
private i18nService: I18nService,
|
||||
private cipherService: CipherService,
|
||||
private activeUserStateProvider: ActiveUserStateProvider,
|
||||
private userStateProvider: UserStateProvider,
|
||||
private stateService: StateService
|
||||
) {
|
||||
(window as any).services ||= {};
|
||||
@@ -41,7 +41,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
}
|
||||
);
|
||||
|
||||
this.folderState = this.activeUserStateProvider.create(FOLDERS);
|
||||
this.folderState = this.userStateProvider.create(FOLDERS);
|
||||
|
||||
this.folders$ = this.folderState.state$.pipe(
|
||||
map((foldersMap) => {
|
||||
|
||||
Reference in New Issue
Block a user