1
0
mirror of https://github.com/bitwarden/jslib synced 2025-12-17 16:53:20 +00:00

Use separate data model

This commit is contained in:
Thomas Rittson
2022-03-30 11:07:25 +10:00
parent 4493cfc2f9
commit 50acba4018
6 changed files with 41 additions and 57 deletions

View File

@@ -1,14 +1,10 @@
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import { import { EncryptedOrganizationKeyData } from "jslib-common/models/data/encryptedOrganizationKeyData";
BaseEncryptedOrganizationKey,
EncryptedOrganizationKey,
} from "jslib-common/models/domain/account/encryptedKey";
import { KdfType } from "../enums/kdfType"; import { KdfType } from "../enums/kdfType";
import { ThemeType } from "../enums/themeType"; import { ThemeType } from "../enums/themeType";
import { UriMatchType } from "../enums/uriMatchType"; import { UriMatchType } from "../enums/uriMatchType";
import { EncryptedOrganizationKeyStore } from "../interfaces/encryptedOrganizationKeyStore";
import { CipherData } from "../models/data/cipherData"; import { CipherData } from "../models/data/cipherData";
import { CollectionData } from "../models/data/collectionData"; import { CollectionData } from "../models/data/collectionData";
import { EventData } from "../models/data/eventData"; import { EventData } from "../models/data/eventData";
@@ -29,6 +25,7 @@ import { CipherView } from "../models/view/cipherView";
import { CollectionView } from "../models/view/collectionView"; import { CollectionView } from "../models/view/collectionView";
import { FolderView } from "../models/view/folderView"; import { FolderView } from "../models/view/folderView";
import { SendView } from "../models/view/sendView"; import { SendView } from "../models/view/sendView";
export abstract class StateService<T extends Account = Account> { export abstract class StateService<T extends Account = Account> {
accounts: BehaviorSubject<{ [userId: string]: T }>; accounts: BehaviorSubject<{ [userId: string]: T }>;
activeAccount: BehaviorSubject<string>; activeAccount: BehaviorSubject<string>;
@@ -191,9 +188,9 @@ export abstract class StateService<T extends Account = Account> {
) => Promise<void>; ) => Promise<void>;
getEncryptedOrganizationKeys: ( getEncryptedOrganizationKeys: (
options?: StorageOptions options?: StorageOptions
) => Promise<{ [orgId: string]: BaseEncryptedOrganizationKey }>; ) => Promise<{ [orgId: string]: EncryptedOrganizationKeyData }>;
setEncryptedOrganizationKeys: ( setEncryptedOrganizationKeys: (
value: { [orgId: string]: BaseEncryptedOrganizationKey }, value: { [orgId: string]: EncryptedOrganizationKeyData },
options?: StorageOptions options?: StorageOptions
) => Promise<void>; ) => Promise<void>;
getEncryptedPasswordGenerationHistory: ( getEncryptedPasswordGenerationHistory: (

View File

@@ -0,0 +1,7 @@
export class EncryptedOrganizationKeyData {
constructor(public key: string, public providerId?: string) {}
static fromObj(obj: { key: string; providerId?: string }) {
return new EncryptedOrganizationKeyData(obj.key, obj.providerId);
}
}

View File

@@ -1,9 +1,9 @@
import { AuthenticationStatus } from "../../enums/authenticationStatus"; import { AuthenticationStatus } from "../../enums/authenticationStatus";
import { KdfType } from "../../enums/kdfType"; import { KdfType } from "../../enums/kdfType";
import { UriMatchType } from "../../enums/uriMatchType"; import { UriMatchType } from "../../enums/uriMatchType";
import { EncryptedOrganizationKeyStore } from "../../interfaces/encryptedOrganizationKeyStore";
import { CipherData } from "../data/cipherData"; import { CipherData } from "../data/cipherData";
import { CollectionData } from "../data/collectionData"; import { CollectionData } from "../data/collectionData";
import { EncryptedOrganizationKeyData } from "../data/encryptedOrganizationKeyData";
import { EventData } from "../data/eventData"; import { EventData } from "../data/eventData";
import { FolderData } from "../data/folderData"; import { FolderData } from "../data/folderData";
import { OrganizationData } from "../data/organizationData"; import { OrganizationData } from "../data/organizationData";
@@ -15,6 +15,7 @@ import { CollectionView } from "../view/collectionView";
import { FolderView } from "../view/folderView"; import { FolderView } from "../view/folderView";
import { SendView } from "../view/sendView"; import { SendView } from "../view/sendView";
import { BaseEncryptedOrganizationKey } from "./account/encryptedKey";
import { EncString } from "./encString"; import { EncString } from "./encString";
import { EnvironmentUrls } from "./environmentUrls"; import { EnvironmentUrls } from "./environmentUrls";
import { GeneratedPasswordHistory } from "./generatedPasswordHistory"; import { GeneratedPasswordHistory } from "./generatedPasswordHistory";
@@ -67,10 +68,10 @@ export class AccountKeys {
SymmetricCryptoKey SymmetricCryptoKey
>(); >();
organizationKeys?: EncryptionPair< organizationKeys?: EncryptionPair<
{ [orgId: string]: EncryptedOrganizationKeyStore }, { [orgId: string]: EncryptedOrganizationKeyData },
Map<string, SymmetricCryptoKey> Map<string, SymmetricCryptoKey>
> = new EncryptionPair< > = new EncryptionPair<
{ [orgId: string]: EncryptedOrganizationKeyStore }, { [orgId: string]: EncryptedOrganizationKeyData },
Map<string, SymmetricCryptoKey> Map<string, SymmetricCryptoKey>
>(); >();
providerKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair< providerKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<

View File

@@ -1,18 +1,18 @@
import { CryptoService } from "jslib-common/abstractions/crypto.service"; import { CryptoService } from "jslib-common/abstractions/crypto.service";
import { EncryptedOrganizationKeyData } from "jslib-common/models/data/encryptedOrganizationKeyData";
import { EncString } from "../encString"; import { EncString } from "../encString";
import { SymmetricCryptoKey } from "../symmetricCryptoKey"; import { SymmetricCryptoKey } from "../symmetricCryptoKey";
export abstract class BaseEncryptedOrganizationKey { export abstract class BaseEncryptedOrganizationKey {
decrypt: (cryptoService: CryptoService) => Promise<SymmetricCryptoKey>; decrypt: (cryptoService: CryptoService) => Promise<SymmetricCryptoKey>;
toJSON: () => string;
static fromObj(obj: { key: string; providerId?: string }) { static fromData(data: EncryptedOrganizationKeyData) {
if (obj.providerId != null) { if (data.providerId != null) {
return new ProviderEncryptedOrganizationKey(obj.key, obj.providerId); return new ProviderEncryptedOrganizationKey(data.key, data.providerId);
} }
return new EncryptedOrganizationKey(obj.key); return new EncryptedOrganizationKey(data.key);
} }
} }
@@ -24,8 +24,8 @@ export class EncryptedOrganizationKey implements BaseEncryptedOrganizationKey {
return new SymmetricCryptoKey(decValue); return new SymmetricCryptoKey(decValue);
} }
toJSON() { toData() {
return JSON.stringify({ key: this.key }); return new EncryptedOrganizationKeyData(this.key);
} }
} }
@@ -38,10 +38,7 @@ export class ProviderEncryptedOrganizationKey implements BaseEncryptedOrganizati
return new SymmetricCryptoKey(decValue); return new SymmetricCryptoKey(decValue);
} }
toJSON() { toData() {
return JSON.stringify({ return new EncryptedOrganizationKeyData(this.key, this.providerId);
key: this.key,
providerId: this.providerId,
});
} }
} }

