1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

PS-813 Add memory storage to state service (#2892)

* Use abstract methods and generics in StorageService

* Prepend `Abstract` to abstract classes

* Create session browser storage service

* Use memory storage service for state memory

* Inject memory storage service

* Maintain filename extensions to help ide formatting

* Preserve state if it's still in memory

* Use jslib's memory storage service

* linter

* Create prototypes on stored objects

* standardize package scripts

* Add type safety to `withPrototype` decorators

* webpack notify manifest version

* Fix desktop

* linter

* Fix script

* Improve prototye application

* do not change prototype if it already matches desired
* fix error with object values prototype application

* Handle null state

* Apply prototypes to browser-specific state

* Add angular language server to recommended extensions

* Improve browser state service tests

* Start testing state Service

* Fix abstract returns

* Move test setup files to not be picked up by default glob matchers

* Add key generation service

* Add low-dependency encrypt service

* Back crypto service with encrypt service.

We'll want to work items that don't require state over to encrypt service

* Add new storage service and tests

* Properly init more stored values

* Fix reload issues when state service is recovering state from session storage

Co-authored-by: Thomas Avery <Thomas-Avery@users.noreply.github.com>
Co-authored-by: Justin Baur <admin@justinbaur.com>

* Simplify encrypt service

* Do not log mac failures for local-backed session storage

* `content` changed to `main` in #2245

* Fix CLI

* Remove loggin

* PR feedback

* Merge remote-tracking branch 'origin/master' into add-memory-storage-to-state-service

* Fix desktop

* Fix decrypt method signature

* Minify if not development

* Key is required

Co-authored-by: Thomas Avery <Thomas-Avery@users.noreply.github.com>
Co-authored-by: Justin Baur <admin@justinbaur.com>
This commit is contained in:
Matt Gibson
2022-06-27 13:38:12 -04:00
committed by GitHub
parent c044c5c770
commit 399b8c2b34
57 changed files with 1575 additions and 370 deletions

View File

@@ -8,6 +8,7 @@ import {
STATE_SERVICE_USE_CACHE,
LOCALES_DIRECTORY,
SYSTEM_LANGUAGE,
MEMORY_STORAGE,
} from "@bitwarden/angular/services/jslib-services.module";
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
@@ -23,9 +24,10 @@ import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/abstractions/platformUtils.service";
import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/abstractions/state.service";
import { StateMigrationService as StateMigrationServiceAbstraction } from "@bitwarden/common/abstractions/stateMigration.service";
import { StorageService as StorageServiceAbstraction } from "@bitwarden/common/abstractions/storage.service";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
import { ImportService } from "@bitwarden/common/services/import.service";
import { MemoryStorageService } from "@bitwarden/common/services/memoryStorage.service";
import { StateService as StateServiceAbstraction } from "../../abstractions/state.service";
import { Account } from "../../models/account";
@@ -33,7 +35,6 @@ import { GlobalState } from "../../models/globalState";
import { BroadcasterMessagingService } from "../../services/broadcasterMessaging.service";
import { HtmlStorageService } from "../../services/htmlStorage.service";
import { I18nService } from "../../services/i18n.service";
import { MemoryStorageService } from "../../services/memoryStorage.service";
import { PasswordRepromptService } from "../../services/passwordReprompt.service";
import { StateService } from "../../services/state.service";
import { StateMigrationService } from "../../services/stateMigration.service";
@@ -77,13 +78,17 @@ import { RouterService } from "./router.service";
useClass: I18nService,
deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY],
},
{ provide: StorageServiceAbstraction, useClass: HtmlStorageService },
{ provide: AbstractStorageService, useClass: HtmlStorageService },
{
provide: SECURE_STORAGE,
// TODO: platformUtilsService.isDev has a helper for this, but using that service here results in a circular dependency.
// We have a tech debt item in the backlog to break up platformUtilsService, but in the meantime simply checking the environement here is less cumbersome.
useClass: process.env.NODE_ENV === "development" ? HtmlStorageService : MemoryStorageService,
},
{
provide: MEMORY_STORAGE,
useClass: MemoryStorageService,
},
{
provide: PlatformUtilsServiceAbstraction,
useClass: WebPlatformUtilsService,
@@ -106,14 +111,15 @@ import { RouterService } from "./router.service";
{
provide: StateMigrationServiceAbstraction,
useClass: StateMigrationService,
deps: [StorageServiceAbstraction, SECURE_STORAGE, STATE_FACTORY],
deps: [AbstractStorageService, SECURE_STORAGE, STATE_FACTORY],
},
{
provide: StateServiceAbstraction,
useClass: StateService,
deps: [
StorageServiceAbstraction,
AbstractStorageService,
SECURE_STORAGE,
MEMORY_STORAGE,
LogService,
StateMigrationServiceAbstraction,
STATE_FACTORY,

View File

@@ -1,11 +1,11 @@
import { Injectable } from "@angular/core";
import { StorageService } from "@bitwarden/common/abstractions/storage.service";
import { AbstractStorageService } from "@bitwarden/common/abstractions/storage.service";
import { HtmlStorageLocation } from "@bitwarden/common/enums/htmlStorageLocation";
import { StorageOptions } from "@bitwarden/common/models/domain/storageOptions";
@Injectable()
export class HtmlStorageService implements StorageService {
export class HtmlStorageService implements AbstractStorageService {
get defaultOptions(): StorageOptions {
return { htmlStorageLocation: HtmlStorageLocation.Session };
}

View File

@@ -1,30 +0,0 @@
import { StorageService } from "@bitwarden/common/abstractions/storage.service";
export class MemoryStorageService implements StorageService {
private store = new Map<string, any>();
get<T>(key: string): Promise<T> {
if (this.store.has(key)) {
const obj = this.store.get(key);
return Promise.resolve(obj as T);
}
return Promise.resolve(null);
}
async has(key: string): Promise<boolean> {
return this.get(key) != null;
}
save(key: string, obj: any): Promise<any> {
if (obj == null) {
return this.remove(key);
}
this.store.set(key, obj);
return Promise.resolve();
}
remove(key: string): Promise<any> {
this.store.delete(key);
return Promise.resolve();
}
}

View File

@@ -37,7 +37,7 @@ export class StateService
}
async getEncryptedCiphers(options?: StorageOptions): Promise<{ [id: string]: CipherData }> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.getEncryptedCiphers(options);
}
@@ -45,14 +45,14 @@ export class StateService
value: { [id: string]: CipherData },
options?: StorageOptions
): Promise<void> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.setEncryptedCiphers(value, options);
}
async getEncryptedCollections(
options?: StorageOptions
): Promise<{ [id: string]: CollectionData }> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.getEncryptedCollections(options);
}
@@ -60,12 +60,12 @@ export class StateService
value: { [id: string]: CollectionData },
options?: StorageOptions
): Promise<void> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.setEncryptedCollections(value, options);
}
async getEncryptedFolders(options?: StorageOptions): Promise<{ [id: string]: FolderData }> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.getEncryptedFolders(options);
}
@@ -73,12 +73,12 @@ export class StateService
value: { [id: string]: FolderData },
options?: StorageOptions
): Promise<void> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.setEncryptedFolders(value, options);
}
async getEncryptedSends(options?: StorageOptions): Promise<{ [id: string]: SendData }> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.getEncryptedSends(options);
}
@@ -86,17 +86,17 @@ export class StateService
value: { [id: string]: SendData },
options?: StorageOptions
): Promise<void> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.setEncryptedSends(value, options);
}
override async getLastSync(options?: StorageOptions): Promise<string> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.getLastSync(options);
}
override async setLastSync(value: string, options?: StorageOptions): Promise<void> {
options = this.reconcileOptions(options, this.defaultInMemoryOptions);
options = this.reconcileOptions(options, await this.defaultInMemoryOptions());
return await super.setLastSync(value, options);
}
}