mirror of
https://github.com/bitwarden/jslib
synced 2025-12-19 09:43:28 +00:00
[bug] Scaffold memory storage for web
Not properly creating storage objects on signin was creating weird behavior when logging out, locking, and logging back in. Namely, encrypted data that was recently synced had nowhere to save to and was lost.
This commit is contained in:
@@ -33,101 +33,101 @@ export class DataEncryptionPair<TEncrypted, TDecrypted> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AccountData {
|
export class AccountData {
|
||||||
ciphers?: DataEncryptionPair<CipherData, CipherView> = new DataEncryptionPair<CipherData, CipherView>();
|
ciphers: DataEncryptionPair<CipherData, CipherView> = new DataEncryptionPair<CipherData, CipherView>();
|
||||||
folders?: DataEncryptionPair<FolderData, FolderView> = new DataEncryptionPair<FolderData, FolderView>();
|
folders: DataEncryptionPair<FolderData, FolderView> = new DataEncryptionPair<FolderData, FolderView>();
|
||||||
localData?: any;
|
localData: any;
|
||||||
sends?: DataEncryptionPair<SendData, SendView> = new DataEncryptionPair<SendData, SendView>();
|
sends: DataEncryptionPair<SendData, SendView> = new DataEncryptionPair<SendData, SendView>();
|
||||||
collections?: DataEncryptionPair<CollectionData, CollectionView> = new DataEncryptionPair<CollectionData, CollectionView>();
|
collections: DataEncryptionPair<CollectionData, CollectionView> = new DataEncryptionPair<CollectionData, CollectionView>();
|
||||||
kdfIterations?: number;
|
policies: DataEncryptionPair<PolicyData, Policy> = new DataEncryptionPair<PolicyData, Policy>();
|
||||||
kdfType?: KdfType;
|
passwordGenerationHistory: EncryptionPair<GeneratedPasswordHistory[], GeneratedPasswordHistory[]> = new EncryptionPair<GeneratedPasswordHistory[], GeneratedPasswordHistory[]>();
|
||||||
policies?: DataEncryptionPair<PolicyData, Policy> = new DataEncryptionPair<PolicyData, Policy>();
|
addEditCipherInfo: any;
|
||||||
passwordGenerationHistory?: EncryptionPair<GeneratedPasswordHistory[], GeneratedPasswordHistory[]> = new EncryptionPair<GeneratedPasswordHistory[], GeneratedPasswordHistory[]>();
|
collapsedGroupings: Set<string>;
|
||||||
addEditCipherInfo?: any;
|
eventCollection: EventData[];
|
||||||
collapsedGroupings?: Set<string>;
|
organizations: { [id: string]: OrganizationData };
|
||||||
eventCollection?: EventData[];
|
providers: { [id: string]: ProviderData };
|
||||||
organizations?: { [id: string]: OrganizationData };
|
|
||||||
providers?: { [id: string]: ProviderData };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountKeys {
|
export class AccountKeys {
|
||||||
cryptoMasterKey?: SymmetricCryptoKey;
|
cryptoMasterKey: SymmetricCryptoKey;
|
||||||
cryptoMasterKeyAuto?: SymmetricCryptoKey;
|
cryptoMasterKeyAuto: SymmetricCryptoKey;
|
||||||
cryptoMasterKeyB64?: string;
|
cryptoMasterKeyB64: string;
|
||||||
cryptoMasterKeyBiometric?: SymmetricCryptoKey;
|
cryptoMasterKeyBiometric: SymmetricCryptoKey;
|
||||||
cryptoSymmetricKey?: EncryptionPair<string, SymmetricCryptoKey> = new EncryptionPair<string, SymmetricCryptoKey>();
|
cryptoSymmetricKey: EncryptionPair<string, SymmetricCryptoKey> = new EncryptionPair<string, SymmetricCryptoKey>();
|
||||||
organizationKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<any, Map<string, SymmetricCryptoKey>>();
|
organizationKeys: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<any, Map<string, SymmetricCryptoKey>>();
|
||||||
privateKey?: EncryptionPair<string, ArrayBuffer> = new EncryptionPair<string, ArrayBuffer>();
|
providerKeys: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<any, Map<string, SymmetricCryptoKey>>();
|
||||||
providerKeys?: EncryptionPair<any, Map<string, SymmetricCryptoKey>> = new EncryptionPair<any, Map<string, SymmetricCryptoKey>>();
|
privateKey: EncryptionPair<string, ArrayBuffer> = new EncryptionPair<string, ArrayBuffer>();
|
||||||
keyHash?: string;
|
legacyEtmKey: SymmetricCryptoKey;
|
||||||
legacyEtmKey?: SymmetricCryptoKey;
|
publicKey: ArrayBuffer;
|
||||||
publicKey?: ArrayBuffer;
|
apiKeyClientSecret: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountProfile {
|
export class AccountProfile {
|
||||||
apiKeyClientId?: string;
|
apiKeyClientId: string;
|
||||||
apiKeyClientSecret?: string;
|
authenticationStatus: AuthenticationStatus;
|
||||||
authenticationStatus?: AuthenticationStatus;
|
convertAccountToKeyConnector: boolean;
|
||||||
convertAccountToKeyConnector?: boolean;
|
email: string;
|
||||||
email?: string;
|
emailVerified: boolean;
|
||||||
emailVerified?: boolean;
|
entityId: string;
|
||||||
entityId?: string;
|
entityType: string;
|
||||||
entityType?: string;
|
everBeenUnlocked: boolean;
|
||||||
everBeenUnlocked?: boolean;
|
forcePasswordReset: boolean;
|
||||||
forcePasswordReset?: boolean;
|
hasPremiumPersonally: boolean;
|
||||||
hasPremiumPersonally?: boolean;
|
lastActive: number;
|
||||||
lastActive?: number;
|
lastSync: string;
|
||||||
lastSync?: string;
|
ssoCodeVerifier: string;
|
||||||
ssoCodeVerifier?: string;
|
ssoOrganizationIdentifier: string;
|
||||||
ssoOrganizationIdentifier?: string;
|
ssoState: string;
|
||||||
ssoState?: string;
|
userId: string;
|
||||||
userId?: string;
|
usesKeyConnector: boolean;
|
||||||
usesKeyConnector?: boolean;
|
keyHash: string;
|
||||||
|
kdfIterations: number;
|
||||||
|
kdfType: KdfType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AccountSettings {
|
export class AccountSettings {
|
||||||
alwaysShowDock?: boolean;
|
alwaysShowDock: boolean;
|
||||||
autoConfirmFingerPrints?: boolean;
|
autoConfirmFingerPrints: boolean;
|
||||||
autoFillOnPageLoadDefault?: boolean;
|
autoFillOnPageLoadDefault: boolean;
|
||||||
biometricLocked?: boolean;
|
biometricLocked: boolean;
|
||||||
biometricText?: string;
|
biometricText: string;
|
||||||
biometricUnlock?: boolean;
|
biometricUnlock: boolean;
|
||||||
clearClipboard?: number;
|
clearClipboard: number;
|
||||||
defaultUriMatch?: UriMatchType;
|
defaultUriMatch: UriMatchType;
|
||||||
disableAddLoginNotification?: boolean;
|
disableAddLoginNotification: boolean;
|
||||||
disableAutoBiometricsPrompt?: boolean;
|
disableAutoBiometricsPrompt: boolean;
|
||||||
disableAutoTotpCopy?: boolean;
|
disableAutoTotpCopy: boolean;
|
||||||
disableBadgeCounter?: boolean;
|
disableBadgeCounter: boolean;
|
||||||
disableChangedPasswordNotification?: boolean;
|
disableChangedPasswordNotification: boolean;
|
||||||
disableContextMenuItem?: boolean;
|
disableContextMenuItem: boolean;
|
||||||
disableGa?: boolean;
|
disableGa: boolean;
|
||||||
dontShowCardsCurrentTab?: boolean;
|
dontShowCardsCurrentTab: boolean;
|
||||||
dontShowIdentitiesCurrentTab?: boolean;
|
dontShowIdentitiesCurrentTab: boolean;
|
||||||
enableAlwaysOnTop?: boolean;
|
enableAlwaysOnTop: boolean;
|
||||||
enableAutoFillOnPageLoad?: boolean;
|
enableAutoFillOnPageLoad: boolean;
|
||||||
enableBiometric?: boolean;
|
enableBiometric: boolean;
|
||||||
enableBiometrics?: boolean;
|
enableBiometrics: boolean;
|
||||||
enableBrowserIntegration?: boolean;
|
enableBrowserIntegration: boolean;
|
||||||
enableBrowserIntegrationFingerprint?: boolean;
|
enableBrowserIntegrationFingerprint: boolean;
|
||||||
enableCloseToTray?: boolean;
|
enableCloseToTray: boolean;
|
||||||
enableFullWidth?: boolean;
|
enableFullWidth: boolean;
|
||||||
enableGravitars?: boolean;
|
enableGravitars: boolean;
|
||||||
enableMinimizeToTray?: boolean;
|
enableMinimizeToTray: boolean;
|
||||||
enableStartToTray?: boolean;
|
enableStartToTray: boolean;
|
||||||
enableTray?: boolean;
|
enableTray: boolean;
|
||||||
environmentUrls?: any;
|
environmentUrls: any;
|
||||||
equivalentDomains?: any;
|
equivalentDomains?: any;
|
||||||
locale?: string;
|
locale: string;
|
||||||
minimizeOnCopyToClipboard?: boolean;
|
minimizeOnCopyToClipboard: boolean;
|
||||||
neverDomains?: { [id: string]: any };
|
neverDomains: { [id: string]: any };
|
||||||
noAutoPromptBiometrics?: boolean;
|
noAutoPromptBiometrics: boolean;
|
||||||
noAutoPromptBiometricsText?: string;
|
noAutoPromptBiometricsText: string;
|
||||||
openAtLogin?: boolean;
|
openAtLogin: boolean;
|
||||||
passwordGenerationOptions?: any;
|
passwordGenerationOptions: any;
|
||||||
pinProtected?: EncryptionPair<string, EncString> = new EncryptionPair<string, EncString>();
|
pinProtected: EncryptionPair<string, EncString> = new EncryptionPair<string, EncString>();
|
||||||
protectedPin?: string;
|
protectedPin: string;
|
||||||
settings?: any; // TODO: Merge whatever is going on here into the AccountSettings model properly
|
settings: any; // TODO: Merge whatever is going on here into the AccountSettings model properly
|
||||||
vaultTimeout?: number;
|
vaultTimeout: number;
|
||||||
vaultTimeoutAction?: string;
|
vaultTimeoutAction: string;
|
||||||
|
|
||||||
get serverUrl(): string {
|
get serverUrl(): string {
|
||||||
return this.environmentUrls?.base ?? 'bitwarden.com';
|
return this.environmentUrls?.base ?? 'bitwarden.com';
|
||||||
@@ -152,23 +152,23 @@ export class Account {
|
|||||||
Object.assign(this, {
|
Object.assign(this, {
|
||||||
data: {
|
data: {
|
||||||
...new AccountData(),
|
...new AccountData(),
|
||||||
...init.data,
|
...init?.data,
|
||||||
},
|
},
|
||||||
keys: {
|
keys: {
|
||||||
...new AccountKeys(),
|
...new AccountKeys(),
|
||||||
...init.keys,
|
...init?.keys,
|
||||||
},
|
},
|
||||||
profile: {
|
profile: {
|
||||||
...new AccountProfile(),
|
...new AccountProfile(),
|
||||||
...init.profile,
|
...init?.profile,
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
...new AccountSettings(),
|
...new AccountSettings(),
|
||||||
...init.settings,
|
...init?.settings,
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
...new AccountTokens(),
|
...new AccountTokens(),
|
||||||
...init.tokens,
|
...init?.tokens,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { HashPurpose } from '../enums/hashPurpose';
|
|||||||
import { KdfType } from '../enums/kdfType';
|
import { KdfType } from '../enums/kdfType';
|
||||||
import { TwoFactorProviderType } from '../enums/twoFactorProviderType';
|
import { TwoFactorProviderType } from '../enums/twoFactorProviderType';
|
||||||
|
|
||||||
import { Account } from '../models/domain/account';
|
import { Account, AccountData, AccountProfile, AccountTokens } from '../models/domain/account';
|
||||||
import { AuthResult } from '../models/domain/authResult';
|
import { AuthResult } from '../models/domain/authResult';
|
||||||
import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey';
|
import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey';
|
||||||
|
|
||||||
@@ -355,19 +355,23 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
const accountInformation = await this.tokenService.decodeToken(tokenResponse.accessToken);
|
const accountInformation = await this.tokenService.decodeToken(tokenResponse.accessToken);
|
||||||
await this.stateService.addAccount({
|
await this.stateService.addAccount({
|
||||||
profile: {
|
profile: {
|
||||||
userId: accountInformation.sub,
|
...new AccountProfile(),
|
||||||
email: accountInformation.email,
|
...{
|
||||||
apiKeyClientId: clientId,
|
userId: accountInformation.sub,
|
||||||
apiKeyClientSecret: clientSecret,
|
email: accountInformation.email,
|
||||||
hasPremiumPersonally: accountInformation.premium,
|
apiKeyClientId: clientId,
|
||||||
},
|
apiKeyClientSecret: clientSecret,
|
||||||
data: {
|
hasPremiumPersonally: accountInformation.premium,
|
||||||
kdfIterations: tokenResponse.kdfIterations,
|
kdfIterations: tokenResponse.kdfIterations,
|
||||||
kdfType: tokenResponse.kdf,
|
kdfType: tokenResponse.kdf,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
accessToken: tokenResponse.accessToken,
|
...new AccountTokens(),
|
||||||
refreshToken: tokenResponse.refreshToken,
|
...{
|
||||||
|
accessToken: tokenResponse.accessToken,
|
||||||
|
refreshToken: tokenResponse.refreshToken,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -120,12 +120,12 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getApiKeyClientSecret(options?: StorageOptions): Promise<string> {
|
async getApiKeyClientSecret(options?: StorageOptions): Promise<string> {
|
||||||
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.profile?.apiKeyClientSecret;
|
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.keys?.apiKeyClientSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setApiKeyClientSecret(value: string, options?: StorageOptions): Promise<void> {
|
async setApiKeyClientSecret(value: string, options?: StorageOptions): Promise<void> {
|
||||||
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
account.profile.apiKeyClientId = value;
|
account.keys.apiKeyClientSecret = value;
|
||||||
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,7 +619,7 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getEnableGravitars(options?: StorageOptions): Promise<boolean> {
|
async getEnableGravitars(options?: StorageOptions): Promise<boolean> {
|
||||||
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())))?.settings?.enableGravitars ?? true;
|
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())))?.settings?.enableGravitars ?? false;
|
||||||
}
|
}
|
||||||
async setEnableGravitars(value: boolean, options?: StorageOptions): Promise<void> {
|
async setEnableGravitars(value: boolean, options?: StorageOptions): Promise<void> {
|
||||||
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()));
|
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()));
|
||||||
@@ -831,30 +831,30 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getKdfIterations(options?: StorageOptions): Promise<number> {
|
async getKdfIterations(options?: StorageOptions): Promise<number> {
|
||||||
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.data?.kdfIterations;
|
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.profile?.kdfIterations;
|
||||||
}
|
}
|
||||||
async setKdfIterations(value: number, options?: StorageOptions): Promise<void> {
|
async setKdfIterations(value: number, options?: StorageOptions): Promise<void> {
|
||||||
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
account.data.kdfIterations = value;
|
account.profile.kdfIterations = value;
|
||||||
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getKdfType(options?: StorageOptions): Promise<KdfType> {
|
async getKdfType(options?: StorageOptions): Promise<KdfType> {
|
||||||
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.data?.kdfType;
|
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.profile?.kdfType;
|
||||||
}
|
}
|
||||||
async setKdfType(value: KdfType, options?: StorageOptions): Promise<void> {
|
async setKdfType(value: KdfType, options?: StorageOptions): Promise<void> {
|
||||||
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
account.data.kdfType = value;
|
account.profile.kdfType = value;
|
||||||
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getKeyHash(options?: StorageOptions): Promise<string> {
|
async getKeyHash(options?: StorageOptions): Promise<string> {
|
||||||
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.keys?.keyHash;
|
return (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())))?.profile?.keyHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setKeyHash(value: string, options?: StorageOptions): Promise<void> {
|
async setKeyHash(value: string, options?: StorageOptions): Promise<void> {
|
||||||
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
const account = await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
account.keys.keyHash = value;
|
account.profile.keyHash = value;
|
||||||
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
await this.saveAccount(account, this.reconcileOptions(options, await this.defaultOnDiskOptions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1284,7 +1284,14 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async scaffoldNewAccountStorage(account: Account): Promise<void> {
|
private async scaffoldNewAccountStorage(account: Account): Promise<void> {
|
||||||
const storedState = await this.storageService.get<State>('state', await this.defaultOnDiskOptions()) ?? new State();
|
await this.scaffoldNewAccountLocalStorage(account);
|
||||||
|
await this.scaffoldNewAccountSessionStorage(account);
|
||||||
|
await this.scaffoldNewAccountMemoryStorage(account);
|
||||||
|
await this.scaffoldNewAccountSecureStorage(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async scaffoldNewAccountLocalStorage(account: Account): Promise<void> {
|
||||||
|
const storedState = await this.storageService.get<State>('state', await this.defaultOnDiskLocalOptions()) ?? new State();
|
||||||
const storedAccount = storedState.accounts[account.profile.userId];
|
const storedAccount = storedState.accounts[account.profile.userId];
|
||||||
if (storedAccount != null) {
|
if (storedAccount != null) {
|
||||||
storedAccount.tokens.accessToken = account.tokens.accessToken;
|
storedAccount.tokens.accessToken = account.tokens.accessToken;
|
||||||
@@ -1293,10 +1300,30 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
}
|
}
|
||||||
storedState.accounts[account.profile.userId] = account;
|
storedState.accounts[account.profile.userId] = account;
|
||||||
await this.storageService.save('state', storedState, await this.defaultOnDiskLocalOptions());
|
await this.storageService.save('state', storedState, await this.defaultOnDiskLocalOptions());
|
||||||
await this.storageService.save('state', storedState, await this.defaultOnDiskMemoryOptions());
|
}
|
||||||
await this.storageService.save('state', storedState, await this.defaultOnDiskOptions());
|
|
||||||
|
|
||||||
await this.scaffoldNewAccountSecureStorage(account);
|
private async scaffoldNewAccountMemoryStorage(account: Account): Promise<void> {
|
||||||
|
const storedState = await this.storageService.get<State>('state', await this.defaultOnDiskMemoryOptions()) ?? new State();
|
||||||
|
const storedAccount = storedState.accounts[account.profile.userId];
|
||||||
|
if (storedAccount != null) {
|
||||||
|
storedAccount.tokens.accessToken = account.tokens.accessToken;
|
||||||
|
storedAccount.tokens.refreshToken = account.tokens.refreshToken;
|
||||||
|
account = storedAccount;
|
||||||
|
}
|
||||||
|
storedState.accounts[account.profile.userId] = account;
|
||||||
|
await this.storageService.save('state', storedState, await this.defaultOnDiskMemoryOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async scaffoldNewAccountSessionStorage(account: Account): Promise<void> {
|
||||||
|
const storedState = await this.storageService.get<State>('state', await this.defaultOnDiskOptions()) ?? new State();
|
||||||
|
const storedAccount = storedState.accounts[account.profile.userId];
|
||||||
|
if (storedAccount != null) {
|
||||||
|
storedAccount.tokens.accessToken = account.tokens.accessToken;
|
||||||
|
storedAccount.tokens.refreshToken = account.tokens.refreshToken;
|
||||||
|
account = storedAccount;
|
||||||
|
}
|
||||||
|
storedState.accounts[account.profile.userId] = account;
|
||||||
|
await this.storageService.save('state', storedState, await this.defaultOnDiskOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async scaffoldNewAccountSecureStorage(account: Account): Promise<void> {
|
private async scaffoldNewAccountSecureStorage(account: Account): Promise<void> {
|
||||||
@@ -1368,7 +1395,7 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
return {
|
return {
|
||||||
storageLocation: StorageLocation.Disk,
|
storageLocation: StorageLocation.Disk,
|
||||||
htmlStorageLocation: HtmlStorageLocation.Memory,
|
htmlStorageLocation: HtmlStorageLocation.Memory,
|
||||||
userId: await this.storageService.get('activeUserId'),
|
userId: await this.getUserId(),
|
||||||
useSecureStorage: false,
|
useSecureStorage: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1386,38 +1413,47 @@ export class StateService implements StateServiceAbstraction {
|
|||||||
return state?.activeUserId;
|
return state?.activeUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async removeAccountFromLocalStorage(userId: string): Promise<void> {
|
private async removeAccountFromLocalStorage(userId: string = this.state.activeUserId): Promise<void> {
|
||||||
const state = await this.secureStorageService.get<State>('state', { htmlStorageLocation: HtmlStorageLocation.Local });
|
const state = await this.secureStorageService.get<State>('state', { htmlStorageLocation: HtmlStorageLocation.Local });
|
||||||
if (state?.accounts[userId ?? this.state.activeUserId] == null) {
|
if (state?.accounts[userId] == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete state.accounts[userId ?? this.state.activeUserId];
|
state.accounts[userId] = new Account({
|
||||||
|
profile: state.accounts[userId].profile,
|
||||||
|
settings: state.accounts[userId].settings,
|
||||||
|
data: state.accounts[userId].data,
|
||||||
|
});
|
||||||
|
|
||||||
await this.storageService.save('state', state, { htmlStorageLocation: HtmlStorageLocation.Local });
|
await this.storageService.save('state', state, { htmlStorageLocation: HtmlStorageLocation.Local });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async removeAccountFromSessionStorage(userId: string): Promise<void> {
|
private async removeAccountFromSessionStorage(userId: string = this.state.activeUserId): Promise<void> {
|
||||||
const state = await this.secureStorageService.get<State>('state', { htmlStorageLocation: HtmlStorageLocation.Session });
|
const state = await this.secureStorageService.get<State>('state', { htmlStorageLocation: HtmlStorageLocation.Session });
|
||||||
const account = state?.accounts[userId ?? this.state.activeUserId];
|
if (state?.accounts[userId] == null) {
|
||||||
if (account == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete state.accounts[userId ?? this.state.activeUserId];
|
state.accounts[userId] = new Account({
|
||||||
|
profile: state.accounts[userId].profile,
|
||||||
|
settings: state.accounts[userId].settings,
|
||||||
|
data: state.accounts[userId].data,
|
||||||
|
});
|
||||||
|
|
||||||
await this.storageService.save('state', state, { htmlStorageLocation: HtmlStorageLocation.Session });
|
await this.storageService.save('state', state, { htmlStorageLocation: HtmlStorageLocation.Session });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async removeAccountFromSecureStorage(userId: string): Promise<void> {
|
private async removeAccountFromSecureStorage(userId: string = this.state.activeUserId): Promise<void> {
|
||||||
const state = await this.secureStorageService.get<State>('state');
|
const state = await this.secureStorageService.get<State>('state');
|
||||||
if (state?.accounts[userId ?? this.state.activeUserId] == null) {
|
if (state?.accounts[userId] == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delete state.accounts[userId ?? this.state.activeUserId];
|
state.accounts[userId] = null;
|
||||||
await this.secureStorageService.save('state', state);
|
await this.secureStorageService.save('state', state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeAccountFromMemory(userId: string): void {
|
private removeAccountFromMemory(userId: string = this.state.activeUserId): void {
|
||||||
if (this.state?.accounts[userId ?? this.state.activeUserId] == null) {
|
if (this.state?.accounts[userId] == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delete this.state.accounts[userId ?? this.state.activeUserId];
|
delete this.state.accounts[userId ?? this.state.activeUserId];
|
||||||
|
|||||||
Reference in New Issue
Block a user