View File

@@ -1,10 +1,7 @@
import * as bigInt from "big-integer"; import * as bigInt from "big-integer";
import { EncryptedOrganizationKeyStore } from "jslib-common/interfaces/encryptedOrganizationKeyStore"; import { EncryptedOrganizationKeyData } from "jslib-common/models/data/encryptedOrganizationKeyData";
import { import { BaseEncryptedOrganizationKey } from "jslib-common/models/domain/account/encryptedKey";
BaseEncryptedOrganizationKey,
EncryptedOrganizationKey,
} from "jslib-common/models/domain/account/encryptedKey";
import { CryptoService as CryptoServiceAbstraction } from "../abstractions/crypto.service"; import { CryptoService as CryptoServiceAbstraction } from "../abstractions/crypto.service";
import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; import { CryptoFunctionService } from "../abstractions/cryptoFunction.service";
@@ -65,15 +62,15 @@ export class CryptoService implements CryptoServiceAbstraction {
orgs: ProfileOrganizationResponse[], orgs: ProfileOrganizationResponse[],
providerOrgs: ProfileProviderOrganizationResponse[] providerOrgs: ProfileProviderOrganizationResponse[]
): Promise<void> { ): Promise<void> {
const encOrgKeys: { [orgId: string]: BaseEncryptedOrganizationKey } = {}; const encOrgKeyData: { [orgId: string]: EncryptedOrganizationKeyData } = {};
const allOrgs = orgs.concat(providerOrgs); const allOrgs = orgs.concat(providerOrgs);
allOrgs.forEach((org) => { allOrgs.forEach((org) => {
encOrgKeys[org.id] = BaseEncryptedOrganizationKey.fromObj(org); encOrgKeyData[org.id] = EncryptedOrganizationKeyData.fromObj(org);
}); });
await this.stateService.setDecryptedOrganizationKeys(null); await this.stateService.setDecryptedOrganizationKeys(null);
return await this.stateService.setEncryptedOrganizationKeys(encOrgKeys); return await this.stateService.setEncryptedOrganizationKeys(encOrgKeyData);
} }
async setProviderKeys(providers: ProfileProviderResponse[]): Promise<void> { async setProviderKeys(providers: ProfileProviderResponse[]): Promise<void> {
@@ -216,21 +213,22 @@ export class CryptoService implements CryptoServiceAbstraction {
return decryptedOrganizationKeys; return decryptedOrganizationKeys;
} }
const encOrgKeys = await this.stateService.getEncryptedOrganizationKeys(); const encOrgKeyData = await this.stateService.getEncryptedOrganizationKeys();
if (encOrgKeys == null) { if (encOrgKeyData == null) {
return null; return null;
} }
let setKey = false; let setKey = false;
for (const orgId in encOrgKeys) { for (const orgId in encOrgKeyData) {
// eslint-disable-next-line // eslint-disable-next-line
if (!encOrgKeys.hasOwnProperty(orgId) || result.has(orgId)) { if (!encOrgKeyData.hasOwnProperty(orgId) || result.has(orgId)) {
continue; continue;
} }
const decryptedKey = await encOrgKeys[orgId].decrypt(this); const encOrgKey = BaseEncryptedOrganizationKey.fromData(encOrgKeyData[orgId]);
result.set(orgId, decryptedKey); const decOrgKey = await encOrgKey.decrypt(this);
result.set(orgId, decOrgKey);
setKey = true; setKey = true;
} }

View File

@@ -1,10 +1,6 @@
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import { EncryptedOrganizationKeyStore } from "jslib-common/interfaces/encryptedOrganizationKeyStore"; import { EncryptedOrganizationKeyData } from "jslib-common/models/data/encryptedOrganizationKeyData";
import {
BaseEncryptedOrganizationKey,
EncryptedOrganizationKey,
} from "jslib-common/models/domain/account/encryptedKey";
import { LogService } from "../abstractions/log.service"; import { LogService } from "../abstractions/log.service";
import { StateService as StateServiceAbstraction } from "../abstractions/state.service"; import { StateService as StateServiceAbstraction } from "../abstractions/state.service";
@@ -1221,32 +1217,20 @@ export class StateService<
async getEncryptedOrganizationKeys( async getEncryptedOrganizationKeys(
options?: StorageOptions options?: StorageOptions
): Promise<{ [orgId: string]: BaseEncryptedOrganizationKey }> { ): Promise<{ [orgId: string]: EncryptedOrganizationKeyData }> {
const data = ( return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))
)?.keys?.organizationKeys.encrypted; )?.keys?.organizationKeys.encrypted;
const result: { [orgId: string]: BaseEncryptedOrganizationKey } = {};
for (const orgId in data) {
result[orgId] = BaseEncryptedOrganizationKey.fromObj(data[orgId]);
}
return result;
} }
async setEncryptedOrganizationKeys( async setEncryptedOrganizationKeys(
value: { [orgId: string]: EncryptedOrganizationKeyStore }, value: { [orgId: string]: EncryptedOrganizationKeyData },
options?: StorageOptions options?: StorageOptions
): Promise<void> { ): Promise<void> {
const data: { [orgId: string]: EncryptedOrganizationKey } = {};
for (const orgId in value) {
data[orgId] = value[orgId].toJSON();
}
const account = await this.getAccount( const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions()) this.reconcileOptions(options, await this.defaultOnDiskOptions())
); );
account.keys.organizationKeys.encrypted = data; account.keys.organizationKeys.encrypted = value;
await this.saveAccount( await this.saveAccount(
account, account,
this.reconcileOptions(options, await this.defaultOnDiskOptions()) this.reconcileOptions(options, await this.defaultOnDiskOptions())