mirror of
https://github.com/bitwarden/browser
synced 2026-02-06 19:53:59 +00:00
Update based on latest sdk
This commit is contained in:
@@ -5,6 +5,7 @@ import { BitwardenClient, Uuid } from "@bitwarden/sdk-internal";
|
||||
import { UserId } from "../../../types/guid";
|
||||
import { Rc } from "../../misc/reference-counting/rc";
|
||||
import { Utils } from "../../misc/utils";
|
||||
import { UserKeyDefinition } from "../../state";
|
||||
|
||||
export class UserNotLoggedInError extends Error {
|
||||
constructor(userId: UserId) {
|
||||
@@ -77,3 +78,9 @@ export abstract class SdkService {
|
||||
*/
|
||||
abstract setClient(userId: UserId, client: BitwardenClient | undefined): void;
|
||||
}
|
||||
|
||||
export interface SdkRecordMapper<ClientType, SdkType> {
|
||||
userKeyDefinition(): UserKeyDefinition<Record<string, ClientType>>;
|
||||
toSdk(value: ClientType): SdkType;
|
||||
fromSdk(value: SdkType): ClientType;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherRecordMapper } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { StateClient, Repository } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { SdkRecordMapper } from "../../abstractions/sdk/sdk.service";
|
||||
import { StateProvider } from "../../state";
|
||||
|
||||
export async function initializeState(
|
||||
userId: UserId,
|
||||
stateClient: StateClient,
|
||||
stateProvider: StateProvider,
|
||||
): Promise<void> {
|
||||
await stateClient.initialize_state(
|
||||
new RepositoryRecord(userId, stateProvider, new CipherRecordMapper()),
|
||||
);
|
||||
}
|
||||
|
||||
class RepositoryRecord<ClientType, SdkType> implements Repository<SdkType> {
|
||||
constructor(
|
||||
private userId: UserId,
|
||||
private stateProvider: StateProvider,
|
||||
private mapper: SdkRecordMapper<ClientType, SdkType>,
|
||||
) {}
|
||||
|
||||
async get(id: string): Promise<SdkType | null> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition());
|
||||
const data = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
const element = data[id];
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
return this.mapper.toSdk(element);
|
||||
}
|
||||
|
||||
async list(): Promise<SdkType[]> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition());
|
||||
const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
return Object.values(elements).map((element) => this.mapper.toSdk(element));
|
||||
}
|
||||
|
||||
async set(id: string, value: SdkType): Promise<void> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition());
|
||||
const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
elements[id] = this.mapper.fromSdk(value);
|
||||
await prov.update(() => elements);
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<void> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.mapper.userKeyDefinition());
|
||||
const elements = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
if (!elements[id]) {
|
||||
return;
|
||||
}
|
||||
delete elements[id];
|
||||
await prov.update(() => elements);
|
||||
}
|
||||
}
|
||||
@@ -12,21 +12,15 @@ import {
|
||||
of,
|
||||
takeWhile,
|
||||
throwIfEmpty,
|
||||
firstValueFrom,
|
||||
} from "rxjs";
|
||||
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { ENCRYPTED_CIPHERS } from "@bitwarden/common/vault/services/key-state/ciphers.state";
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { KeyService, KdfConfigService, KdfConfig, KdfType } from "@bitwarden/key-management";
|
||||
import {
|
||||
BitwardenClient,
|
||||
ClientSettings,
|
||||
Cipher as SdkCipher,
|
||||
DeviceType as SdkDeviceType,
|
||||
Repository as SdkRepository,
|
||||
} from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncryptedOrganizationKeyData } from "../../../admin-console/models/data/encrypted-organization-key.data";
|
||||
@@ -42,7 +36,9 @@ import { SdkService, UserNotLoggedInError } from "../../abstractions/sdk/sdk.ser
|
||||
import { compareValues } from "../../misc/compare-values";
|
||||
import { Rc } from "../../misc/reference-counting/rc";
|
||||
import { EncryptedString } from "../../models/domain/enc-string";
|
||||
import { StateProvider, UserKeyDefinition } from "../../state";
|
||||
import { StateProvider } from "../../state";
|
||||
|
||||
import { initializeState } from "./client-managed-state";
|
||||
|
||||
// A symbol that represents an overriden client that is explicitly set to undefined,
|
||||
// blocking the creation of an internal client for that user.
|
||||
@@ -234,17 +230,8 @@ export class DefaultSdkService implements SdkService {
|
||||
|
||||
// This is optional to avoid having to mock it on the server
|
||||
if (this.stateProvider) {
|
||||
client
|
||||
.platform()
|
||||
.state()
|
||||
.register_cipher_repository(
|
||||
new RepositoryRecordImpl(
|
||||
userId,
|
||||
this.stateProvider,
|
||||
ENCRYPTED_CIPHERS,
|
||||
new CipherMapper(),
|
||||
),
|
||||
);
|
||||
// Initialize the SDK managed database and the client managed repositories.
|
||||
await initializeState(userId, client.platform().state(), this.stateProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,60 +301,3 @@ export class DefaultSdkService implements SdkService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface SdkMapper<ClientType, SdkType> {
|
||||
toSdk(value: ClientType): SdkType;
|
||||
fromSdk(value: SdkType): ClientType;
|
||||
}
|
||||
|
||||
class RepositoryRecordImpl<ClientType, SdkType> implements SdkRepository<SdkType> {
|
||||
constructor(
|
||||
private userId: UserId,
|
||||
private stateProvider: StateProvider,
|
||||
private userKeyDefinition: UserKeyDefinition<Record<string, ClientType>>,
|
||||
private mapper: SdkMapper<ClientType, SdkType>,
|
||||
) {}
|
||||
|
||||
async get(id: string): Promise<SdkType | null> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.userKeyDefinition);
|
||||
const data = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
|
||||
const cipher = data[id];
|
||||
if (!cipher) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.mapper.toSdk(cipher);
|
||||
}
|
||||
async list(): Promise<SdkType[]> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.userKeyDefinition);
|
||||
const ciphers = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
|
||||
return Object.values(ciphers).map((cipher) => this.mapper.toSdk(cipher));
|
||||
}
|
||||
async set(id: string, value: SdkType): Promise<void> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.userKeyDefinition);
|
||||
const ciphers = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
ciphers[id] = this.mapper.fromSdk(value);
|
||||
await prov.update(() => ciphers);
|
||||
}
|
||||
async remove(id: string): Promise<void> {
|
||||
const prov = this.stateProvider.getUser(this.userId, this.userKeyDefinition);
|
||||
const ciphers = await firstValueFrom(prov.state$.pipe(map((data) => data ?? {})));
|
||||
if (!ciphers[id]) {
|
||||
return;
|
||||
}
|
||||
delete ciphers[id];
|
||||
await prov.update(() => ciphers);
|
||||
}
|
||||
}
|
||||
|
||||
class CipherMapper implements SdkMapper<CipherData, SdkCipher> {
|
||||
toSdk(value: CipherData): SdkCipher {
|
||||
return new Cipher(value).toSdkCipher();
|
||||
}
|
||||
|
||||
fromSdk(value: SdkCipher): CipherData {
|
||||
throw new Error("Cipher.fromSdk is not implemented yet");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { CipherView as SdkCipherView } from "@bitwarden/sdk-internal";
|
||||
import {
|
||||
SdkRecordMapper,
|
||||
uuidToString,
|
||||
} from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { UserKeyDefinition } from "@bitwarden/common/platform/state";
|
||||
import { CipherView as SdkCipherView, Cipher as SdkCipher } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { View } from "../../../models/view/view";
|
||||
import { InitializerMetadata } from "../../../platform/interfaces/initializer-metadata.interface";
|
||||
@@ -8,7 +13,9 @@ import { InitializerKey } from "../../../platform/services/cryptography/initiali
|
||||
import { DeepJsonify } from "../../../types/deep-jsonify";
|
||||
import { CipherType, LinkedIdType } from "../../enums";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { ENCRYPTED_CIPHERS } from "../../services/key-state/ciphers.state";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
import { CipherData } from "../data/cipher.data";
|
||||
import { LocalData } from "../data/local.data";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
@@ -21,6 +28,21 @@ import { PasswordHistoryView } from "./password-history.view";
|
||||
import { SecureNoteView } from "./secure-note.view";
|
||||
import { SshKeyView } from "./ssh-key.view";
|
||||
|
||||
// TODO: This should probably be moved to a better place
|
||||
export class CipherRecordMapper implements SdkRecordMapper<CipherData, SdkCipher> {
|
||||
userKeyDefinition(): UserKeyDefinition<Record<string, CipherData>> {
|
||||
return ENCRYPTED_CIPHERS;
|
||||
}
|
||||
|
||||
toSdk(value: CipherData): SdkCipher {
|
||||
return new Cipher(value).toSdkCipher();
|
||||
}
|
||||
|
||||
fromSdk(value: SdkCipher): CipherData {
|
||||
throw new Error("Cipher.fromSdk is not implemented yet");
|
||||
}
|
||||
}
|
||||
|
||||
export class CipherView implements View, InitializerMetadata {
|
||||
readonly initializerKey = InitializerKey.CipherView;
|
||||
|
||||
@@ -234,9 +256,9 @@ export class CipherView implements View, InitializerMetadata {
|
||||
}
|
||||
|
||||
const cipherView = new CipherView();
|
||||
cipherView.id = obj.id ?? null;
|
||||
cipherView.organizationId = obj.organizationId ?? null;
|
||||
cipherView.folderId = obj.folderId ?? null;
|
||||
cipherView.id = obj.id ? uuidToString(obj.id) : null;
|
||||
cipherView.organizationId = obj.organizationId ? uuidToString(obj.organizationId) : null;
|
||||
cipherView.folderId = obj.folderId ? uuidToString(obj.folderId) : null;
|
||||
cipherView.name = obj.name;
|
||||
cipherView.notes = obj.notes ?? null;
|
||||
cipherView.type = obj.type;
|
||||
@@ -260,7 +282,7 @@ export class CipherView implements View, InitializerMetadata {
|
||||
cipherView.fields = obj.fields?.map((f) => FieldView.fromSdkFieldView(f)) ?? null;
|
||||
cipherView.passwordHistory =
|
||||
obj.passwordHistory?.map((ph) => PasswordHistoryView.fromSdkPasswordHistoryView(ph)) ?? null;
|
||||
cipherView.collectionIds = obj.collectionIds ?? null;
|
||||
cipherView.collectionIds = obj.collectionIds.map((id) => uuidToString(id)) ?? null;
|
||||
cipherView.revisionDate = obj.revisionDate == null ? null : new Date(obj.revisionDate);
|
||||
cipherView.creationDate = obj.creationDate == null ? null : new Date(obj.creationDate);
|
||||
cipherView.deletedDate = obj.deletedDate == null ? null : new Date(obj.deletedDate);
|
||||
|
||||
Reference in New Issue
Block a user