mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 23:33:31 +00:00
[deps] Autofill: Update prettier to v3 (#7014)
* [deps] Autofill: Update prettier to v3 * prettier formatting updates --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jonathan Prusik <jprusik@classynemesis.com>
This commit is contained in:
@@ -11,14 +11,14 @@ export abstract class ConfigServiceAbstraction {
|
||||
cloudRegion$: Observable<Region>;
|
||||
getFeatureFlag$: <T extends boolean | number | string>(
|
||||
key: FeatureFlag,
|
||||
defaultValue?: T
|
||||
defaultValue?: T,
|
||||
) => Observable<T>;
|
||||
getFeatureFlag: <T extends boolean | number | string>(
|
||||
key: FeatureFlag,
|
||||
defaultValue?: T
|
||||
defaultValue?: T,
|
||||
) => Promise<T>;
|
||||
checkServerMeetsVersionRequirement$: (
|
||||
minimumRequiredServerVersion: SemVer
|
||||
minimumRequiredServerVersion: SemVer,
|
||||
) => Observable<boolean>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,42 +7,42 @@ export abstract class CryptoFunctionService {
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
algorithm: "sha256" | "sha512",
|
||||
iterations: number
|
||||
iterations: number,
|
||||
) => Promise<Uint8Array>;
|
||||
argon2: (
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number
|
||||
parallelism: number,
|
||||
) => Promise<Uint8Array>;
|
||||
hkdf: (
|
||||
ikm: Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
info: string | Uint8Array,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
algorithm: "sha256" | "sha512",
|
||||
) => Promise<Uint8Array>;
|
||||
hkdfExpand: (
|
||||
prk: Uint8Array,
|
||||
info: string | Uint8Array,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
algorithm: "sha256" | "sha512",
|
||||
) => Promise<Uint8Array>;
|
||||
hash: (
|
||||
value: string | Uint8Array,
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5"
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5",
|
||||
) => Promise<Uint8Array>;
|
||||
hmac: (
|
||||
value: Uint8Array,
|
||||
key: Uint8Array,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
algorithm: "sha1" | "sha256" | "sha512",
|
||||
) => Promise<Uint8Array>;
|
||||
compare: (a: Uint8Array, b: Uint8Array) => Promise<boolean>;
|
||||
hmacFast: (
|
||||
value: Uint8Array | string,
|
||||
key: Uint8Array | string,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
algorithm: "sha1" | "sha256" | "sha512",
|
||||
) => Promise<Uint8Array | string>;
|
||||
compareFast: (a: Uint8Array | string, b: Uint8Array | string) => Promise<boolean>;
|
||||
aesEncrypt: (data: Uint8Array, iv: Uint8Array, key: Uint8Array) => Promise<Uint8Array>;
|
||||
@@ -50,27 +50,27 @@ export abstract class CryptoFunctionService {
|
||||
data: string,
|
||||
iv: string,
|
||||
mac: string,
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
) => DecryptParameters<Uint8Array | string>;
|
||||
aesDecryptFast: (
|
||||
parameters: DecryptParameters<Uint8Array | string>,
|
||||
mode: "cbc" | "ecb"
|
||||
mode: "cbc" | "ecb",
|
||||
) => Promise<string>;
|
||||
aesDecrypt: (
|
||||
data: Uint8Array,
|
||||
iv: Uint8Array,
|
||||
key: Uint8Array,
|
||||
mode: "cbc" | "ecb"
|
||||
mode: "cbc" | "ecb",
|
||||
) => Promise<Uint8Array>;
|
||||
rsaEncrypt: (
|
||||
data: Uint8Array,
|
||||
publicKey: Uint8Array,
|
||||
algorithm: "sha1" | "sha256"
|
||||
algorithm: "sha1" | "sha256",
|
||||
) => Promise<Uint8Array>;
|
||||
rsaDecrypt: (
|
||||
data: Uint8Array,
|
||||
privateKey: Uint8Array,
|
||||
algorithm: "sha1" | "sha256"
|
||||
algorithm: "sha1" | "sha256",
|
||||
) => Promise<Uint8Array>;
|
||||
rsaExtractPublicKey: (privateKey: Uint8Array) => Promise<Uint8Array>;
|
||||
rsaGenerateKeyPair: (length: 1024 | 2048 | 4096) => Promise<[Uint8Array, Uint8Array]>;
|
||||
|
||||
@@ -133,7 +133,7 @@ export abstract class CryptoService {
|
||||
password: string,
|
||||
email: string,
|
||||
kdf: KdfType,
|
||||
KdfConfig: KdfConfig
|
||||
KdfConfig: KdfConfig,
|
||||
) => Promise<MasterKey>;
|
||||
/**
|
||||
* Clears the user's master key
|
||||
@@ -149,7 +149,7 @@ export abstract class CryptoService {
|
||||
*/
|
||||
encryptUserKeyWithMasterKey: (
|
||||
masterKey: MasterKey,
|
||||
userKey?: UserKey
|
||||
userKey?: UserKey,
|
||||
) => Promise<[UserKey, EncString]>;
|
||||
/**
|
||||
* Decrypts the user key with the provided master key
|
||||
@@ -161,7 +161,7 @@ export abstract class CryptoService {
|
||||
decryptUserKeyWithMasterKey: (
|
||||
masterKey: MasterKey,
|
||||
userKey?: EncString,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
) => Promise<UserKey>;
|
||||
/**
|
||||
* Creates a master password hash from the user's master password. Can
|
||||
@@ -204,7 +204,7 @@ export abstract class CryptoService {
|
||||
*/
|
||||
setOrgKeys: (
|
||||
orgs: ProfileOrganizationResponse[],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[]
|
||||
providerOrgs: ProfileProviderOrganizationResponse[],
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* Returns the organization's symmetric key
|
||||
@@ -322,7 +322,7 @@ export abstract class CryptoService {
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
protectedKeyCs?: EncString
|
||||
protectedKeyCs?: EncString,
|
||||
) => Promise<UserKey>;
|
||||
/**
|
||||
* Creates a new Pin key that encrypts the user key instead of the
|
||||
@@ -342,7 +342,7 @@ export abstract class CryptoService {
|
||||
email: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
oldPinKey: EncString
|
||||
oldPinKey: EncString,
|
||||
) => Promise<UserKey>;
|
||||
/**
|
||||
* Replaces old master auto keys with new user auto keys
|
||||
@@ -398,7 +398,7 @@ export abstract class CryptoService {
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
protectedKeyCs?: EncString
|
||||
protectedKeyCs?: EncString,
|
||||
) => Promise<MasterKey>;
|
||||
/**
|
||||
* Previously, the master key was used for any additional key like the biometrics or pin key.
|
||||
|
||||
@@ -9,13 +9,13 @@ export abstract class EncryptService {
|
||||
abstract encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString>;
|
||||
abstract encryptToBytes: (
|
||||
plainValue: Uint8Array,
|
||||
key?: SymmetricCryptoKey
|
||||
key?: SymmetricCryptoKey,
|
||||
) => Promise<EncArrayBuffer>;
|
||||
abstract decryptToUtf8: (encString: EncString, key: SymmetricCryptoKey) => Promise<string>;
|
||||
abstract decryptToBytes: (encThing: Encrypted, key: SymmetricCryptoKey) => Promise<Uint8Array>;
|
||||
abstract resolveLegacyKey: (key: SymmetricCryptoKey, encThing: Encrypted) => SymmetricCryptoKey;
|
||||
abstract decryptItems: <T extends InitializerMetadata>(
|
||||
items: Decryptable<T>[],
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
) => Promise<T[]>;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ export abstract class FileUploadService {
|
||||
uploadData: { url: string; fileUploadType: FileUploadType },
|
||||
fileName: EncString,
|
||||
encryptedFileData: EncArrayBuffer,
|
||||
fileUploadMethods: FileUploadApiMethods
|
||||
fileUploadMethods: FileUploadApiMethods,
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export abstract class PlatformUtilsService {
|
||||
type: "error" | "success" | "warning" | "info",
|
||||
title: string,
|
||||
text: string | string[],
|
||||
options?: ToastOptions
|
||||
options?: ToastOptions,
|
||||
) => void;
|
||||
isDev: () => boolean;
|
||||
isSelfHost: () => boolean;
|
||||
|
||||
@@ -186,18 +186,18 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getDecryptedCollections: (options?: StorageOptions) => Promise<CollectionView[]>;
|
||||
setDecryptedCollections: (value: CollectionView[], options?: StorageOptions) => Promise<void>;
|
||||
getDecryptedOrganizationKeys: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
setDecryptedOrganizationKeys: (
|
||||
value: Map<string, SymmetricCryptoKey>,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getDecryptedPasswordGenerationHistory: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<GeneratedPasswordHistory[]>;
|
||||
setDecryptedPasswordGenerationHistory: (
|
||||
value: GeneratedPasswordHistory[],
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* @deprecated For migration purposes only, use getDecryptedUserKeyPin instead
|
||||
@@ -220,7 +220,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getDecryptedProviderKeys: (options?: StorageOptions) => Promise<Map<string, SymmetricCryptoKey>>;
|
||||
setDecryptedProviderKeys: (
|
||||
value: Map<string, SymmetricCryptoKey>,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* @deprecated Do not call this directly, use SendService
|
||||
@@ -243,7 +243,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getDisableChangedPasswordNotification: (options?: StorageOptions) => Promise<boolean>;
|
||||
setDisableChangedPasswordNotification: (
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEnablePasskeys: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnablePasskeys: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
@@ -272,16 +272,16 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getAdminAuthRequest: (options?: StorageOptions) => Promise<AdminAuthRequestStorable | null>;
|
||||
setAdminAuthRequest: (
|
||||
adminAuthRequest: AdminAuthRequestStorable,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getShouldTrustDevice: (options?: StorageOptions) => Promise<boolean | null>;
|
||||
setShouldTrustDevice: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getAccountDecryptionOptions: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<AccountDecryptionOptions | null>;
|
||||
setAccountDecryptionOptions: (
|
||||
value: AccountDecryptionOptions,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEmail: (options?: StorageOptions) => Promise<string>;
|
||||
setEmail: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
@@ -298,14 +298,14 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getEnableBrowserIntegrationFingerprint: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableBrowserIntegrationFingerprint: (
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEnableCloseToTray: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableCloseToTray: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
getEnableDuckDuckGoBrowserIntegration: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableDuckDuckGoBrowserIntegration: (
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEnableFullWidth: (options?: StorageOptions) => Promise<boolean>;
|
||||
setEnableFullWidth: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||
@@ -318,12 +318,12 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getEncryptedCiphers: (options?: StorageOptions) => Promise<{ [id: string]: CipherData }>;
|
||||
setEncryptedCiphers: (
|
||||
value: { [id: string]: CipherData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedCollections: (options?: StorageOptions) => Promise<{ [id: string]: CollectionData }>;
|
||||
setEncryptedCollections: (
|
||||
value: { [id: string]: CollectionData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* @deprecated Do not call this directly, use FolderService
|
||||
@@ -334,21 +334,21 @@ export abstract class StateService<T extends Account = Account> {
|
||||
*/
|
||||
setEncryptedFolders: (
|
||||
value: { [id: string]: FolderData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedOrganizationKeys: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<{ [orgId: string]: EncryptedOrganizationKeyData }>;
|
||||
setEncryptedOrganizationKeys: (
|
||||
value: { [orgId: string]: EncryptedOrganizationKeyData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedPasswordGenerationHistory: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<GeneratedPasswordHistory[]>;
|
||||
setEncryptedPasswordGenerationHistory: (
|
||||
value: GeneratedPasswordHistory[],
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* @deprecated For migration purposes only, use getEncryptedUserKeyPin instead
|
||||
@@ -367,7 +367,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
*/
|
||||
setEncryptedPolicies: (
|
||||
value: { [id: string]: PolicyData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getEncryptedPrivateKey: (options?: StorageOptions) => Promise<string>;
|
||||
setEncryptedPrivateKey: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
@@ -400,7 +400,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getForceSetPasswordReason: (options?: StorageOptions) => Promise<ForceSetPasswordReason>;
|
||||
setForceSetPasswordReason: (
|
||||
value: ForceSetPasswordReason,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getInstalledVersion: (options?: StorageOptions) => Promise<string>;
|
||||
setInstalledVersion: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
@@ -418,7 +418,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getLocalData: (options?: StorageOptions) => Promise<{ [cipherId: string]: LocalData }>;
|
||||
setLocalData: (
|
||||
value: { [cipherId: string]: LocalData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getLocale: (options?: StorageOptions) => Promise<string>;
|
||||
setLocale: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
@@ -443,17 +443,17 @@ export abstract class StateService<T extends Account = Account> {
|
||||
*/
|
||||
setOrganizations: (
|
||||
value: { [id: string]: OrganizationData },
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getPasswordGenerationOptions: (options?: StorageOptions) => Promise<PasswordGeneratorOptions>;
|
||||
setPasswordGenerationOptions: (
|
||||
value: PasswordGeneratorOptions,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getUsernameGenerationOptions: (options?: StorageOptions) => Promise<UsernameGeneratorOptions>;
|
||||
setUsernameGenerationOptions: (
|
||||
value: UsernameGeneratorOptions,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getGeneratorOptions: (options?: StorageOptions) => Promise<GeneratorOptions>;
|
||||
setGeneratorOptions: (value: GeneratorOptions, options?: StorageOptions) => Promise<void>;
|
||||
@@ -492,7 +492,7 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getUserSsoOrganizationIdentifier: (options?: StorageOptions) => Promise<string>;
|
||||
setUserSsoOrganizationIdentifier: (
|
||||
value: string | null,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getTheme: (options?: StorageOptions) => Promise<ThemeType>;
|
||||
setTheme: (value: ThemeType, options?: StorageOptions) => Promise<void>;
|
||||
@@ -521,18 +521,18 @@ export abstract class StateService<T extends Account = Account> {
|
||||
getAvatarColor: (options?: StorageOptions) => Promise<string | null | undefined>;
|
||||
setAvatarColor: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getActivateAutoFillOnPageLoadFromPolicy: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<boolean | undefined>;
|
||||
setActivateAutoFillOnPageLoadFromPolicy: (
|
||||
value: boolean,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
getSMOnboardingTasks: (
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<Record<string, Record<string, boolean>>>;
|
||||
setSMOnboardingTasks: (
|
||||
value: Record<string, Record<string, boolean>>,
|
||||
options?: StorageOptions
|
||||
options?: StorageOptions,
|
||||
) => Promise<void>;
|
||||
/**
|
||||
* fetches string value of URL user tried to navigate to while unauthenticated.
|
||||
|
||||
@@ -6,14 +6,14 @@ import { GlobalStateFactory } from "./global-state-factory";
|
||||
|
||||
export class StateFactory<
|
||||
TGlobal extends GlobalState = GlobalState,
|
||||
TAccount extends Account = Account
|
||||
TAccount extends Account = Account,
|
||||
> {
|
||||
private globalStateFactory: GlobalStateFactory<TGlobal>;
|
||||
private accountFactory: AccountFactory<TAccount>;
|
||||
|
||||
constructor(
|
||||
globalStateConstructor: new (init: Partial<TGlobal>) => TGlobal,
|
||||
accountConstructor: new (init: Partial<TAccount>) => TAccount
|
||||
accountConstructor: new (init: Partial<TAccount>) => TAccount,
|
||||
) {
|
||||
this.globalStateFactory = new GlobalStateFactory(globalStateConstructor);
|
||||
this.accountFactory = new AccountFactory(accountConstructor);
|
||||
|
||||
@@ -56,7 +56,7 @@ export function devFlagEnabled<DevFlags extends SharedDevFlags>(flag: keyof DevF
|
||||
* @throws Error if the flag is not enabled
|
||||
*/
|
||||
export function devFlagValue<DevFlags extends SharedDevFlags>(
|
||||
flag: keyof DevFlags
|
||||
flag: keyof DevFlags,
|
||||
): DevFlags[keyof DevFlags] {
|
||||
if (!devFlagEnabled(flag)) {
|
||||
throw new Error(`This method should not be called, it is protected by a disabled dev flag.`);
|
||||
|
||||
@@ -8,7 +8,7 @@ export function throttle(limit: number, throttleKey: (args: any[]) => string) {
|
||||
return <T>(
|
||||
target: any,
|
||||
propertyKey: string | symbol,
|
||||
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<T>>
|
||||
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<T>>,
|
||||
) => {
|
||||
const originalMethod: () => Promise<T> = descriptor.value;
|
||||
const allThrottles = new Map<any, Map<string, (() => void)[]>>();
|
||||
|
||||
@@ -49,13 +49,13 @@ describe("Utils Service", () => {
|
||||
expect(Utils.getDomain("https://www.vault.bitwarden.com")).toBe("bitwarden.com");
|
||||
|
||||
expect(
|
||||
Utils.getDomain("user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
Utils.getDomain("user:password@bitwarden.com:8080/password/sites?and&query#hash"),
|
||||
).toBe("bitwarden.com");
|
||||
expect(
|
||||
Utils.getDomain("http://user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
Utils.getDomain("http://user:password@bitwarden.com:8080/password/sites?and&query#hash"),
|
||||
).toBe("bitwarden.com");
|
||||
expect(
|
||||
Utils.getDomain("https://user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
Utils.getDomain("https://user:password@bitwarden.com:8080/password/sites?and&query#hash"),
|
||||
).toBe("bitwarden.com");
|
||||
|
||||
expect(Utils.getDomain("bitwarden.unknown")).toBe("bitwarden.unknown");
|
||||
@@ -87,7 +87,7 @@ describe("Utils Service", () => {
|
||||
expect(Utils.getDomain("subdomain.xn--btwarden-65a.com")).toBe("xn--btwarden-65a.com");
|
||||
expect(Utils.getDomain("http://subdomain.xn--btwarden-65a.com")).toBe("xn--btwarden-65a.com");
|
||||
expect(Utils.getDomain("https://subdomain.xn--btwarden-65a.com")).toBe(
|
||||
"xn--btwarden-65a.com"
|
||||
"xn--btwarden-65a.com",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -165,10 +165,10 @@ describe("Utils Service", () => {
|
||||
expect(Utils.getHostname("https://www.vault.bitwarden.com")).toBe("www.vault.bitwarden.com");
|
||||
|
||||
expect(
|
||||
Utils.getHostname("user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
Utils.getHostname("user:password@bitwarden.com:8080/password/sites?and&query#hash"),
|
||||
).toBe("bitwarden.com");
|
||||
expect(
|
||||
Utils.getHostname("https://user:password@bitwarden.com:8080/password/sites?and&query#hash")
|
||||
Utils.getHostname("https://user:password@bitwarden.com:8080/password/sites?and&query#hash"),
|
||||
).toBe("bitwarden.com");
|
||||
expect(Utils.getHostname("https://bitwarden.unknown")).toBe("bitwarden.unknown");
|
||||
});
|
||||
@@ -195,13 +195,13 @@ describe("Utils Service", () => {
|
||||
expect(Utils.getHostname("xn--btwarden-65a.com")).toBe("xn--btwarden-65a.com");
|
||||
|
||||
expect(Utils.getHostname("subdomain.xn--btwarden-65a.com")).toBe(
|
||||
"subdomain.xn--btwarden-65a.com"
|
||||
"subdomain.xn--btwarden-65a.com",
|
||||
);
|
||||
expect(Utils.getHostname("http://subdomain.xn--btwarden-65a.com")).toBe(
|
||||
"subdomain.xn--btwarden-65a.com"
|
||||
"subdomain.xn--btwarden-65a.com",
|
||||
);
|
||||
expect(Utils.getHostname("https://subdomain.xn--btwarden-65a.com")).toBe(
|
||||
"subdomain.xn--btwarden-65a.com"
|
||||
"subdomain.xn--btwarden-65a.com",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -337,7 +337,7 @@ describe("Utils Service", () => {
|
||||
|
||||
// Compare the original ArrayBuffer with the round-tripped ArrayBuffer
|
||||
expect(roundTrippedArray).toEqual(originalArray);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
runInBothEnvironments(
|
||||
@@ -351,7 +351,7 @@ describe("Utils Service", () => {
|
||||
|
||||
// Compare the original base64 string with the round-tripped base64 string
|
||||
expect(roundTrippedB64String).toBe(b64HelloWorldString);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -402,7 +402,7 @@ describe("Utils Service", () => {
|
||||
const hexString = Utils.fromBufferToHex(largeBuffer);
|
||||
const expectedHexString = createSequentialHexByteString(256).repeat(4);
|
||||
expect(hexString).toBe(expectedHexString);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
runInBothEnvironments("should correctly convert a buffer with a single byte to hex", () => {
|
||||
@@ -417,7 +417,7 @@ describe("Utils Service", () => {
|
||||
const oddByteBuffer = new Uint8Array([0x01, 0x23, 0x45, 0x67, 0x89]).buffer;
|
||||
const hexString = Utils.fromBufferToHex(oddByteBuffer);
|
||||
expect(hexString).toBe("0123456789");
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -467,7 +467,7 @@ describe("Utils Service", () => {
|
||||
const hexString = Utils.fromBufferToHex(originalBuffer);
|
||||
const roundTripBuffer = Utils.hexStringToArrayBuffer(hexString);
|
||||
expect(new Uint8Array(roundTripBuffer)).toEqual(new Uint8Array(originalBuffer));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
runInBothEnvironments(
|
||||
@@ -477,7 +477,7 @@ describe("Utils Service", () => {
|
||||
const bufferFromHex = Utils.hexStringToArrayBuffer(hexString);
|
||||
const roundTripHexString = Utils.fromBufferToHex(bufferFromHex);
|
||||
expect(roundTripHexString).toBe(hexString);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -535,7 +535,7 @@ describe("Utils Service", () => {
|
||||
new Map([
|
||||
[1, "value1"],
|
||||
[2, "value2"],
|
||||
])
|
||||
]),
|
||||
);
|
||||
expect(Utils.mapToRecord(result)).toEqual(record);
|
||||
});
|
||||
@@ -552,16 +552,16 @@ describe("Utils Service", () => {
|
||||
describe("encodeRFC3986URIComponent", () => {
|
||||
it("returns input string with expected encoded chars", () => {
|
||||
expect(Utils.encodeRFC3986URIComponent("test'user@example.com")).toBe(
|
||||
"test%27user%40example.com"
|
||||
"test%27user%40example.com",
|
||||
);
|
||||
expect(Utils.encodeRFC3986URIComponent("(test)user@example.com")).toBe(
|
||||
"%28test%29user%40example.com"
|
||||
"%28test%29user%40example.com",
|
||||
);
|
||||
expect(Utils.encodeRFC3986URIComponent("testuser!@example.com")).toBe(
|
||||
"testuser%21%40example.com"
|
||||
"testuser%21%40example.com",
|
||||
);
|
||||
expect(Utils.encodeRFC3986URIComponent("Test*User@example.com")).toBe(
|
||||
"Test%2AUser%40example.com"
|
||||
"Test%2AUser%40example.com",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -581,7 +581,7 @@ describe("Utils Service", () => {
|
||||
|
||||
it("removes multiple encoded traversals", () => {
|
||||
expect(
|
||||
Utils.normalizePath("api/sends/access/..%2f..%2f..%2fapi%2fsends%2faccess%2fsendkey")
|
||||
Utils.normalizePath("api/sends/access/..%2f..%2f..%2fapi%2fsends%2faccess%2fsendkey"),
|
||||
).toBe(path.normalize("api/sends/access/sendkey"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -261,7 +261,7 @@ export class Utils {
|
||||
static isGuid(id: string) {
|
||||
return RegExp(
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,
|
||||
"i"
|
||||
"i",
|
||||
).test(id);
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ export class Utils {
|
||||
}
|
||||
map.set(
|
||||
decodeURIComponent(parts[0]).toLowerCase(),
|
||||
parts[1] == null ? "" : decodeURIComponent(parts[1])
|
||||
parts[1] == null ? "" : decodeURIComponent(parts[1]),
|
||||
);
|
||||
});
|
||||
return map;
|
||||
@@ -368,7 +368,7 @@ export class Utils {
|
||||
|
||||
static getSortFunction<T>(
|
||||
i18nService: I18nService,
|
||||
prop: { [K in keyof T]: T[K] extends string ? K : never }[keyof T]
|
||||
prop: { [K in keyof T]: T[K] extends string ? K : never }[keyof T],
|
||||
): (a: T, b: T) => number {
|
||||
return (a, b) => {
|
||||
if (a[prop] == null && b[prop] != null) {
|
||||
@@ -521,7 +521,7 @@ export class Utils {
|
||||
/** Applies Object.assign, but converts the type nicely using Type-Fest Merge<Destination, Source> */
|
||||
static merge<Destination, Source>(
|
||||
destination: Destination,
|
||||
source: Source
|
||||
source: Source,
|
||||
): Merge<Destination, Source> {
|
||||
return Object.assign(destination, source) as unknown as Merge<Destination, Source>;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ export class Utils {
|
||||
static encodeRFC3986URIComponent(str: string): string {
|
||||
return encodeURIComponent(str).replace(
|
||||
/[!'()*]/g,
|
||||
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
||||
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -552,10 +552,10 @@ export class Utils {
|
||||
((a) => {
|
||||
if (
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
||||
a
|
||||
a,
|
||||
) ||
|
||||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
|
||||
a.substr(0, 4)
|
||||
a.substr(0, 4),
|
||||
)
|
||||
) {
|
||||
mobile = true;
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("AccountKeys", () => {
|
||||
const accountKeys = new AccountKeys();
|
||||
const deviceKeyBytesLength = 64;
|
||||
accountKeys.deviceKey = new SymmetricCryptoKey(
|
||||
new Uint8Array(deviceKeyBytesLength).buffer as CsprngArray
|
||||
new Uint8Array(deviceKeyBytesLength).buffer as CsprngArray,
|
||||
) as DeviceKey;
|
||||
|
||||
// Act
|
||||
|
||||
@@ -51,7 +51,7 @@ export class EncryptionPair<TEncrypted, TDecrypted> {
|
||||
static fromJSON<TEncrypted, TDecrypted>(
|
||||
obj: { encrypted?: Jsonify<TEncrypted>; decrypted?: string | Jsonify<TDecrypted> },
|
||||
decryptedFromJson?: (decObj: Jsonify<TDecrypted> | string) => TDecrypted,
|
||||
encryptedFromJson?: (encObj: Jsonify<TEncrypted>) => TEncrypted
|
||||
encryptedFromJson?: (encObj: Jsonify<TEncrypted>) => TEncrypted,
|
||||
) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
@@ -159,12 +159,12 @@ export class AccountKeys {
|
||||
cryptoMasterKey: SymmetricCryptoKey.fromJSON(obj?.cryptoMasterKey),
|
||||
cryptoSymmetricKey: EncryptionPair.fromJSON(
|
||||
obj?.cryptoSymmetricKey,
|
||||
SymmetricCryptoKey.fromJSON
|
||||
SymmetricCryptoKey.fromJSON,
|
||||
),
|
||||
organizationKeys: AccountKeys.initRecordEncryptionPairsFromJSON(obj?.organizationKeys),
|
||||
providerKeys: AccountKeys.initRecordEncryptionPairsFromJSON(obj?.providerKeys),
|
||||
privateKey: EncryptionPair.fromJSON<string, Uint8Array>(obj?.privateKey, (decObj: string) =>
|
||||
Utils.fromByteStringToArray(decObj)
|
||||
Utils.fromByteStringToArray(decObj),
|
||||
),
|
||||
publicKey: Utils.fromByteStringToArray(obj?.publicKey),
|
||||
});
|
||||
@@ -266,7 +266,7 @@ export class AccountSettings {
|
||||
environmentUrls: EnvironmentUrls.fromJSON(obj?.environmentUrls),
|
||||
pinProtected: EncryptionPair.fromJSON<string, EncString>(
|
||||
obj?.pinProtected,
|
||||
EncString.fromJSON
|
||||
EncString.fromJSON,
|
||||
),
|
||||
serverConfig: ServerConfigData.fromJSON(obj?.serverConfig),
|
||||
});
|
||||
@@ -330,13 +330,13 @@ export class AccountDecryptionOptions {
|
||||
accountDecryptionOptions.trustedDeviceOption = new TrustedDeviceUserDecryptionOption(
|
||||
responseOptions.trustedDeviceOption.hasAdminApproval,
|
||||
responseOptions.trustedDeviceOption.hasLoginApprovingDevice,
|
||||
responseOptions.trustedDeviceOption.hasManageResetPasswordPermission
|
||||
responseOptions.trustedDeviceOption.hasManageResetPasswordPermission,
|
||||
);
|
||||
}
|
||||
|
||||
if (responseOptions.keyConnectorOption) {
|
||||
accountDecryptionOptions.keyConnectorOption = new KeyConnectorUserDecryptionOption(
|
||||
responseOptions.keyConnectorOption.keyConnectorUrl
|
||||
responseOptions.keyConnectorOption.keyConnectorUrl,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -349,7 +349,7 @@ export class AccountDecryptionOptions {
|
||||
accountDecryptionOptions.hasMasterPassword = !usingKeyConnector;
|
||||
if (usingKeyConnector) {
|
||||
accountDecryptionOptions.keyConnectorOption = new KeyConnectorUserDecryptionOption(
|
||||
response.keyConnectorUrl
|
||||
response.keyConnectorUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -367,13 +367,13 @@ export class AccountDecryptionOptions {
|
||||
accountDecryptionOptions.trustedDeviceOption = new TrustedDeviceUserDecryptionOption(
|
||||
obj.trustedDeviceOption.hasAdminApproval,
|
||||
obj.trustedDeviceOption.hasLoginApprovingDevice,
|
||||
obj.trustedDeviceOption.hasManageResetPasswordPermission
|
||||
obj.trustedDeviceOption.hasManageResetPasswordPermission,
|
||||
);
|
||||
}
|
||||
|
||||
if (obj.keyConnectorOption) {
|
||||
accountDecryptionOptions.keyConnectorOption = new KeyConnectorUserDecryptionOption(
|
||||
obj.keyConnectorOption.keyConnectorUrl
|
||||
obj.keyConnectorOption.keyConnectorUrl,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export default class Domain {
|
||||
domain: D,
|
||||
dataObj: any,
|
||||
map: any,
|
||||
notEncList: any[] = []
|
||||
notEncList: any[] = [],
|
||||
) {
|
||||
for (const prop in map) {
|
||||
// eslint-disable-next-line
|
||||
@@ -29,7 +29,7 @@ export default class Domain {
|
||||
domain: D,
|
||||
dataObj: any,
|
||||
map: any,
|
||||
notEncStringList: any[] = []
|
||||
notEncStringList: any[] = [],
|
||||
) {
|
||||
for (const prop in map) {
|
||||
// eslint-disable-next-line
|
||||
@@ -50,7 +50,7 @@ export default class Domain {
|
||||
viewModel: T,
|
||||
map: any,
|
||||
orgId: string,
|
||||
key: SymmetricCryptoKey = null
|
||||
key: SymmetricCryptoKey = null,
|
||||
): Promise<T> {
|
||||
const promises = [];
|
||||
const self: any = this;
|
||||
|
||||
@@ -28,7 +28,7 @@ export class EncArrayBuffer implements Encrypted {
|
||||
this.ivBytes = encBytes.slice(ENC_TYPE_LENGTH, ENC_TYPE_LENGTH + IV_LENGTH);
|
||||
this.macBytes = encBytes.slice(
|
||||
ENC_TYPE_LENGTH + IV_LENGTH,
|
||||
ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH
|
||||
ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH,
|
||||
);
|
||||
this.dataBytes = encBytes.slice(ENC_TYPE_LENGTH + IV_LENGTH + MAC_LENGTH);
|
||||
break;
|
||||
@@ -52,7 +52,7 @@ export class EncArrayBuffer implements Encrypted {
|
||||
|
||||
private throwDecryptionError() {
|
||||
throw new Error(
|
||||
"Error parsing encrypted ArrayBuffer: data is corrupted or has an invalid format."
|
||||
"Error parsing encrypted ArrayBuffer: data is corrupted or has an invalid format.",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ describe("EncString", () => {
|
||||
const cryptoService = mock<CryptoService>();
|
||||
cryptoService.hasUserKey.mockResolvedValue(true);
|
||||
cryptoService.getUserKeyWithLegacySupport.mockResolvedValue(
|
||||
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey
|
||||
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey,
|
||||
);
|
||||
|
||||
const encryptService = mock<EncryptService>();
|
||||
@@ -77,7 +77,7 @@ describe("EncString", () => {
|
||||
beforeEach(() => {
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -206,7 +206,7 @@ describe("EncString", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -215,7 +215,7 @@ describe("EncString", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
|
||||
const decrypted = await encString.decrypt(null);
|
||||
|
||||
@@ -18,7 +18,7 @@ export class EncString implements Encrypted {
|
||||
encryptedStringOrType: string | EncryptionType,
|
||||
data?: string,
|
||||
iv?: string,
|
||||
mac?: string
|
||||
mac?: string,
|
||||
) {
|
||||
if (data != null) {
|
||||
this.initFromData(encryptedStringOrType as EncryptionType, data, iv, mac);
|
||||
|
||||
@@ -21,7 +21,7 @@ describe("state", () => {
|
||||
userId: {},
|
||||
},
|
||||
},
|
||||
Account.fromJSON
|
||||
Account.fromJSON,
|
||||
);
|
||||
|
||||
expect(state.accounts["userId"]).toBeInstanceOf(Account);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { GlobalState } from "./global-state";
|
||||
|
||||
export class State<
|
||||
TGlobalState extends GlobalState = GlobalState,
|
||||
TAccount extends Account = Account
|
||||
TAccount extends Account = Account,
|
||||
> {
|
||||
accounts: { [userId: string]: TAccount } = {};
|
||||
globals: TGlobalState;
|
||||
@@ -20,7 +20,7 @@ export class State<
|
||||
// TODO, make Jsonify<State,TGlobalState,TAccount> work. It currently doesn't because Globals doesn't implement Jsonify.
|
||||
static fromJSON<TGlobalState extends GlobalState, TAccount extends Account>(
|
||||
obj: any,
|
||||
accountDeserializer: (json: Jsonify<TAccount>) => TAccount
|
||||
accountDeserializer: (json: Jsonify<TAccount>) => TAccount,
|
||||
): State<TGlobalState, TAccount> {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
@@ -33,7 +33,7 @@ export class State<
|
||||
|
||||
private static buildAccountMapFromJSON<TAccount extends Account>(
|
||||
jsonAccounts: { [userId: string]: Jsonify<TAccount> },
|
||||
accountDeserializer: (json: Jsonify<TAccount>) => TAccount
|
||||
accountDeserializer: (json: Jsonify<TAccount>) => TAccount,
|
||||
) {
|
||||
if (!jsonAccounts) {
|
||||
return {};
|
||||
|
||||
@@ -5,7 +5,10 @@ import { ConfigApiServiceAbstraction } from "../../abstractions/config/config-ap
|
||||
import { ServerConfigResponse } from "../../models/response/server-config.response";
|
||||
|
||||
export class ConfigApiService implements ConfigApiServiceAbstraction {
|
||||
constructor(private apiService: ApiService, private authService: AuthService) {}
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
|
||||
async get(): Promise<ServerConfigResponse> {
|
||||
const authed: boolean =
|
||||
|
||||
@@ -34,7 +34,7 @@ describe("ConfigService", () => {
|
||||
configApiService,
|
||||
authService,
|
||||
environmentService,
|
||||
logService
|
||||
logService,
|
||||
);
|
||||
configService.init();
|
||||
return configService;
|
||||
@@ -51,7 +51,7 @@ describe("ConfigService", () => {
|
||||
|
||||
serverResponseCount = 1;
|
||||
configApiService.get.mockImplementation(() =>
|
||||
Promise.resolve(serverConfigResponseFactory("server" + serverResponseCount++))
|
||||
Promise.resolve(serverConfigResponseFactory("server" + serverResponseCount++)),
|
||||
);
|
||||
|
||||
jest.useFakeTimers();
|
||||
@@ -124,7 +124,7 @@ describe("ConfigService", () => {
|
||||
|
||||
const oneHourInMs = 1000 * 3600;
|
||||
jest.advanceTimersByTime(oneHourInMs * hours + 1);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("when environment URLs change", (done) => {
|
||||
@@ -166,7 +166,7 @@ describe("ConfigService", () => {
|
||||
configService.serverConfig$.pipe(take(1)).subscribe(() => {
|
||||
try {
|
||||
expect(stateService.setServerConfig).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ gitHash: "server1" })
|
||||
expect.objectContaining({ gitHash: "server1" }),
|
||||
);
|
||||
done();
|
||||
} catch (e) {
|
||||
|
||||
@@ -35,7 +35,7 @@ export class ConfigService implements ConfigServiceAbstraction {
|
||||
protected refreshTimer$ = timer(ONE_HOUR_IN_MILLISECONDS, ONE_HOUR_IN_MILLISECONDS); // after 1 hour, then every hour
|
||||
|
||||
cloudRegion$ = this.serverConfig$.pipe(
|
||||
map((config) => config?.environment?.cloudRegion ?? Region.US)
|
||||
map((config) => config?.environment?.cloudRegion ?? Region.US),
|
||||
);
|
||||
|
||||
constructor(
|
||||
@@ -46,7 +46,7 @@ export class ConfigService implements ConfigServiceAbstraction {
|
||||
private logService: LogService,
|
||||
|
||||
// Used to avoid duplicate subscriptions, e.g. in browser between the background and popup
|
||||
private subscribe = true
|
||||
private subscribe = true,
|
||||
) {}
|
||||
|
||||
init() {
|
||||
@@ -61,18 +61,18 @@ export class ConfigService implements ConfigServiceAbstraction {
|
||||
// fall back to stored ServerConfig (if any)
|
||||
this.logService.error("Unable to fetch ServerConfig: " + (e as Error)?.message);
|
||||
return this.stateService.getServerConfig();
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// If you need to fetch a new config when an event occurs, add an observable that emits on that event here
|
||||
merge(
|
||||
this.refreshTimer$, // an overridable interval
|
||||
this.environmentService.urls, // when environment URLs change (including when app is started)
|
||||
this._forceFetchConfig // manual
|
||||
this._forceFetchConfig, // manual
|
||||
)
|
||||
.pipe(
|
||||
concatMap(() => latestServerConfig$),
|
||||
map((data) => (data == null ? null : new ServerConfig(data)))
|
||||
map((data) => (data == null ? null : new ServerConfig(data))),
|
||||
)
|
||||
.subscribe((config) => this._serverConfig.next(config));
|
||||
|
||||
@@ -87,7 +87,7 @@ export class ConfigService implements ConfigServiceAbstraction {
|
||||
}
|
||||
|
||||
return serverConfig.featureStates[key] as T;
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ export class ConfigService implements ConfigServiceAbstraction {
|
||||
}
|
||||
const serverVersion = new SemVer(serverConfig.version);
|
||||
return serverVersion.compare(minimumRequiredServerVersion) >= 0;
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export class ConsoleLogService implements LogServiceAbstraction {
|
||||
|
||||
constructor(
|
||||
protected isDev: boolean,
|
||||
protected filter: (level: LogLevelType) => boolean = null
|
||||
protected filter: (level: LogLevelType) => boolean = null,
|
||||
) {}
|
||||
|
||||
debug(message: string) {
|
||||
|
||||
@@ -2,7 +2,10 @@ import { CryptoService } from "../abstractions/crypto.service";
|
||||
import { EncryptService } from "../abstractions/encrypt.service";
|
||||
|
||||
export class ContainerService {
|
||||
constructor(private cryptoService: CryptoService, private encryptService: EncryptService) {}
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private encryptService: EncryptService,
|
||||
) {}
|
||||
|
||||
attachToGlobal(global: any) {
|
||||
if (!global.bitwardenContainerService) {
|
||||
|
||||
@@ -38,7 +38,7 @@ describe("cryptoService", () => {
|
||||
encryptService,
|
||||
platformUtilService,
|
||||
logService,
|
||||
stateService
|
||||
stateService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -165,7 +165,7 @@ describe("cryptoService", () => {
|
||||
cryptoSvcMakePinKey = jest.spyOn(cryptoService, "makePinKey");
|
||||
cryptoSvcMakePinKey.mockResolvedValue(new SymmetricCryptoKey(new Uint8Array(64)) as PinKey);
|
||||
encPin = new EncString(
|
||||
"2.jcow2vTUePO+CCyokcIfVw==|DTBNlJ5yVsV2Bsk3UU3H6Q==|YvFBff5gxWqM+UsFB6BKimKxhC32AtjF3IStpU1Ijwg="
|
||||
"2.jcow2vTUePO+CCyokcIfVw==|DTBNlJ5yVsV2Bsk3UU3H6Q==|YvFBff5gxWqM+UsFB6BKimKxhC32AtjF3IStpU1Ijwg=",
|
||||
);
|
||||
encryptService.encrypt.mockResolvedValue(encPin);
|
||||
});
|
||||
@@ -174,8 +174,8 @@ describe("cryptoService", () => {
|
||||
stateService.getProtectedPin.mockResolvedValue(protectedPin);
|
||||
stateService.getPinKeyEncryptedUserKey.mockResolvedValue(
|
||||
new EncString(
|
||||
"2.OdGNE3L23GaDZGvu9h2Brw==|/OAcNnrYwu0rjiv8+RUr3Tc+Ef8fV035Tm1rbTxfEuC+2LZtiCAoIvHIZCrM/V1PWnb/pHO2gh9+Koks04YhX8K29ED4FzjeYP8+YQD/dWo=|+12xTcIK/UVRsOyawYudPMHb6+lCHeR2Peq1pQhPm0A="
|
||||
)
|
||||
"2.OdGNE3L23GaDZGvu9h2Brw==|/OAcNnrYwu0rjiv8+RUr3Tc+Ef8fV035Tm1rbTxfEuC+2LZtiCAoIvHIZCrM/V1PWnb/pHO2gh9+Koks04YhX8K29ED4FzjeYP8+YQD/dWo=|+12xTcIK/UVRsOyawYudPMHb6+lCHeR2Peq1pQhPm0A=",
|
||||
),
|
||||
);
|
||||
|
||||
await cryptoService.setUserKey(mockUserKey, mockUserId);
|
||||
@@ -195,7 +195,7 @@ describe("cryptoService", () => {
|
||||
expect.any(EncString),
|
||||
{
|
||||
userId: mockUserId,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
protected encryptService: EncryptService,
|
||||
protected platformUtilService: PlatformUtilsService,
|
||||
protected logService: LogService,
|
||||
protected stateService: StateService
|
||||
protected stateService: StateService,
|
||||
) {}
|
||||
|
||||
async setUserKey(key: UserKey, userId?: string): Promise<void> {
|
||||
@@ -80,7 +80,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
async isLegacyUser(masterKey?: MasterKey, userId?: string): Promise<boolean> {
|
||||
return await this.validateUserKey(
|
||||
(masterKey ?? (await this.getMasterKey(userId))) as unknown as UserKey
|
||||
(masterKey ?? (await this.getMasterKey(userId))) as unknown as UserKey,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
password,
|
||||
await this.stateService.getEmail({ userId: userId }),
|
||||
await this.stateService.getKdfType({ userId: userId }),
|
||||
await this.stateService.getKdfConfig({ userId: userId })
|
||||
await this.stateService.getKdfConfig({ userId: userId }),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
password: string,
|
||||
email: string,
|
||||
kdf: KdfType,
|
||||
KdfConfig: KdfConfig
|
||||
KdfConfig: KdfConfig,
|
||||
): Promise<MasterKey> {
|
||||
return (await this.makeKey(password, email, kdf, KdfConfig)) as MasterKey;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
async encryptUserKeyWithMasterKey(
|
||||
masterKey: MasterKey,
|
||||
userKey?: UserKey
|
||||
userKey?: UserKey,
|
||||
): Promise<[UserKey, EncString]> {
|
||||
userKey ||= await this.getUserKey();
|
||||
return await this.buildProtectedSymmetricKey(masterKey, userKey.key);
|
||||
@@ -199,7 +199,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
async decryptUserKeyWithMasterKey(
|
||||
masterKey: MasterKey,
|
||||
userKey?: EncString,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
): Promise<UserKey> {
|
||||
masterKey ||= await this.getMasterKey(userId);
|
||||
if (masterKey == null) {
|
||||
@@ -243,7 +243,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
async hashMasterKey(
|
||||
password: string,
|
||||
key: MasterKey,
|
||||
hashPurpose?: HashPurpose
|
||||
hashPurpose?: HashPurpose,
|
||||
): Promise<string> {
|
||||
key ||= await this.getMasterKey();
|
||||
|
||||
@@ -274,7 +274,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
const localKeyHash = await this.hashMasterKey(
|
||||
masterPassword,
|
||||
masterKey,
|
||||
HashPurpose.LocalAuthorization
|
||||
HashPurpose.LocalAuthorization,
|
||||
);
|
||||
if (localKeyHash != null && storedPasswordHash === localKeyHash) {
|
||||
return true;
|
||||
@@ -284,7 +284,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
const serverKeyHash = await this.hashMasterKey(
|
||||
masterPassword,
|
||||
masterKey,
|
||||
HashPurpose.ServerAuthorization
|
||||
HashPurpose.ServerAuthorization,
|
||||
);
|
||||
if (serverKeyHash != null && storedPasswordHash === serverKeyHash) {
|
||||
await this.setMasterKeyHash(localKeyHash);
|
||||
@@ -297,7 +297,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
async setOrgKeys(
|
||||
orgs: ProfileOrganizationResponse[] = [],
|
||||
providerOrgs: ProfileProviderOrganizationResponse[] = []
|
||||
providerOrgs: ProfileProviderOrganizationResponse[] = [],
|
||||
): Promise<void> {
|
||||
const encOrgKeyData: { [orgId: string]: EncryptedOrganizationKeyData } = {};
|
||||
|
||||
@@ -368,7 +368,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
}
|
||||
|
||||
async makeDataEncKey<T extends OrgKey | UserKey>(
|
||||
key: T
|
||||
key: T,
|
||||
): Promise<[SymmetricCryptoKey, EncString]> {
|
||||
if (key == null) {
|
||||
throw new Error("No key provided");
|
||||
@@ -493,7 +493,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
const privateKey = await this.encryptService.decryptToBytes(
|
||||
new EncString(encPrivateKey),
|
||||
await this.getUserKeyWithLegacySupport()
|
||||
await this.getUserKeyWithLegacySupport(),
|
||||
);
|
||||
await this.stateService.setDecryptedPrivateKey(privateKey);
|
||||
return privateKey;
|
||||
@@ -511,7 +511,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
keyFingerprint,
|
||||
fingerprintMaterial,
|
||||
32,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
return this.hashPhrase(userFingerprint);
|
||||
}
|
||||
@@ -554,7 +554,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
pinProtectedUserKey?: EncString
|
||||
pinProtectedUserKey?: EncString,
|
||||
): Promise<UserKey> {
|
||||
pinProtectedUserKey ||= await this.stateService.getPinKeyEncryptedUserKey();
|
||||
pinProtectedUserKey ||= await this.stateService.getPinKeyEncryptedUserKeyEphemeral();
|
||||
@@ -572,7 +572,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
pinProtectedMasterKey?: EncString
|
||||
pinProtectedMasterKey?: EncString,
|
||||
): Promise<MasterKey> {
|
||||
if (!pinProtectedMasterKey) {
|
||||
const pinProtectedMasterKeyString = await this.stateService.getEncryptedPinProtected();
|
||||
@@ -592,7 +592,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
"bitwarden-send",
|
||||
"send",
|
||||
64,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
return new SymmetricCryptoKey(sendKey);
|
||||
}
|
||||
@@ -725,7 +725,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
const privateKey = await this.encryptService.decryptToBytes(
|
||||
new EncString(encPrivateKey),
|
||||
key
|
||||
key,
|
||||
);
|
||||
await this.cryptoFunctionService.rsaExtractPublicKey(privateKey);
|
||||
} catch (e) {
|
||||
@@ -794,13 +794,13 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
protected async storePinKey(key: UserKey, userId?: string) {
|
||||
const pin = await this.encryptService.decryptToUtf8(
|
||||
new EncString(await this.stateService.getProtectedPin({ userId: userId })),
|
||||
key
|
||||
key,
|
||||
);
|
||||
const pinKey = await this.makePinKey(
|
||||
pin,
|
||||
await this.stateService.getEmail({ userId: userId }),
|
||||
await this.stateService.getKdfType({ userId: userId }),
|
||||
await this.stateService.getKdfConfig({ userId: userId })
|
||||
await this.stateService.getKdfConfig({ userId: userId }),
|
||||
);
|
||||
const encPin = await this.encryptService.encrypt(key.key, pinKey);
|
||||
|
||||
@@ -830,7 +830,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
protected async getKeyFromStorage(
|
||||
keySuffix: KeySuffixOptions,
|
||||
userId?: string
|
||||
userId?: string,
|
||||
): Promise<UserKey> {
|
||||
if (keySuffix === KeySuffixOptions.Auto) {
|
||||
const userKey = await this.stateService.getUserKeyAutoUnlock({ userId: userId });
|
||||
@@ -877,7 +877,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
|
||||
private async buildProtectedSymmetricKey<T extends SymmetricCryptoKey>(
|
||||
encryptionKey: SymmetricCryptoKey,
|
||||
newSymKey: Uint8Array
|
||||
newSymKey: Uint8Array,
|
||||
): Promise<[T, EncString]> {
|
||||
let protectedSymKey: EncString = null;
|
||||
if (encryptionKey.key.byteLength === 32) {
|
||||
@@ -895,7 +895,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
password: string,
|
||||
salt: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig
|
||||
kdfConfig: KdfConfig,
|
||||
): Promise<SymmetricCryptoKey> {
|
||||
let key: Uint8Array = null;
|
||||
if (kdf == null || kdf === KdfType.PBKDF2_SHA256) {
|
||||
@@ -932,7 +932,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
saltHash,
|
||||
kdfConfig.iterations,
|
||||
kdfConfig.memory * 1024, // convert to KiB from MiB
|
||||
kdfConfig.parallelism
|
||||
kdfConfig.parallelism,
|
||||
);
|
||||
} else {
|
||||
throw new Error("Unknown Kdf.");
|
||||
@@ -973,7 +973,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
const userKey = await this.decryptUserKeyWithMasterKey(
|
||||
masterKey,
|
||||
new EncString(encryptedUserKey),
|
||||
userId
|
||||
userId,
|
||||
);
|
||||
// Migrate
|
||||
await this.stateService.setUserKeyAutoUnlock(userKey.keyB64, { userId: userId });
|
||||
@@ -988,7 +988,7 @@ export class CryptoService implements CryptoServiceAbstraction {
|
||||
email: string,
|
||||
kdf: KdfType,
|
||||
kdfConfig: KdfConfig,
|
||||
oldPinKey: EncString
|
||||
oldPinKey: EncString,
|
||||
): Promise<UserKey> {
|
||||
// Decrypt
|
||||
const masterKey = await this.decryptMasterKeyWithPin(pin, email, kdf, kdfConfig, oldPinKey);
|
||||
|
||||
@@ -15,7 +15,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
constructor(
|
||||
protected cryptoFunctionService: CryptoFunctionService,
|
||||
protected logService: LogService,
|
||||
protected logMacFailures: boolean
|
||||
protected logMacFailures: boolean,
|
||||
) {}
|
||||
|
||||
async encrypt(plainValue: string | Uint8Array, key: SymmetricCryptoKey): Promise<EncString> {
|
||||
@@ -84,13 +84,13 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
encString.data,
|
||||
encString.iv,
|
||||
encString.mac,
|
||||
key
|
||||
key,
|
||||
);
|
||||
if (fastParams.macKey != null && fastParams.mac != null) {
|
||||
const computedMac = await this.cryptoFunctionService.hmacFast(
|
||||
fastParams.macData,
|
||||
fastParams.macKey,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac);
|
||||
if (!macsEqual) {
|
||||
@@ -141,7 +141,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
encThing.dataBytes,
|
||||
encThing.ivBytes,
|
||||
key.encKey,
|
||||
"cbc"
|
||||
"cbc",
|
||||
);
|
||||
|
||||
return result ?? null;
|
||||
@@ -149,7 +149,7 @@ export class EncryptServiceImplementation implements EncryptService {
|
||||
|
||||
async decryptItems<T extends InitializerMetadata>(
|
||||
items: Decryptable<T>[],
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<T[]> {
|
||||
if (items == null || items.length < 1) {
|
||||
return [];
|
||||
|
||||
@@ -16,7 +16,7 @@ const classInitializers: Record<InitializerKey, (obj: any) => any> = {
|
||||
};
|
||||
|
||||
export function getClassInitializer<T extends InitializerMetadata>(
|
||||
className: InitializerKey
|
||||
className: InitializerKey,
|
||||
): (obj: Jsonify<T>) => T {
|
||||
return classInitializers[className];
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class MultithreadEncryptServiceImplementation extends EncryptServiceImple
|
||||
*/
|
||||
async decryptItems<T extends InitializerMetadata>(
|
||||
items: Decryptable<T>[],
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<T[]> {
|
||||
if (items == null || items.length < 1) {
|
||||
return [];
|
||||
@@ -36,8 +36,8 @@ export class MultithreadEncryptServiceImplementation extends EncryptServiceImple
|
||||
new URL(
|
||||
/* webpackChunkName: 'encrypt-worker' */
|
||||
"@bitwarden/common/platform/services/cryptography/encrypt.worker.ts",
|
||||
import.meta.url
|
||||
)
|
||||
import.meta.url,
|
||||
),
|
||||
);
|
||||
|
||||
this.restartTimeout();
|
||||
@@ -58,11 +58,11 @@ export class MultithreadEncryptServiceImplementation extends EncryptServiceImple
|
||||
items.map((jsonItem: Jsonify<T>) => {
|
||||
const initializer = getClassInitializer<T>(jsonItem.initializerKey);
|
||||
return initializer(jsonItem);
|
||||
})
|
||||
}),
|
||||
),
|
||||
takeUntil(this.clear$),
|
||||
defaultIfEmpty([])
|
||||
)
|
||||
defaultIfEmpty([]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("EncryptService", () => {
|
||||
|
||||
it("throws if no key is provided", () => {
|
||||
return expect(encryptService.encryptToBytes(plainValue, null)).rejects.toThrow(
|
||||
"No encryption key"
|
||||
"No encryption key",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -57,7 +57,7 @@ describe("EncryptService", () => {
|
||||
expect(actual.macBytes).toEqualBuffer(mac);
|
||||
expect(actual.dataBytes).toEqualBuffer(encryptedData);
|
||||
expect(actual.buffer.byteLength).toEqual(
|
||||
1 + iv.byteLength + mac.byteLength + encryptedData.byteLength
|
||||
1 + iv.byteLength + mac.byteLength + encryptedData.byteLength,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -93,13 +93,13 @@ describe("EncryptService", () => {
|
||||
|
||||
it("throws if no key is provided", () => {
|
||||
return expect(encryptService.decryptToBytes(encBuffer, null)).rejects.toThrow(
|
||||
"No encryption key"
|
||||
"No encryption key",
|
||||
);
|
||||
});
|
||||
|
||||
it("throws if no encrypted value is provided", () => {
|
||||
return expect(encryptService.decryptToBytes(null, key)).rejects.toThrow(
|
||||
"Nothing provided for decryption"
|
||||
"Nothing provided for decryption",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -116,7 +116,7 @@ describe("EncryptService", () => {
|
||||
expect.toEqualBuffer(encBuffer.dataBytes),
|
||||
expect.toEqualBuffer(encBuffer.ivBytes),
|
||||
expect.toEqualBuffer(key.encKey),
|
||||
"cbc"
|
||||
"cbc",
|
||||
);
|
||||
|
||||
expect(actual).toEqualBuffer(decryptedBytes);
|
||||
@@ -124,7 +124,7 @@ describe("EncryptService", () => {
|
||||
|
||||
it("compares macs using CryptoFunctionService", async () => {
|
||||
const expectedMacData = new Uint8Array(
|
||||
encBuffer.ivBytes.byteLength + encBuffer.dataBytes.byteLength
|
||||
encBuffer.ivBytes.byteLength + encBuffer.dataBytes.byteLength,
|
||||
);
|
||||
expectedMacData.set(new Uint8Array(encBuffer.ivBytes));
|
||||
expectedMacData.set(new Uint8Array(encBuffer.dataBytes), encBuffer.ivBytes.byteLength);
|
||||
@@ -134,12 +134,12 @@ describe("EncryptService", () => {
|
||||
expect(cryptoFunctionService.hmac).toBeCalledWith(
|
||||
expect.toEqualBuffer(expectedMacData),
|
||||
key.macKey,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
|
||||
expect(cryptoFunctionService.compare).toBeCalledWith(
|
||||
expect.toEqualBuffer(encBuffer.macBytes),
|
||||
expect.toEqualBuffer(computedMac)
|
||||
expect.toEqualBuffer(computedMac),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
return;
|
||||
}
|
||||
await this.setUrlsFromStorage();
|
||||
})
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
@@ -296,7 +296,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction {
|
||||
default: {
|
||||
// Environment is self-hosted
|
||||
const envUrls = await this.stateService.getEnvironmentUrls(
|
||||
userId ? { userId: userId } : null
|
||||
userId ? { userId: userId } : null,
|
||||
);
|
||||
return Utils.getHost(envUrls.webVault || envUrls.base);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export class AzureFileUploadService {
|
||||
private async azureUploadBlocks(
|
||||
url: string,
|
||||
data: EncArrayBuffer,
|
||||
renewalCallback: () => Promise<string>
|
||||
renewalCallback: () => Promise<string>,
|
||||
) {
|
||||
const baseUrl = Utils.getUrl(url);
|
||||
const blockSize = this.getMaxBlockSize(baseUrl.searchParams.get("sv"));
|
||||
@@ -50,7 +50,7 @@ export class AzureFileUploadService {
|
||||
|
||||
if (numBlocks > MAX_BLOCKS_PER_BLOB) {
|
||||
throw new Error(
|
||||
`Cannot upload file, exceeds maximum size of ${blockSize * MAX_BLOCKS_PER_BLOB}`
|
||||
`Cannot upload file, exceeds maximum size of ${blockSize * MAX_BLOCKS_PER_BLOB}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ export class AzureFileUploadService {
|
||||
|
||||
private async renewUrlIfNecessary(
|
||||
url: string,
|
||||
renewalCallback: () => Promise<string>
|
||||
renewalCallback: () => Promise<string>,
|
||||
): Promise<string> {
|
||||
const urlObject = Utils.getUrl(url);
|
||||
const expiry = new Date(urlObject.searchParams.get("se") ?? "");
|
||||
@@ -183,10 +183,10 @@ class Version {
|
||||
return a.year !== b.year
|
||||
? a.year - b.year
|
||||
: a.month !== b.month
|
||||
? a.month - b.month
|
||||
: a.day !== b.day
|
||||
? a.day - b.day
|
||||
: 0;
|
||||
? a.month - b.month
|
||||
: a.day !== b.day
|
||||
? a.day - b.day
|
||||
: 0;
|
||||
}
|
||||
year = 0;
|
||||
month = 0;
|
||||
|
||||
@@ -5,7 +5,7 @@ export class BitwardenFileUploadService {
|
||||
async upload(
|
||||
encryptedFileName: string,
|
||||
encryptedFileData: EncArrayBuffer,
|
||||
apiCall: (fd: FormData) => Promise<any>
|
||||
apiCall: (fd: FormData) => Promise<any>,
|
||||
) {
|
||||
const fd = new FormData();
|
||||
try {
|
||||
@@ -19,7 +19,7 @@ export class BitwardenFileUploadService {
|
||||
{
|
||||
filepath: encryptedFileName,
|
||||
contentType: "application/octet-stream",
|
||||
} as any
|
||||
} as any,
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
|
||||
@@ -23,7 +23,7 @@ export class FileUploadService implements FileUploadServiceAbstraction {
|
||||
uploadData: { url: string; fileUploadType: FileUploadType },
|
||||
fileName: EncString,
|
||||
encryptedFileData: EncArrayBuffer,
|
||||
fileUploadMethods: FileUploadApiMethods
|
||||
fileUploadMethods: FileUploadApiMethods,
|
||||
) {
|
||||
try {
|
||||
switch (uploadData.fileUploadType) {
|
||||
@@ -31,14 +31,14 @@ export class FileUploadService implements FileUploadServiceAbstraction {
|
||||
await this.bitwardenFileUploadService.upload(
|
||||
fileName.encryptedString,
|
||||
encryptedFileData,
|
||||
(fd) => fileUploadMethods.postDirect(fd)
|
||||
(fd) => fileUploadMethods.postDirect(fd),
|
||||
);
|
||||
break;
|
||||
case FileUploadType.Azure: {
|
||||
await this.azureFileUploadService.upload(
|
||||
uploadData.url,
|
||||
encryptedFileData,
|
||||
fileUploadMethods.renewFileUploadUrl
|
||||
fileUploadMethods.renewFileUploadUrl,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export class I18nService extends TranslationService implements I18nServiceAbstra
|
||||
constructor(
|
||||
protected systemLanguage: string,
|
||||
protected localesDirectory: string,
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>,
|
||||
) {
|
||||
super(systemLanguage, localesDirectory, getLocalesJson);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export class NoopNotificationsService implements NotificationsServiceAbstraction
|
||||
|
||||
init(): Promise<void> {
|
||||
this.logService.info(
|
||||
"Initializing no-op notification service, no push notifications will be received"
|
||||
"Initializing no-op notification service, no push notifications will be received",
|
||||
);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@ export class SystemService implements SystemServiceAbstraction {
|
||||
private messagingService: MessagingService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private reloadCallback: () => Promise<void> = null,
|
||||
private stateService: StateService
|
||||
private stateService: StateService,
|
||||
) {}
|
||||
|
||||
async startProcessReload(authService: AuthService): Promise<void> {
|
||||
|
||||
@@ -73,7 +73,7 @@ export abstract class TranslationService implements TranslationServiceAbstractio
|
||||
constructor(
|
||||
protected systemLanguage: string,
|
||||
protected localesDirectory: string,
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>,
|
||||
) {
|
||||
this.systemLanguage = systemLanguage.replace("_", "-");
|
||||
}
|
||||
@@ -171,7 +171,7 @@ export abstract class TranslationService implements TranslationServiceAbstractio
|
||||
}
|
||||
messagesObj[prop] = messagesObj[prop].replace(
|
||||
new RegExp(replaceToken, "g"),
|
||||
replaceContent
|
||||
replaceContent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ValidationService as ValidationServiceAbstraction } from "../abstractio
|
||||
export class ValidationService implements ValidationServiceAbstraction {
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
) {}
|
||||
|
||||
showError(data: any): string[] {
|
||||
|
||||
@@ -85,7 +85,7 @@ describe("WebCrypto Function Service", () => {
|
||||
prk32Byte,
|
||||
64,
|
||||
"BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD9BV+" +
|
||||
"/queOZenPNkDhmlVyL2WZ3OSU5+7ISNF5NhNfvZA=="
|
||||
"/queOZenPNkDhmlVyL2WZ3OSU5+7ISNF5NhNfvZA==",
|
||||
);
|
||||
testHkdfExpand("sha512", prk64Byte, 32, "uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlk=");
|
||||
testHkdfExpand(
|
||||
@@ -93,7 +93,7 @@ describe("WebCrypto Function Service", () => {
|
||||
prk64Byte,
|
||||
64,
|
||||
"uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlkY5Pv0sB+" +
|
||||
"MqvaopmkC6sD/j89zDwTV9Ib2fpucUydO8w=="
|
||||
"MqvaopmkC6sD/j89zDwTV9Ib2fpucUydO8w==",
|
||||
);
|
||||
|
||||
it("should fail with prk too small", async () => {
|
||||
@@ -102,7 +102,7 @@ describe("WebCrypto Function Service", () => {
|
||||
Utils.fromB64ToArray(prk16Byte),
|
||||
"info",
|
||||
32,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
await expect(f).rejects.toEqual(new Error("prk is too small."));
|
||||
});
|
||||
@@ -113,7 +113,7 @@ describe("WebCrypto Function Service", () => {
|
||||
Utils.fromB64ToArray(prk32Byte),
|
||||
"info",
|
||||
8161,
|
||||
"sha256"
|
||||
"sha256",
|
||||
);
|
||||
await expect(f).rejects.toEqual(new Error("outputByteSize is too large."));
|
||||
});
|
||||
@@ -337,7 +337,7 @@ describe("WebCrypto Function Service", () => {
|
||||
"A1/p8BQzN9UrbdYxUY2Va5+kPLyfZXF9JsZrjeEXcaclsnHurdxVAJcnbEqYMP3UXV" +
|
||||
"4YAS/mpf+Rxe6/X0WS1boQdA0MAHSgx95hIlAraZYpiMLLiJRKeo2u8YivCdTM9V5vuAEJwf9Tof/qFsFci3sApdbATkorCT" +
|
||||
"zFOIEPF2S1zgperEP23M01mr4dWVdYN18B32YF67xdJHMbFhp5dkQwv9CmscoWq7OE5HIfOb+JAh7BEZb+CmKhM3yWJvoR/D" +
|
||||
"/5jcercUtK2o+XrzNrL4UQ7yLZcFz6Bfwb/j6ICYvqd/YJwXNE6dwlL57OfwJyCdw2rRYf0/qI00t9u8Iitw=="
|
||||
"/5jcercUtK2o+XrzNrL4UQ7yLZcFz6Bfwb/j6ICYvqd/YJwXNE6dwlL57OfwJyCdw2rRYf0/qI00t9u8Iitw==",
|
||||
);
|
||||
const decValue = await cryptoFunctionService.rsaDecrypt(data, privKey, "sha1");
|
||||
expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!");
|
||||
@@ -373,7 +373,7 @@ describe("WebCrypto Function Service", () => {
|
||||
const randomData = await cryptoFunctionService.randomBytes(16);
|
||||
const randomData2 = await cryptoFunctionService.randomBytes(16);
|
||||
expect(
|
||||
randomData.byteLength === randomData2.byteLength && randomData !== randomData2
|
||||
randomData.byteLength === randomData2.byteLength && randomData !== randomData2,
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -397,7 +397,7 @@ function testPbkdf2(
|
||||
algorithm: "sha256" | "sha512",
|
||||
regularKey: string,
|
||||
utf8Key: string,
|
||||
unicodeKey: string
|
||||
unicodeKey: string,
|
||||
) {
|
||||
const regularEmail = "user@example.com";
|
||||
const utf8Email = "üser@example.com";
|
||||
@@ -430,7 +430,7 @@ function testPbkdf2(
|
||||
Utils.fromUtf8ToArray(regularPassword),
|
||||
Utils.fromUtf8ToArray(regularEmail),
|
||||
algorithm,
|
||||
5000
|
||||
5000,
|
||||
);
|
||||
expect(Utils.fromBufferToB64(key)).toBe(regularKey);
|
||||
});
|
||||
@@ -440,7 +440,7 @@ function testHkdf(
|
||||
algorithm: "sha256" | "sha512",
|
||||
regularKey: string,
|
||||
utf8Key: string,
|
||||
unicodeKey: string
|
||||
unicodeKey: string,
|
||||
) {
|
||||
const ikm = Utils.fromB64ToArray("criAmKtfzxanbgea5/kelQ==");
|
||||
|
||||
@@ -477,7 +477,7 @@ function testHkdf(
|
||||
Utils.fromUtf8ToArray(regularSalt),
|
||||
Utils.fromUtf8ToArray(regularInfo),
|
||||
32,
|
||||
algorithm
|
||||
algorithm,
|
||||
);
|
||||
expect(Utils.fromBufferToB64(key)).toBe(regularKey);
|
||||
});
|
||||
@@ -487,7 +487,7 @@ function testHkdfExpand(
|
||||
algorithm: "sha256" | "sha512",
|
||||
b64prk: string,
|
||||
outputByteSize: number,
|
||||
b64ExpectedOkm: string
|
||||
b64ExpectedOkm: string,
|
||||
) {
|
||||
const info = "info";
|
||||
|
||||
@@ -497,7 +497,7 @@ function testHkdfExpand(
|
||||
Utils.fromB64ToArray(b64prk),
|
||||
info,
|
||||
outputByteSize,
|
||||
algorithm
|
||||
algorithm,
|
||||
);
|
||||
expect(Utils.fromBufferToB64(okm)).toBe(b64ExpectedOkm);
|
||||
});
|
||||
@@ -507,7 +507,7 @@ function testHash(
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5",
|
||||
regularHash: string,
|
||||
utf8Hash: string,
|
||||
unicodeHash: string
|
||||
unicodeHash: string,
|
||||
) {
|
||||
const regularValue = "HashMe!!";
|
||||
const utf8Value = "HǻshMe!!";
|
||||
@@ -544,7 +544,7 @@ function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string) {
|
||||
const computedMac = await cryptoFunctionService.hmac(
|
||||
Utils.fromUtf8ToArray("SignMe!!"),
|
||||
Utils.fromUtf8ToArray("secretkey"),
|
||||
algorithm
|
||||
algorithm,
|
||||
);
|
||||
expect(Utils.fromBufferToHex(computedMac)).toBe(mac);
|
||||
});
|
||||
@@ -558,7 +558,7 @@ function testHmacFast(algorithm: "sha1" | "sha256" | "sha512", mac: string) {
|
||||
const computedMac = await cryptoFunctionService.hmacFast(
|
||||
dataByteString,
|
||||
keyByteString,
|
||||
algorithm
|
||||
algorithm,
|
||||
);
|
||||
expect(Utils.fromBufferToHex(Utils.fromByteStringToArray(computedMac))).toBe(mac);
|
||||
});
|
||||
@@ -570,13 +570,13 @@ function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) {
|
||||
async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const keyPair = (await cryptoFunctionService.rsaGenerateKeyPair(length)).map(
|
||||
(k) => new Uint8Array(k)
|
||||
(k) => new Uint8Array(k),
|
||||
);
|
||||
expect(keyPair[0] == null || keyPair[1] == null).toBe(false);
|
||||
const publicKey = await cryptoFunctionService.rsaExtractPublicKey(keyPair[1]);
|
||||
expect(Utils.fromBufferToB64(keyPair[0])).toBe(Utils.fromBufferToB64(publicKey));
|
||||
},
|
||||
30000
|
||||
30000,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
password: string | Uint8Array,
|
||||
salt: string | Uint8Array,
|
||||
algorithm: "sha256" | "sha512",
|
||||
iterations: number
|
||||
iterations: number,
|
||||
): Promise<Uint8Array> {
|
||||
const wcLen = algorithm === "sha256" ? 256 : 512;
|
||||
const passwordBuf = this.toBuf(password);
|
||||
@@ -41,7 +41,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
passwordBuf,
|
||||
{ name: "PBKDF2" } as any,
|
||||
false,
|
||||
["deriveBits"]
|
||||
["deriveBits"],
|
||||
);
|
||||
const buffer = await this.subtle.deriveBits(pbkdf2Params as any, impKey, wcLen);
|
||||
return new Uint8Array(buffer);
|
||||
@@ -52,7 +52,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
salt: string | Uint8Array,
|
||||
iterations: number,
|
||||
memory: number,
|
||||
parallelism: number
|
||||
parallelism: number,
|
||||
): Promise<Uint8Array> {
|
||||
if (!this.wasmSupported) {
|
||||
throw "Webassembly support is required for the Argon2 KDF feature.";
|
||||
@@ -79,7 +79,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
salt: string | Uint8Array,
|
||||
info: string | Uint8Array,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
algorithm: "sha256" | "sha512",
|
||||
): Promise<Uint8Array> {
|
||||
const saltBuf = this.toBuf(salt);
|
||||
const infoBuf = this.toBuf(info);
|
||||
@@ -103,7 +103,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
prk: Uint8Array,
|
||||
info: string | Uint8Array,
|
||||
outputByteSize: number,
|
||||
algorithm: "sha256" | "sha512"
|
||||
algorithm: "sha256" | "sha512",
|
||||
): Promise<Uint8Array> {
|
||||
const hashLen = algorithm === "sha256" ? 32 : 64;
|
||||
if (outputByteSize > 255 * hashLen) {
|
||||
@@ -136,7 +136,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
|
||||
async hash(
|
||||
value: string | Uint8Array,
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5"
|
||||
algorithm: "sha1" | "sha256" | "sha512" | "md5",
|
||||
): Promise<Uint8Array> {
|
||||
if (algorithm === "md5") {
|
||||
const md = algorithm === "md5" ? forge.md.md5.create() : forge.md.sha1.create();
|
||||
@@ -148,7 +148,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
const valueBuf = this.toBuf(value);
|
||||
const buffer = await this.subtle.digest(
|
||||
{ name: this.toWebCryptoAlgorithm(algorithm) },
|
||||
valueBuf
|
||||
valueBuf,
|
||||
);
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
async hmac(
|
||||
value: Uint8Array,
|
||||
key: Uint8Array,
|
||||
algorithm: "sha1" | "sha256" | "sha512"
|
||||
algorithm: "sha1" | "sha256" | "sha512",
|
||||
): Promise<Uint8Array> {
|
||||
const signingAlgorithm = {
|
||||
name: "HMAC",
|
||||
@@ -238,7 +238,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
data: string,
|
||||
iv: string,
|
||||
mac: string,
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): DecryptParameters<string> {
|
||||
const p = new DecryptParameters<string>();
|
||||
if (key.meta != null) {
|
||||
@@ -276,7 +276,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
aesDecryptFast(parameters: DecryptParameters<string>, mode: "cbc" | "ecb"): Promise<string> {
|
||||
const decipher = (forge as any).cipher.createDecipher(
|
||||
this.toWebCryptoAesMode(mode),
|
||||
parameters.encKey
|
||||
parameters.encKey,
|
||||
);
|
||||
const options = {} as any;
|
||||
if (mode === "cbc") {
|
||||
@@ -294,7 +294,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
data: Uint8Array,
|
||||
iv: Uint8Array,
|
||||
key: Uint8Array,
|
||||
mode: "cbc" | "ecb"
|
||||
mode: "cbc" | "ecb",
|
||||
): Promise<Uint8Array> {
|
||||
if (mode === "ecb") {
|
||||
// Web crypto does not support AES-ECB mode, so we need to do this in forge.
|
||||
@@ -314,7 +314,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
async rsaEncrypt(
|
||||
data: Uint8Array,
|
||||
publicKey: Uint8Array,
|
||||
algorithm: "sha1" | "sha256"
|
||||
algorithm: "sha1" | "sha256",
|
||||
): Promise<Uint8Array> {
|
||||
// Note: Edge browser requires that we specify name and hash for both key import and decrypt.
|
||||
// We cannot use the proper types here.
|
||||
@@ -330,7 +330,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
async rsaDecrypt(
|
||||
data: Uint8Array,
|
||||
privateKey: Uint8Array,
|
||||
algorithm: "sha1" | "sha256"
|
||||
algorithm: "sha1" | "sha256",
|
||||
): Promise<Uint8Array> {
|
||||
// Note: Edge browser requires that we specify name and hash for both key import and decrypt.
|
||||
// We cannot use the proper types here.
|
||||
@@ -440,7 +440,7 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
try {
|
||||
if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
|
||||
const module = new WebAssembly.Module(
|
||||
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
|
||||
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00),
|
||||
);
|
||||
if (module instanceof WebAssembly.Module) {
|
||||
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
|
||||
@@ -18,7 +18,7 @@ export interface GlobalState<T> {
|
||||
*/
|
||||
update: <TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
options?: StateUpdateOptions<T, TCombine>
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<T>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,14 +10,14 @@ export class DefaultDerivedUserState<TFrom, TTo> implements DerivedUserState<TTo
|
||||
constructor(
|
||||
private converter: Converter<TFrom, TTo>,
|
||||
private encryptService: EncryptService,
|
||||
private userState: UserState<TFrom>
|
||||
private userState: UserState<TFrom>,
|
||||
) {
|
||||
this.state$ = userState.state$.pipe(
|
||||
switchMap(async (from) => {
|
||||
// TODO: How do I get the key?
|
||||
const convertedData = await this.converter(from, new DeriveContext(null, encryptService));
|
||||
return convertedData;
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export class DefaultGlobalStateProvider implements GlobalStateProvider {
|
||||
|
||||
constructor(
|
||||
private memoryStorage: AbstractMemoryStorageService & ObservableStorageService,
|
||||
private diskStorage: AbstractStorageService & ObservableStorageService
|
||||
private diskStorage: AbstractStorageService & ObservableStorageService,
|
||||
) {}
|
||||
|
||||
get<T>(keyDefinition: KeyDefinition<T>): GlobalState<T> {
|
||||
@@ -29,7 +29,7 @@ export class DefaultGlobalStateProvider implements GlobalStateProvider {
|
||||
|
||||
const newGlobalState = new DefaultGlobalState<T>(
|
||||
keyDefinition,
|
||||
this.getLocation(keyDefinition.stateDefinition.storageLocation)
|
||||
this.getLocation(keyDefinition.stateDefinition.storageLocation),
|
||||
);
|
||||
|
||||
this.globalStateCache[cacheKey] = newGlobalState;
|
||||
|
||||
@@ -120,7 +120,7 @@ describe("DefaultGlobalState", () => {
|
||||
},
|
||||
{
|
||||
combineLatestWith: of(combinedDependencies),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await awaitAsync();
|
||||
@@ -140,7 +140,7 @@ describe("DefaultGlobalState", () => {
|
||||
},
|
||||
{
|
||||
shouldUpdate: () => false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
expect(diskStorageService.mock.save).not.toHaveBeenCalled();
|
||||
|
||||
@@ -32,7 +32,7 @@ export class DefaultGlobalState<T> implements GlobalState<T> {
|
||||
|
||||
constructor(
|
||||
private keyDefinition: KeyDefinition<T>,
|
||||
private chosenLocation: AbstractStorageService & ObservableStorageService
|
||||
private chosenLocation: AbstractStorageService & ObservableStorageService,
|
||||
) {
|
||||
this.storageKey = globalKeyBuilder(this.keyDefinition);
|
||||
|
||||
@@ -45,10 +45,10 @@ export class DefaultGlobalState<T> implements GlobalState<T> {
|
||||
return await getStoredValue(
|
||||
this.storageKey,
|
||||
this.chosenLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
}),
|
||||
shareReplay({ bufferSize: 1, refCount: false })
|
||||
shareReplay({ bufferSize: 1, refCount: false }),
|
||||
);
|
||||
|
||||
this.state$ = defer(() => {
|
||||
@@ -65,17 +65,17 @@ export class DefaultGlobalState<T> implements GlobalState<T> {
|
||||
complete: () => {
|
||||
storageUpdateSubscription.unsubscribe();
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
}).pipe(
|
||||
shareReplay({ refCount: false, bufferSize: 1 }),
|
||||
filter<T>((i) => i != FAKE_DEFAULT)
|
||||
filter<T>((i) => i != FAKE_DEFAULT),
|
||||
);
|
||||
}
|
||||
|
||||
async update<TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
options: StateUpdateOptions<T, TCombine> = {}
|
||||
options: StateUpdateOptions<T, TCombine> = {},
|
||||
): Promise<T> {
|
||||
options = populateOptionsWithDefault(options);
|
||||
const currentState = await this.getGuaranteedState();
|
||||
@@ -102,7 +102,7 @@ export class DefaultGlobalState<T> implements GlobalState<T> {
|
||||
return await getStoredValue(
|
||||
this.storageKey,
|
||||
this.chosenLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export class DefaultUserStateProvider implements UserStateProvider {
|
||||
protected accountService: AccountService,
|
||||
protected encryptService: EncryptService,
|
||||
protected memoryStorage: AbstractMemoryStorageService & ObservableStorageService,
|
||||
protected diskStorage: AbstractStorageService & ObservableStorageService
|
||||
protected diskStorage: AbstractStorageService & ObservableStorageService,
|
||||
) {}
|
||||
|
||||
get<T>(keyDefinition: KeyDefinition<T>): UserState<T> {
|
||||
@@ -41,7 +41,7 @@ export class DefaultUserStateProvider implements UserStateProvider {
|
||||
keyDefinition,
|
||||
this.accountService,
|
||||
this.encryptService,
|
||||
this.getLocation(keyDefinition.stateDefinition.storageLocation)
|
||||
this.getLocation(keyDefinition.stateDefinition.storageLocation),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ describe("DefaultUserState", () => {
|
||||
testKeyDefinition,
|
||||
accountService,
|
||||
null, // Not testing anything with encrypt service
|
||||
diskStorageService
|
||||
diskStorageService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -111,17 +111,17 @@ describe("DefaultUserState", () => {
|
||||
expect(diskStorageService.mock.get).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
"user_00000000-0000-1000-a000-000000000001_fake_fake",
|
||||
any()
|
||||
any(),
|
||||
);
|
||||
expect(diskStorageService.mock.get).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
"user_00000000-0000-1000-a000-000000000001_fake_fake",
|
||||
any()
|
||||
any(),
|
||||
);
|
||||
expect(diskStorageService.mock.get).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
"user_00000000-0000-1000-a000-000000000002_fake_fake",
|
||||
any()
|
||||
any(),
|
||||
);
|
||||
|
||||
// Should only have saved data for the first user
|
||||
@@ -129,7 +129,7 @@ describe("DefaultUserState", () => {
|
||||
expect(diskStorageService.mock.save).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
"user_00000000-0000-1000-a000-000000000001_fake_fake",
|
||||
any()
|
||||
any(),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -275,7 +275,7 @@ describe("DefaultUserState", () => {
|
||||
},
|
||||
{
|
||||
combineLatestWith: of(combinedDependencies),
|
||||
}
|
||||
},
|
||||
);
|
||||
await awaitAsync();
|
||||
|
||||
@@ -295,7 +295,7 @@ describe("DefaultUserState", () => {
|
||||
},
|
||||
{
|
||||
shouldUpdate: () => false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await awaitAsync();
|
||||
|
||||
@@ -43,15 +43,15 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
protected keyDefinition: KeyDefinition<T>,
|
||||
private accountService: AccountService,
|
||||
private encryptService: EncryptService,
|
||||
private chosenStorageLocation: AbstractStorageService & ObservableStorageService
|
||||
private chosenStorageLocation: AbstractStorageService & ObservableStorageService,
|
||||
) {
|
||||
this.formattedKey$ = this.accountService.activeAccount$.pipe(
|
||||
map((account) =>
|
||||
account != null && account.id != null
|
||||
? userKeyBuilder(account.id, this.keyDefinition)
|
||||
: null
|
||||
: null,
|
||||
),
|
||||
shareReplay({ bufferSize: 1, refCount: false })
|
||||
shareReplay({ bufferSize: 1, refCount: false }),
|
||||
);
|
||||
|
||||
const activeAccountData$ = this.formattedKey$.pipe(
|
||||
@@ -62,11 +62,11 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
return await getStoredValue(
|
||||
key,
|
||||
this.chosenStorageLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
}),
|
||||
// Share the execution
|
||||
shareReplay({ refCount: false, bufferSize: 1 })
|
||||
shareReplay({ refCount: false, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
const storageUpdates$ = this.chosenStorageLocation.updates$.pipe(
|
||||
@@ -79,10 +79,10 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
const data = await getStoredValue(
|
||||
key,
|
||||
this.chosenStorageLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
return data;
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// Whomever subscribes to this data, should be notified of updated data
|
||||
@@ -101,7 +101,7 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
accountChangeSubscription.unsubscribe();
|
||||
storageUpdateSubscription.unsubscribe();
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
})
|
||||
// I fake the generic here because I am filtering out the other union type
|
||||
@@ -111,7 +111,7 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
|
||||
async update<TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
options: StateUpdateOptions<T, TCombine> = {}
|
||||
options: StateUpdateOptions<T, TCombine> = {},
|
||||
): Promise<T> {
|
||||
options = populateOptionsWithDefault(options);
|
||||
const key = await this.createKey();
|
||||
@@ -133,7 +133,7 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
async updateFor<TCombine>(
|
||||
userId: UserId,
|
||||
configureState: (state: T, dependencies: TCombine) => T,
|
||||
options: StateUpdateOptions<T, TCombine> = {}
|
||||
options: StateUpdateOptions<T, TCombine> = {},
|
||||
): Promise<T> {
|
||||
if (userId == null) {
|
||||
throw new Error("Attempting to update user state, but no userId has been supplied.");
|
||||
@@ -144,7 +144,7 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
const currentState = await getStoredValue(
|
||||
key,
|
||||
this.chosenStorageLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
const combinedDependencies =
|
||||
options.combineLatestWith != null
|
||||
@@ -187,7 +187,7 @@ export class DefaultUserState<T> implements UserState<T> {
|
||||
const value = await getStoredValue(
|
||||
key,
|
||||
this.chosenStorageLocation,
|
||||
this.keyDefinition.deserializer
|
||||
this.keyDefinition.deserializer,
|
||||
);
|
||||
this.stateSubject.next(value);
|
||||
return value;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AbstractStorageService } from "../../abstractions/storage.service";
|
||||
export async function getStoredValue<T>(
|
||||
key: string,
|
||||
storage: AbstractStorageService,
|
||||
deserializer: (jsonValue: Jsonify<T>) => T
|
||||
deserializer: (jsonValue: Jsonify<T>) => T,
|
||||
) {
|
||||
if (storage.valuesRequireDeserialization) {
|
||||
const jsonValue = await storage.get<Jsonify<T>>(key);
|
||||
|
||||
@@ -47,11 +47,11 @@ describe("KeyDefinition", () => {
|
||||
"fake",
|
||||
{
|
||||
deserializer: (value) => !value,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const fancyRecord = recordDefinition.deserializer(
|
||||
JSON.parse(`{ "myKey": false, "mySecondKey": true }`)
|
||||
JSON.parse(`{ "myKey": false, "mySecondKey": true }`),
|
||||
);
|
||||
|
||||
expect(fancyRecord).toBeTruthy();
|
||||
|
||||
@@ -39,11 +39,11 @@ export class KeyDefinition<T> {
|
||||
constructor(
|
||||
readonly stateDefinition: StateDefinition,
|
||||
readonly key: string,
|
||||
private readonly options: KeyDefinitionOptions<T>
|
||||
private readonly options: KeyDefinitionOptions<T>,
|
||||
) {
|
||||
if (options.deserializer == null) {
|
||||
throw new Error(
|
||||
`'deserializer' is a required property on key ${stateDefinition.name} > ${key}`
|
||||
`'deserializer' is a required property on key ${stateDefinition.name} > ${key}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ export class KeyDefinition<T> {
|
||||
stateDefinition: StateDefinition,
|
||||
key: string,
|
||||
// We have them provide options for the element of the array, depending on future options we add, this could get a little weird.
|
||||
options: KeyDefinitionOptions<T> // The array helper forces an initialValue of an empty array
|
||||
options: KeyDefinitionOptions<T>, // The array helper forces an initialValue of an empty array
|
||||
) {
|
||||
return new KeyDefinition<T[]>(stateDefinition, key, {
|
||||
...options,
|
||||
@@ -107,7 +107,7 @@ export class KeyDefinition<T> {
|
||||
stateDefinition: StateDefinition,
|
||||
key: string,
|
||||
// We have them provide options for the value of the record, depending on future options we add, this could get a little weird.
|
||||
options: KeyDefinitionOptions<T> // The array helper forces an initialValue of an empty record
|
||||
options: KeyDefinitionOptions<T>, // The array helper forces an initialValue of an empty record
|
||||
) {
|
||||
return new KeyDefinition<Record<TKey, T>>(stateDefinition, key, {
|
||||
...options,
|
||||
|
||||
@@ -9,5 +9,8 @@ export class StateDefinition {
|
||||
* @param name The name of the state, this needs to be unique from all other {@link StateDefinition}'s.
|
||||
* @param storageLocation The location of where this state should be stored.
|
||||
*/
|
||||
constructor(readonly name: string, readonly storageLocation: StorageLocation) {}
|
||||
constructor(
|
||||
readonly name: string,
|
||||
readonly storageLocation: StorageLocation,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type DefinitelyTypedDefault<T, TCombine> = Omit<
|
||||
export type StateUpdateOptions<T, TCombine> = Partial<DefinitelyTypedDefault<T, TCombine>>;
|
||||
|
||||
export function populateOptionsWithDefault<T, TCombine>(
|
||||
options: StateUpdateOptions<T, TCombine>
|
||||
options: StateUpdateOptions<T, TCombine>,
|
||||
): StateUpdateOptions<T, TCombine> {
|
||||
return {
|
||||
...(DEFAULT_OPTIONS as StateUpdateOptions<T, TCombine>),
|
||||
|
||||
@@ -9,7 +9,10 @@ import { StateUpdateOptions } from "./state-update-options";
|
||||
import { DerivedUserState } from ".";
|
||||
|
||||
export class DeriveContext {
|
||||
constructor(readonly activeUserKey: UserKey, readonly encryptService: EncryptService) {}
|
||||
constructor(
|
||||
readonly activeUserKey: UserKey,
|
||||
readonly encryptService: EncryptService,
|
||||
) {}
|
||||
}
|
||||
|
||||
export type Converter<TFrom, TTo> = (data: TFrom, context: DeriveContext) => Promise<TTo>;
|
||||
@@ -32,7 +35,7 @@ export interface UserState<T> {
|
||||
*/
|
||||
readonly update: <TCombine>(
|
||||
configureState: (state: T, dependencies: TCombine) => T,
|
||||
options?: StateUpdateOptions<T, TCombine>
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<T>;
|
||||
/**
|
||||
* Updates backing stores for the given userId, which may or may not be active.
|
||||
@@ -48,7 +51,7 @@ export interface UserState<T> {
|
||||
readonly updateFor: <TCombine>(
|
||||
userId: UserId,
|
||||
configureState: (state: T, dependencies: TCombine) => T,
|
||||
options?: StateUpdateOptions<T, TCombine>
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<T>;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user