mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00:00
[PM-18243] Improve type safety in decryption (#12885)
* Improve decrypt failure logging * Rename decryptcontext to decrypttrace * Improve docs * PM-16984: Improving type safety of decryption * Improving type safety of decryption --------- Co-authored-by: Bernd Schoolmann <mail@quexten.com>
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { ConditionalExcept, ConditionalKeys, Constructor } from "type-fest";
|
||||
|
||||
import { EncryptService } from "../../../key-management/crypto/abstractions/encrypt.service";
|
||||
@@ -15,6 +13,19 @@ export type DecryptedObject<
|
||||
TDecryptedKeys extends EncStringKeys<TEncryptedObject>,
|
||||
> = Record<TDecryptedKeys, string> & Omit<TEncryptedObject, TDecryptedKeys>;
|
||||
|
||||
// extracts shared keys from the domain and view types
|
||||
type EncryptableKeys<D extends Domain, V extends View> = (keyof D &
|
||||
ConditionalKeys<D, EncString | null>) &
|
||||
(keyof V & ConditionalKeys<V, string | null>);
|
||||
|
||||
type DomainEncryptableKeys<D extends Domain> = {
|
||||
[key in ConditionalKeys<D, EncString | null>]: EncString | null;
|
||||
};
|
||||
|
||||
type ViewEncryptableKeys<V extends View> = {
|
||||
[key in ConditionalKeys<V, string | null>]: string | null;
|
||||
};
|
||||
|
||||
// https://contributing.bitwarden.com/architecture/clients/data-model#domain
|
||||
export default class Domain {
|
||||
protected buildDomainModel<D extends Domain>(
|
||||
@@ -37,6 +48,7 @@ export default class Domain {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected buildDataModel<D extends Domain>(
|
||||
domain: D,
|
||||
dataObj: any,
|
||||
@@ -58,31 +70,24 @@ export default class Domain {
|
||||
}
|
||||
}
|
||||
|
||||
protected async decryptObj<T extends View>(
|
||||
viewModel: T,
|
||||
map: any,
|
||||
orgId: string,
|
||||
key: SymmetricCryptoKey = null,
|
||||
protected async decryptObj<D extends Domain, V extends View>(
|
||||
domain: DomainEncryptableKeys<D>,
|
||||
viewModel: ViewEncryptableKeys<V>,
|
||||
props: EncryptableKeys<D, V>[],
|
||||
orgId: string | null,
|
||||
key: SymmetricCryptoKey | null = null,
|
||||
objectContext: string = "No Domain Context",
|
||||
): Promise<T> {
|
||||
const self: any = this;
|
||||
|
||||
for (const prop in map) {
|
||||
// eslint-disable-next-line
|
||||
if (!map.hasOwnProperty(prop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mapProp = map[prop] || prop;
|
||||
if (self[mapProp]) {
|
||||
(viewModel as any)[prop] = await self[mapProp].decrypt(
|
||||
): Promise<V> {
|
||||
for (const prop of props) {
|
||||
viewModel[prop] =
|
||||
(await domain[prop]?.decrypt(
|
||||
orgId,
|
||||
key,
|
||||
`Property: ${prop}; ObjectContext: ${objectContext}`,
|
||||
);
|
||||
}
|
||||
`Property: ${prop as string}; ObjectContext: ${objectContext}`,
|
||||
)) ?? null;
|
||||
}
|
||||
return viewModel;
|
||||
|
||||
return viewModel as V;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +116,7 @@ export default class Domain {
|
||||
const decryptedObjects = [];
|
||||
|
||||
for (const prop of encryptedProperties) {
|
||||
const value = (this as any)[prop] as EncString;
|
||||
const value = this[prop] as EncString;
|
||||
const decrypted = await this.decryptProperty(
|
||||
prop,
|
||||
value,
|
||||
@@ -138,11 +143,9 @@ export default class Domain {
|
||||
encryptService: EncryptService,
|
||||
decryptTrace: string,
|
||||
) {
|
||||
let decrypted: string = null;
|
||||
let decrypted: string | null = null;
|
||||
if (value) {
|
||||
decrypted = await value.decryptWithKey(key, encryptService, decryptTrace);
|
||||
} else {
|
||||
decrypted = null;
|
||||
}
|
||||
return {
|
||||
[propertyKey]: decrypted,
|
||||
|
||||
@@ -160,7 +160,7 @@ export class EncString implements Encrypted {
|
||||
|
||||
async decrypt(
|
||||
orgId: string | null,
|
||||
key: SymmetricCryptoKey = null,
|
||||
key: SymmetricCryptoKey | null = null,
|
||||
context?: string,
|
||||
): Promise<string> {
|
||||
if (this.decryptedValue != null) {
|
||||
|
||||
Reference in New Issue
Block a user