import { firstValueFrom, Observable } from "rxjs"; import { Jsonify } from "type-fest/source/jsonify"; import { KDF_CONFIG_DISK, StateProvider, UserKeyDefinition, } from "@bitwarden/common/platform/state"; import { UserId } from "@bitwarden/common/types/guid"; import { KdfConfigService } from "./abstractions/kdf-config.service"; import { KdfType } from "./enums/kdf-type.enum"; import { Argon2KdfConfig, KdfConfig, PBKDF2KdfConfig } from "./models/kdf-config"; export const KDF_CONFIG = new UserKeyDefinition(KDF_CONFIG_DISK, "kdfConfig", { deserializer: (kdfConfig: Jsonify) => { if (kdfConfig == null) { return null; } return kdfConfig.kdfType === KdfType.PBKDF2_SHA256 ? PBKDF2KdfConfig.fromJSON(kdfConfig) : Argon2KdfConfig.fromJSON(kdfConfig); }, clearOn: ["logout"], }); export class DefaultKdfConfigService implements KdfConfigService { constructor(private stateProvider: StateProvider) {} async setKdfConfig(userId: UserId, kdfConfig: KdfConfig) { if (userId == null) { throw new Error("userId cannot be null"); } if (kdfConfig == null) { throw new Error("kdfConfig cannot be null"); } await this.stateProvider.setUserState(KDF_CONFIG, kdfConfig, userId); } async getKdfConfig(): Promise { const userId = await firstValueFrom(this.stateProvider.activeUserId$); if (userId == null) { throw new Error("KdfConfig can only be retrieved when there is active user"); } const state = await firstValueFrom(this.stateProvider.getUser(userId, KDF_CONFIG).state$); if (state == null) { throw new Error("KdfConfig for active user account state is null"); } return state; } getKdfConfig$(userId: UserId): Observable { if (userId == null) { throw new Error("userId cannot be null"); } return this.stateProvider.getUser(userId, KDF_CONFIG).state$; } }