1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-5273] Migrate state in CipherService (#8314)

* PM-5273 Initial migration work for localData

* PM-5273 Encrypted and Decrypted ciphers migration to state provider

* pm-5273 Update references

* pm5273 Ensure prototype on cipher

* PM-5273 Add CipherId

* PM-5273 Remove migrated methods and updated references

* pm-5273 Fix versions

* PM-5273 Added missing options

* Conflict resolution

* Revert "Conflict resolution"

This reverts commit 0c0c2039ed.

* PM-5273 Fix PR comments

* Pm-5273 Fix comments

* PM-5273 Changed decryptedCiphers to use ActiveUserState

* PM-5273 Fix tests

* PM-5273 Fix pr comments
This commit is contained in:
Carlos Gonçalves
2024-04-16 17:37:03 +01:00
committed by GitHub
parent 62ed7e5abc
commit 06acdefa91
29 changed files with 525 additions and 305 deletions

View File

@@ -9,10 +9,6 @@ import { GeneratorOptions } from "../../tools/generator/generator-options";
import { GeneratedPasswordHistory, PasswordGeneratorOptions } from "../../tools/generator/password";
import { UsernameGeneratorOptions } from "../../tools/generator/username";
import { UserId } from "../../types/guid";
import { CipherData } from "../../vault/models/data/cipher.data";
import { LocalData } from "../../vault/models/data/local.data";
import { CipherView } from "../../vault/models/view/cipher.view";
import { AddEditCipherInfo } from "../../vault/types/add-edit-cipher-info";
import { EnvironmentService } from "../abstractions/environment.service";
import { LogService } from "../abstractions/log.service";
import {
@@ -221,34 +217,6 @@ export class StateService<
return currentUser as UserId;
}
async getAddEditCipherInfo(options?: StorageOptions): Promise<AddEditCipherInfo> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
// ensure prototype on cipher
const raw = account?.data?.addEditCipherInfo;
return raw == null
? null
: {
cipher:
raw?.cipher.toJSON != null
? raw.cipher
: CipherView.fromJSON(raw?.cipher as Jsonify<CipherView>),
collectionIds: raw?.collectionIds,
};
}
async setAddEditCipherInfo(value: AddEditCipherInfo, options?: StorageOptions): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
account.data.addEditCipherInfo = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
}
/**
* user key when using the "never" option of vault timeout
*/
@@ -465,24 +433,6 @@ export class StateService<
await this.saveSecureStorageKey(partialKeys.biometricKey, value, options);
}
@withPrototypeForArrayMembers(CipherView, CipherView.fromJSON)
async getDecryptedCiphers(options?: StorageOptions): Promise<CipherView[]> {
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions()))
)?.data?.ciphers?.decrypted;
}
async setDecryptedCiphers(value: CipherView[], options?: StorageOptions): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
account.data.ciphers.decrypted = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultInMemoryOptions()),
);
}
@withPrototypeForArrayMembers(GeneratedPasswordHistory)
async getDecryptedPasswordGenerationHistory(
options?: StorageOptions,
@@ -621,27 +571,6 @@ export class StateService<
);
}
@withPrototypeForObjectValues(CipherData)
async getEncryptedCiphers(options?: StorageOptions): Promise<{ [id: string]: CipherData }> {
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()))
)?.data?.ciphers?.encrypted;
}
async setEncryptedCiphers(
value: { [id: string]: CipherData },
options?: StorageOptions,
): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()),
);
account.data.ciphers.encrypted = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()),
);
}
/**
* @deprecated Use UserKey instead
*/
@@ -805,26 +734,6 @@ export class StateService<
);
}
async getLocalData(options?: StorageOptions): Promise<{ [cipherId: string]: LocalData }> {
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()))
)?.data?.localData;
}
async setLocalData(
value: { [cipherId: string]: LocalData },
options?: StorageOptions,
): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
);
account.data.localData = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
);
}
async getMinimizeOnCopyToClipboard(options?: StorageOptions): Promise<boolean> {
return (
(await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))
@@ -1510,50 +1419,3 @@ function withPrototypeForArrayMembers<T>(
};
};
}
function withPrototypeForObjectValues<T>(
valuesConstructor: new (...args: any[]) => T,
valuesConverter: (input: any) => T = (i) => i,
): (
target: any,
propertyKey: string | symbol,
descriptor: PropertyDescriptor,
) => { value: (...args: any[]) => Promise<{ [key: string]: T }> } {
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
return {
value: function (...args: any[]) {
const originalResult: Promise<{ [key: string]: T }> = originalMethod.apply(this, args);
if (!Utils.isPromise(originalResult)) {
throw new Error(
`Error applying prototype to stored value -- result is not a promise for method ${String(
propertyKey,
)}`,
);
}
return originalResult.then((result) => {
if (result == null) {
return null;
} else {
for (const [key, val] of Object.entries(result)) {
result[key] =
val == null || val.constructor.name === valuesConstructor.prototype.constructor.name
? valuesConverter(val)
: valuesConverter(
Object.create(
valuesConstructor.prototype,
Object.getOwnPropertyDescriptors(val),
),
);
}
return result as { [key: string]: T };
}
});
},
};
};
}