mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 17:53:39 +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:
@@ -13,7 +13,7 @@ export abstract class CipherService {
|
||||
model: CipherView,
|
||||
keyForEncryption?: SymmetricCryptoKey,
|
||||
keyForCipherKeyDecryption?: SymmetricCryptoKey,
|
||||
originalCipher?: Cipher
|
||||
originalCipher?: Cipher,
|
||||
) => Promise<Cipher>;
|
||||
encryptFields: (fieldsModel: FieldView[], key: SymmetricCryptoKey) => Promise<Field[]>;
|
||||
encryptField: (fieldModel: FieldView, key: SymmetricCryptoKey) => Promise<Field>;
|
||||
@@ -24,7 +24,7 @@ export abstract class CipherService {
|
||||
getAllDecryptedForUrl: (
|
||||
url: string,
|
||||
includeOtherTypes?: CipherType[],
|
||||
defaultMatch?: UriMatchType
|
||||
defaultMatch?: UriMatchType,
|
||||
) => Promise<CipherView[]>;
|
||||
getAllFromApiForOrganization: (organizationId: string) => Promise<CipherView[]>;
|
||||
getLastUsedForUrl: (url: string, autofillOnPageLoad: boolean) => Promise<CipherView>;
|
||||
@@ -39,23 +39,23 @@ export abstract class CipherService {
|
||||
shareWithServer: (
|
||||
cipher: CipherView,
|
||||
organizationId: string,
|
||||
collectionIds: string[]
|
||||
collectionIds: string[],
|
||||
) => Promise<any>;
|
||||
shareManyWithServer: (
|
||||
ciphers: CipherView[],
|
||||
organizationId: string,
|
||||
collectionIds: string[]
|
||||
collectionIds: string[],
|
||||
) => Promise<any>;
|
||||
saveAttachmentWithServer: (
|
||||
cipher: Cipher,
|
||||
unencryptedFile: any,
|
||||
admin?: boolean
|
||||
admin?: boolean,
|
||||
) => Promise<Cipher>;
|
||||
saveAttachmentRawWithServer: (
|
||||
cipher: Cipher,
|
||||
filename: string,
|
||||
data: ArrayBuffer,
|
||||
admin?: boolean
|
||||
admin?: boolean,
|
||||
) => Promise<Cipher>;
|
||||
saveCollectionsWithServer: (cipher: Cipher) => Promise<any>;
|
||||
upsert: (cipher: CipherData | CipherData[]) => Promise<any>;
|
||||
@@ -74,13 +74,13 @@ export abstract class CipherService {
|
||||
softDeleteWithServer: (id: string, asAdmin?: boolean) => Promise<any>;
|
||||
softDeleteManyWithServer: (ids: string[], asAdmin?: boolean) => Promise<any>;
|
||||
restore: (
|
||||
cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[]
|
||||
cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[],
|
||||
) => Promise<any>;
|
||||
restoreWithServer: (id: string, asAdmin?: boolean) => Promise<any>;
|
||||
restoreManyWithServer: (
|
||||
ids: string[],
|
||||
organizationId?: string,
|
||||
asAdmin?: boolean
|
||||
asAdmin?: boolean,
|
||||
) => Promise<void>;
|
||||
getKeyForCipherKeyDecryption: (cipher: Cipher) => Promise<any>;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export abstract class Fido2AuthenticatorService {
|
||||
makeCredential: (
|
||||
params: Fido2AuthenticatorMakeCredentialsParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
) => Promise<Fido2AuthenticatorMakeCredentialResult>;
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ export abstract class Fido2AuthenticatorService {
|
||||
getAssertion: (
|
||||
params: Fido2AuthenticatorGetAssertionParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
) => Promise<Fido2AuthenticatorGetAssertionResult>;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export abstract class Fido2ClientService {
|
||||
createCredential: (
|
||||
params: CreateCredentialParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
) => Promise<CreateCredentialResult>;
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,7 @@ export abstract class Fido2ClientService {
|
||||
assertCredential: (
|
||||
params: AssertCredentialParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
) => Promise<AssertCredentialResult>;
|
||||
|
||||
isFido2FeatureEnabled: () => Promise<boolean>;
|
||||
|
||||
@@ -51,7 +51,7 @@ export abstract class Fido2UserInterfaceService {
|
||||
newSession: (
|
||||
fallbackSupported: boolean,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
) => Promise<Fido2UserInterfaceSession>;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export abstract class Fido2UserInterfaceSession {
|
||||
* @returns The ID of the cipher that contains the credentials the user picked.
|
||||
*/
|
||||
pickCredential: (
|
||||
params: PickCredentialParams
|
||||
params: PickCredentialParams,
|
||||
) => Promise<{ cipherId: string; userVerified: boolean }>;
|
||||
|
||||
/**
|
||||
@@ -75,7 +75,7 @@ export abstract class Fido2UserInterfaceSession {
|
||||
* @returns The ID of the cipher where the new credential should be saved.
|
||||
*/
|
||||
confirmNewCredential: (
|
||||
params: NewCredentialParams
|
||||
params: NewCredentialParams,
|
||||
) => Promise<{ cipherId: string; userVerified: boolean }>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,6 @@ export abstract class CipherFileUploadService {
|
||||
encFileName: EncString,
|
||||
encData: EncArrayBuffer,
|
||||
admin: boolean,
|
||||
dataEncKey: [SymmetricCryptoKey, EncString]
|
||||
dataEncKey: [SymmetricCryptoKey, EncString],
|
||||
) => Promise<CipherResponse>;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { CipherView } from "../models/view/cipher.view";
|
||||
export function buildCipherIcon(
|
||||
iconsServerUrl: string,
|
||||
cipher: CipherView,
|
||||
isFaviconDisabled: boolean
|
||||
isFaviconDisabled: boolean,
|
||||
) {
|
||||
const imageEnabled = !isFaviconDisabled;
|
||||
let icon;
|
||||
|
||||
@@ -2,7 +2,10 @@ import { LinkedIdType } from "./enums";
|
||||
import { ItemView } from "./models/view/item.view";
|
||||
|
||||
export class LinkedMetadata {
|
||||
constructor(readonly propertyKey: string, private readonly _i18nKey?: string) {}
|
||||
constructor(
|
||||
readonly propertyKey: string,
|
||||
private readonly _i18nKey?: string,
|
||||
) {}
|
||||
|
||||
get i18nKey() {
|
||||
return this._i18nKey ?? this.propertyKey;
|
||||
|
||||
@@ -33,7 +33,7 @@ export class LoginApi extends BaseResponse {
|
||||
const fido2Credentials = this.getResponseProperty("Fido2Credentials");
|
||||
if (fido2Credentials != null) {
|
||||
this.fido2Credentials = fido2Credentials.map(
|
||||
(key: JsonObject) => new Fido2CredentialApi(key)
|
||||
(key: JsonObject) => new Fido2CredentialApi(key),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ describe("Attachment", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export class Attachment extends Domain {
|
||||
fileName: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "url", "sizeName"]
|
||||
["id", "url", "sizeName"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export class Attachment extends Domain {
|
||||
fileName: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
|
||||
if (this.key != null) {
|
||||
@@ -87,7 +87,7 @@ export class Attachment extends Domain {
|
||||
fileName: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "url", "sizeName"]
|
||||
["id", "url", "sizeName"],
|
||||
);
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export class Card extends Domain {
|
||||
expYear: null,
|
||||
code: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export class Card extends Domain {
|
||||
code: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -230,11 +230,11 @@ describe("Cipher DTO", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
|
||||
const cipherView = await cipher.decrypt(
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher)
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
);
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
@@ -350,11 +350,11 @@ describe("Cipher DTO", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
|
||||
const cipherView = await cipher.decrypt(
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher)
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
);
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
@@ -488,11 +488,11 @@ describe("Cipher DTO", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
|
||||
const cipherView = await cipher.decrypt(
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher)
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
);
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
@@ -650,11 +650,11 @@ describe("Cipher DTO", () => {
|
||||
|
||||
(window as any).bitwardenContainerService = new ContainerService(
|
||||
cryptoService,
|
||||
encryptService
|
||||
encryptService,
|
||||
);
|
||||
|
||||
const cipherView = await cipher.decrypt(
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher)
|
||||
await cipherService.getKeyForCipherKeyDecryption(cipher),
|
||||
);
|
||||
|
||||
expect(cipherView).toMatchObject({
|
||||
|
||||
@@ -65,7 +65,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
notes: null,
|
||||
key: null,
|
||||
},
|
||||
["id", "organizationId", "folderId"]
|
||||
["id", "organizationId", "folderId"],
|
||||
);
|
||||
|
||||
this.type = obj.type;
|
||||
@@ -138,7 +138,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
notes: null,
|
||||
},
|
||||
this.organizationId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
|
||||
switch (this.type) {
|
||||
|
||||
@@ -30,7 +30,7 @@ export class Collection extends Domain {
|
||||
hidePasswords: null,
|
||||
manage: null,
|
||||
},
|
||||
["id", "organizationId", "externalId", "readOnly", "hidePasswords", "manage"]
|
||||
["id", "organizationId", "externalId", "readOnly", "hidePasswords", "manage"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export class Collection extends Domain {
|
||||
{
|
||||
name: null,
|
||||
},
|
||||
this.organizationId
|
||||
this.organizationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export class Fido2Credential extends Domain {
|
||||
userDisplayName: null,
|
||||
discoverable: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
this.creationDate = obj.creationDate != null ? new Date(obj.creationDate) : null;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ export class Fido2Credential extends Domain {
|
||||
discoverable: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
|
||||
const { counter } = await this.decryptObj(
|
||||
@@ -75,7 +75,7 @@ export class Fido2Credential extends Domain {
|
||||
counter: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
// Counter will end up as NaN if this fails
|
||||
view.counter = parseInt(counter);
|
||||
@@ -86,7 +86,7 @@ export class Fido2Credential extends Domain {
|
||||
discoverable: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
view.discoverable = discoverable === "true";
|
||||
view.creationDate = this.creationDate;
|
||||
|
||||
@@ -28,7 +28,7 @@ export class Field extends Domain {
|
||||
name: null,
|
||||
value: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export class Field extends Domain {
|
||||
value: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class Field extends Domain {
|
||||
type: null,
|
||||
linkedId: null,
|
||||
},
|
||||
["type", "linkedId"]
|
||||
["type", "linkedId"],
|
||||
);
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export class Folder extends Domain {
|
||||
id: null,
|
||||
name: null,
|
||||
},
|
||||
["id"]
|
||||
["id"],
|
||||
);
|
||||
|
||||
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
|
||||
@@ -35,7 +35,7 @@ export class Folder extends Domain {
|
||||
{
|
||||
name: null,
|
||||
},
|
||||
null
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export class Identity extends Domain {
|
||||
passportNumber: null,
|
||||
licenseNumber: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ export class Identity extends Domain {
|
||||
licenseNumber: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export class LoginUri extends Domain {
|
||||
{
|
||||
uri: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class LoginUri extends Domain {
|
||||
uri: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export class LoginUri extends Domain {
|
||||
uri: null,
|
||||
match: null,
|
||||
},
|
||||
["match"]
|
||||
["match"],
|
||||
);
|
||||
return u;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class Login extends Domain {
|
||||
password: null,
|
||||
totp: null,
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
if (obj.uris) {
|
||||
@@ -59,7 +59,7 @@ export class Login extends Domain {
|
||||
totp: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
|
||||
if (this.uris != null) {
|
||||
@@ -72,7 +72,7 @@ export class Login extends Domain {
|
||||
|
||||
if (this.fido2Credentials != null) {
|
||||
view.fido2Credentials = await Promise.all(
|
||||
this.fido2Credentials.map((key) => key.decrypt(orgId, encKey))
|
||||
this.fido2Credentials.map((key) => key.decrypt(orgId, encKey)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export class Password extends Domain {
|
||||
password: null,
|
||||
},
|
||||
orgId,
|
||||
encKey
|
||||
encKey,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ export class SortedCiphersCache {
|
||||
setTimeout(() => {
|
||||
this.sortedCiphersByUrl.delete(url);
|
||||
this.timeouts.delete(url);
|
||||
}, CacheTTL)
|
||||
}, CacheTTL),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class Ciphers {
|
||||
getLastLaunched() {
|
||||
const usedCiphers = this.ciphers.filter((cipher) => cipher.localData?.lastLaunched);
|
||||
const sortedCiphers = usedCiphers.sort(
|
||||
(x, y) => y.localData.lastLaunched.valueOf() - x.localData.lastLaunched.valueOf()
|
||||
(x, y) => y.localData.lastLaunched.valueOf() - x.localData.lastLaunched.valueOf(),
|
||||
);
|
||||
return sortedCiphers[0];
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export class CardView extends ItemView {
|
||||
// Updated for Mastercard 2017 BINs expansion
|
||||
if (
|
||||
/^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$/.test(
|
||||
cardNum
|
||||
cardNum,
|
||||
)
|
||||
) {
|
||||
return "Mastercard";
|
||||
@@ -112,7 +112,7 @@ export class CardView extends ItemView {
|
||||
|
||||
// Discover
|
||||
re = new RegExp(
|
||||
"^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)"
|
||||
"^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)",
|
||||
);
|
||||
if (cardNum.match(re) != null) {
|
||||
return "Discover";
|
||||
|
||||
@@ -35,7 +35,7 @@ export class CollectionView implements View, ITreeNodeObject {
|
||||
canEdit(org: Organization): boolean {
|
||||
if (org.id !== this.organizationId) {
|
||||
throw new Error(
|
||||
"Id of the organization provided does not match the org id of the collection."
|
||||
"Id of the organization provided does not match the org id of the collection.",
|
||||
);
|
||||
}
|
||||
return org?.canEditAnyCollection || org?.canEditAssignedCollections;
|
||||
@@ -45,7 +45,7 @@ export class CollectionView implements View, ITreeNodeObject {
|
||||
canDelete(org: Organization, flexibleCollectionsEnabled: boolean): boolean {
|
||||
if (org.id !== this.organizationId) {
|
||||
throw new Error(
|
||||
"Id of the organization provided does not match the org id of the collection."
|
||||
"Id of the organization provided does not match the org id of the collection.",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ describe("LoginUriView", () => {
|
||||
const uri = uriFactory(UriMatchType.Domain, exampleUris.standard);
|
||||
const actual = uri.matchesUri(
|
||||
exampleUris.differentDomain,
|
||||
exampleUris.noEquivalentDomains()
|
||||
exampleUris.noEquivalentDomains(),
|
||||
);
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
@@ -136,7 +136,7 @@ describe("LoginUriView", () => {
|
||||
const uri = uriFactory(UriMatchType.Exact, exampleUris.standard);
|
||||
const actual = uri.matchesUri(
|
||||
exampleUris.standard + "#",
|
||||
exampleUris.noEquivalentDomains()
|
||||
exampleUris.noEquivalentDomains(),
|
||||
);
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
@@ -147,7 +147,7 @@ describe("LoginUriView", () => {
|
||||
const uri = uriFactory(UriMatchType.StartsWith, exampleUris.standard);
|
||||
const actual = uri.matchesUri(
|
||||
exampleUris.standard + "#bookmark",
|
||||
exampleUris.noEquivalentDomains()
|
||||
exampleUris.noEquivalentDomains(),
|
||||
);
|
||||
expect(actual).toBe(true);
|
||||
});
|
||||
@@ -156,7 +156,7 @@ describe("LoginUriView", () => {
|
||||
const uri = uriFactory(UriMatchType.StartsWith, exampleUris.standard);
|
||||
const actual = uri.matchesUri(
|
||||
exampleUris.standard.slice(1),
|
||||
exampleUris.noEquivalentDomains()
|
||||
exampleUris.noEquivalentDomains(),
|
||||
);
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
|
||||
@@ -113,7 +113,7 @@ export class LoginUriView implements View {
|
||||
matchesUri(
|
||||
targetUri: string,
|
||||
equivalentDomains: Set<string>,
|
||||
defaultUriMatch: UriMatchType = null
|
||||
defaultUriMatch: UriMatchType = null,
|
||||
): boolean {
|
||||
if (!this.uri || !targetUri) {
|
||||
return false;
|
||||
|
||||
@@ -72,7 +72,7 @@ export class LoginView extends ItemView {
|
||||
matchesUri(
|
||||
targetUri: string,
|
||||
equivalentDomains: Set<string>,
|
||||
defaultUriMatch: UriMatchType = null
|
||||
defaultUriMatch: UriMatchType = null,
|
||||
): boolean {
|
||||
if (this.uris == null) {
|
||||
return false;
|
||||
|
||||
@@ -55,11 +55,11 @@ describe("serviceUtils", () => {
|
||||
|
||||
type TreeNodeFactory<T extends ITreeNodeObject> = (
|
||||
obj: T,
|
||||
children?: TreeNodeFactoryWithoutParent<T>[]
|
||||
children?: TreeNodeFactoryWithoutParent<T>[],
|
||||
) => TreeNodeFactoryWithoutParent<T>;
|
||||
|
||||
type TreeNodeFactoryWithoutParent<T extends ITreeNodeObject> = (
|
||||
parent?: TreeNode<T>
|
||||
parent?: TreeNode<T>,
|
||||
) => TreeNode<T>;
|
||||
|
||||
const createTreeNode: TreeNodeFactory<FakeObject> =
|
||||
|
||||
@@ -16,7 +16,7 @@ export class ServiceUtils {
|
||||
parts: string[],
|
||||
obj: ITreeNodeObject,
|
||||
parent: TreeNode<ITreeNodeObject> | undefined,
|
||||
delimiter: string
|
||||
delimiter: string,
|
||||
) {
|
||||
if (parts.length <= partIndex) {
|
||||
return;
|
||||
@@ -41,7 +41,7 @@ export class ServiceUtils {
|
||||
parts,
|
||||
obj,
|
||||
nodeTree[i],
|
||||
delimiter
|
||||
delimiter,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export class ServiceUtils {
|
||||
[newPartName, ...parts.slice(partIndex + 2)],
|
||||
obj,
|
||||
parent,
|
||||
delimiter
|
||||
delimiter,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export class ServiceUtils {
|
||||
*/
|
||||
static getTreeNodeObject<T extends ITreeNodeObject>(
|
||||
nodeTree: TreeNode<T>,
|
||||
id: string
|
||||
id: string,
|
||||
): TreeNode<T> {
|
||||
if (nodeTree.node.id === id) {
|
||||
return nodeTree;
|
||||
@@ -100,7 +100,7 @@ export class ServiceUtils {
|
||||
*/
|
||||
static getTreeNodeObjectFromList<T extends ITreeNodeObject>(
|
||||
nodeTree: TreeNode<T>[],
|
||||
id: string
|
||||
id: string,
|
||||
): TreeNode<T> {
|
||||
for (let i = 0; i < nodeTree.length; i++) {
|
||||
if (nodeTree[i].node.id === id) {
|
||||
|
||||
@@ -132,7 +132,7 @@ describe("Cipher Service", () => {
|
||||
stateService,
|
||||
encryptService,
|
||||
cipherFileUploadService,
|
||||
configService
|
||||
configService,
|
||||
);
|
||||
|
||||
cipherObj = new Cipher(cipherData);
|
||||
@@ -142,10 +142,10 @@ describe("Cipher Service", () => {
|
||||
const fileName = "filename";
|
||||
const fileData = new Uint8Array(10);
|
||||
cryptoService.getOrgKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey)
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
|
||||
);
|
||||
cryptoService.makeDataEncKey.mockReturnValue(
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)))
|
||||
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32))),
|
||||
);
|
||||
|
||||
configService.checkServerMeetsVersionRequirement$.mockReturnValue(of(false));
|
||||
@@ -253,7 +253,7 @@ describe("Cipher Service", () => {
|
||||
encryptService.decryptToBytes.mockReturnValue(Promise.resolve(makeStaticByteArray(64)));
|
||||
configService.checkServerMeetsVersionRequirement$.mockReturnValue(of(true));
|
||||
cryptoService.makeCipherKey.mockReturnValue(
|
||||
Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey)
|
||||
Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey),
|
||||
);
|
||||
cryptoService.encrypt.mockReturnValue(Promise.resolve(new EncString(ENCRYPTED_TEXT)));
|
||||
});
|
||||
|
||||
@@ -57,7 +57,7 @@ const CIPHER_KEY_ENC_MIN_SERVER_VER = new SemVer("2023.9.1");
|
||||
|
||||
export class CipherService implements CipherServiceAbstraction {
|
||||
private sortedCiphersCache: SortedCiphersCache = new SortedCiphersCache(
|
||||
this.sortCiphersByLastUsed
|
||||
this.sortCiphersByLastUsed,
|
||||
);
|
||||
|
||||
constructor(
|
||||
@@ -69,7 +69,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
private stateService: StateService,
|
||||
private encryptService: EncryptService,
|
||||
private cipherFileUploadService: CipherFileUploadService,
|
||||
private configService: ConfigServiceAbstraction
|
||||
private configService: ConfigServiceAbstraction,
|
||||
) {}
|
||||
|
||||
async getDecryptedCipherCache(): Promise<CipherView[]> {
|
||||
@@ -96,7 +96,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
model: CipherView,
|
||||
keyForEncryption?: SymmetricCryptoKey,
|
||||
keyForCipherKeyDecryption?: SymmetricCryptoKey,
|
||||
originalCipher: Cipher = null
|
||||
originalCipher: Cipher = null,
|
||||
): Promise<Cipher> {
|
||||
if (model.id != null) {
|
||||
if (originalCipher == null) {
|
||||
@@ -131,7 +131,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
model,
|
||||
cipher,
|
||||
keyForEncryption,
|
||||
keyForCipherKeyDecryption
|
||||
keyForCipherKeyDecryption,
|
||||
);
|
||||
} else {
|
||||
if (keyForEncryption == null && cipher.organizationId != null) {
|
||||
@@ -149,7 +149,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
async encryptAttachments(
|
||||
attachmentsModel: AttachmentView[],
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<Attachment[]> {
|
||||
if (attachmentsModel == null || attachmentsModel.length === 0) {
|
||||
return null;
|
||||
@@ -169,7 +169,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
{
|
||||
fileName: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
).then(async () => {
|
||||
if (model.key != null) {
|
||||
attachment.key = await this.cryptoService.encrypt(model.key.key, key);
|
||||
@@ -215,7 +215,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
name: null,
|
||||
value: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
|
||||
return field;
|
||||
@@ -223,7 +223,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
async encryptPasswordHistories(
|
||||
phModels: PasswordHistoryView[],
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<Password[]> {
|
||||
if (!phModels || !phModels.length) {
|
||||
return null;
|
||||
@@ -242,7 +242,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
async encryptPasswordHistory(
|
||||
phModel: PasswordHistoryView,
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<Password> {
|
||||
const ph = new Password();
|
||||
ph.lastUsedDate = phModel.lastUsedDate;
|
||||
@@ -253,7 +253,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
{
|
||||
password: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
|
||||
return ph;
|
||||
@@ -299,17 +299,20 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
|
||||
// Group ciphers by orgId or under 'null' for the user's ciphers
|
||||
const grouped = ciphers.reduce((agg, c) => {
|
||||
agg[c.organizationId] ??= [];
|
||||
agg[c.organizationId].push(c);
|
||||
return agg;
|
||||
}, {} as Record<string, Cipher[]>);
|
||||
const grouped = ciphers.reduce(
|
||||
(agg, c) => {
|
||||
agg[c.organizationId] ??= [];
|
||||
agg[c.organizationId].push(c);
|
||||
return agg;
|
||||
},
|
||||
{} as Record<string, Cipher[]>,
|
||||
);
|
||||
|
||||
const decCiphers = (
|
||||
await Promise.all(
|
||||
Object.entries(grouped).map(([orgId, groupedCiphers]) =>
|
||||
this.encryptService.decryptItems(groupedCiphers, orgKeys.get(orgId) ?? userKey)
|
||||
)
|
||||
this.encryptService.decryptItems(groupedCiphers, orgKeys.get(orgId) ?? userKey),
|
||||
),
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
@@ -352,7 +355,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
async getAllDecryptedForUrl(
|
||||
url: string,
|
||||
includeOtherTypes?: CipherType[],
|
||||
defaultMatch: UriMatchType = null
|
||||
defaultMatch: UriMatchType = null,
|
||||
): Promise<CipherView[]> {
|
||||
if (url == null && includeOtherTypes == null) {
|
||||
return Promise.resolve([]);
|
||||
@@ -528,14 +531,14 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
async shareWithServer(
|
||||
cipher: CipherView,
|
||||
organizationId: string,
|
||||
collectionIds: string[]
|
||||
collectionIds: string[],
|
||||
): Promise<any> {
|
||||
const attachmentPromises: Promise<any>[] = [];
|
||||
if (cipher.attachments != null) {
|
||||
cipher.attachments.forEach((attachment) => {
|
||||
if (attachment.key == null) {
|
||||
attachmentPromises.push(
|
||||
this.shareAttachmentWithServer(attachment, cipher.id, organizationId)
|
||||
this.shareAttachmentWithServer(attachment, cipher.id, organizationId),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -554,7 +557,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
async shareManyWithServer(
|
||||
ciphers: CipherView[],
|
||||
organizationId: string,
|
||||
collectionIds: string[]
|
||||
collectionIds: string[],
|
||||
): Promise<any> {
|
||||
const promises: Promise<any>[] = [];
|
||||
const encCiphers: Cipher[] = [];
|
||||
@@ -564,7 +567,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
promises.push(
|
||||
this.encryptSharedCipher(cipher).then((c) => {
|
||||
encCiphers.push(c);
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
@@ -591,7 +594,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
cipher,
|
||||
unencryptedFile.name,
|
||||
evt.target.result,
|
||||
admin
|
||||
admin,
|
||||
);
|
||||
resolve(cData);
|
||||
} catch (e) {
|
||||
@@ -608,7 +611,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
cipher: Cipher,
|
||||
filename: string,
|
||||
data: Uint8Array,
|
||||
admin = false
|
||||
admin = false,
|
||||
): Promise<Cipher> {
|
||||
const encKey = await this.getKeyForCipherKeyDecryption(cipher);
|
||||
const cipherKeyEncryptionEnabled = await this.getCipherKeyEncryptionEnabled();
|
||||
@@ -616,7 +619,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
const cipherEncKey =
|
||||
cipherKeyEncryptionEnabled && cipher.key != null
|
||||
? (new SymmetricCryptoKey(
|
||||
await this.encryptService.decryptToBytes(cipher.key, encKey)
|
||||
await this.encryptService.decryptToBytes(cipher.key, encKey),
|
||||
) as UserKey)
|
||||
: encKey;
|
||||
|
||||
@@ -639,7 +642,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
encFileName,
|
||||
encData,
|
||||
admin,
|
||||
dataEncKey
|
||||
dataEncKey,
|
||||
);
|
||||
|
||||
const cData = new CipherData(response, cipher.collectionIds);
|
||||
@@ -886,7 +889,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
|
||||
async restore(
|
||||
cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[]
|
||||
cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[],
|
||||
) {
|
||||
const ciphers = await this.stateService.getEncryptedCiphers();
|
||||
if (ciphers == null) {
|
||||
@@ -925,7 +928,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
async restoreManyWithServer(
|
||||
ids: string[],
|
||||
organizationId: string = null,
|
||||
asAdmin = false
|
||||
asAdmin = false,
|
||||
): Promise<void> {
|
||||
let response;
|
||||
if (asAdmin) {
|
||||
@@ -961,10 +964,10 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
|
||||
private async updateModelfromExistingCipher(
|
||||
model: CipherView,
|
||||
originalCipher: Cipher
|
||||
originalCipher: Cipher,
|
||||
): Promise<void> {
|
||||
const existingCipher = await originalCipher.decrypt(
|
||||
await this.getKeyForCipherKeyDecryption(originalCipher)
|
||||
await this.getKeyForCipherKeyDecryption(originalCipher),
|
||||
);
|
||||
model.passwordHistory = existingCipher.passwordHistory || [];
|
||||
if (model.type === CipherType.Login && existingCipher.type === CipherType.Login) {
|
||||
@@ -988,13 +991,13 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
f.name != null &&
|
||||
f.name !== "" &&
|
||||
f.value != null &&
|
||||
f.value !== ""
|
||||
f.value !== "",
|
||||
);
|
||||
const hiddenFields =
|
||||
model.fields == null
|
||||
? []
|
||||
: model.fields.filter(
|
||||
(f) => f.type === FieldType.Hidden && f.name != null && f.name !== ""
|
||||
(f) => f.type === FieldType.Hidden && f.name != null && f.name !== "",
|
||||
);
|
||||
existingHiddenFields.forEach((ef) => {
|
||||
const matchedField = hiddenFields.find((f) => f.name === ef.name);
|
||||
@@ -1020,10 +1023,10 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
private async shareAttachmentWithServer(
|
||||
attachmentView: AttachmentView,
|
||||
cipherId: string,
|
||||
organizationId: string
|
||||
organizationId: string,
|
||||
): Promise<any> {
|
||||
const attachmentResponse = await this.apiService.nativeFetch(
|
||||
new Request(attachmentView.url, { cache: "no-store" })
|
||||
new Request(attachmentView.url, { cache: "no-store" }),
|
||||
);
|
||||
if (attachmentResponse.status !== 200) {
|
||||
throw Error("Failed to download attachment: " + attachmentResponse.status.toString());
|
||||
@@ -1055,7 +1058,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
{
|
||||
filepath: encFileName.encryptedString,
|
||||
contentType: "application/octet-stream",
|
||||
} as any
|
||||
} as any,
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
@@ -1067,7 +1070,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
cipherId,
|
||||
attachmentView.id,
|
||||
fd,
|
||||
organizationId
|
||||
organizationId,
|
||||
);
|
||||
} catch (e) {
|
||||
throw new Error((e as ErrorResponse).getSingleMessage());
|
||||
@@ -1078,7 +1081,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
model: V,
|
||||
obj: D,
|
||||
map: any,
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<void> {
|
||||
const promises = [];
|
||||
const self = this;
|
||||
@@ -1122,7 +1125,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
password: null,
|
||||
totp: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
|
||||
if (model.login.uris != null) {
|
||||
@@ -1136,7 +1139,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
{
|
||||
uri: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
cipher.login.uris.push(loginUri);
|
||||
}
|
||||
@@ -1162,16 +1165,16 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
userDisplayName: null,
|
||||
origin: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
domainKey.counter = await this.cryptoService.encrypt(String(viewKey.counter), key);
|
||||
domainKey.discoverable = await this.cryptoService.encrypt(
|
||||
String(viewKey.discoverable),
|
||||
key
|
||||
key,
|
||||
);
|
||||
domainKey.creationDate = viewKey.creationDate;
|
||||
return domainKey;
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -1192,7 +1195,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
expYear: null,
|
||||
code: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
return;
|
||||
case CipherType.Identity:
|
||||
@@ -1220,7 +1223,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
passportNumber: null,
|
||||
licenseNumber: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
);
|
||||
return;
|
||||
default:
|
||||
@@ -1232,7 +1235,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
url: string,
|
||||
lastUsed: boolean,
|
||||
lastLaunched: boolean,
|
||||
autofillOnPageLoad: boolean
|
||||
autofillOnPageLoad: boolean,
|
||||
): Promise<CipherView> {
|
||||
const cacheKey = autofillOnPageLoad ? "autofillOnPageLoad-" + url : url;
|
||||
|
||||
@@ -1247,7 +1250,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
ciphers = ciphers.filter(
|
||||
(cipher) =>
|
||||
cipher.login.autofillOnPageLoad ||
|
||||
(cipher.login.autofillOnPageLoad == null && autofillOnPageLoadDefault !== false)
|
||||
(cipher.login.autofillOnPageLoad == null && autofillOnPageLoadDefault !== false),
|
||||
);
|
||||
if (ciphers.length === 0) {
|
||||
return null;
|
||||
@@ -1282,7 +1285,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
private async encryptCipher(
|
||||
model: CipherView,
|
||||
cipher: Cipher,
|
||||
key: SymmetricCryptoKey
|
||||
key: SymmetricCryptoKey,
|
||||
): Promise<Cipher> {
|
||||
await Promise.all([
|
||||
this.encryptObjProperty(
|
||||
@@ -1292,7 +1295,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
name: null,
|
||||
notes: null,
|
||||
},
|
||||
key
|
||||
key,
|
||||
),
|
||||
this.encryptCipherData(cipher, model, key),
|
||||
this.encryptFields(model.fields, key).then((fields) => {
|
||||
@@ -1313,7 +1316,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
model: CipherView,
|
||||
cipher: Cipher,
|
||||
keyForCipherKeyEncryption: SymmetricCryptoKey,
|
||||
keyForCipherKeyDecryption: SymmetricCryptoKey
|
||||
keyForCipherKeyDecryption: SymmetricCryptoKey,
|
||||
): Promise<Cipher> {
|
||||
// First, we get the key for cipher key encryption, in its decrypted form
|
||||
let decryptedCipherKey: SymmetricCryptoKey;
|
||||
@@ -1321,14 +1324,14 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
decryptedCipherKey = await this.cryptoService.makeCipherKey();
|
||||
} else {
|
||||
decryptedCipherKey = new SymmetricCryptoKey(
|
||||
await this.encryptService.decryptToBytes(cipher.key, keyForCipherKeyDecryption)
|
||||
await this.encryptService.decryptToBytes(cipher.key, keyForCipherKeyDecryption),
|
||||
);
|
||||
}
|
||||
|
||||
// Then, we have to encrypt the cipher key with the proper key.
|
||||
cipher.key = await this.encryptService.encrypt(
|
||||
decryptedCipherKey.key,
|
||||
keyForCipherKeyEncryption
|
||||
keyForCipherKeyEncryption,
|
||||
);
|
||||
|
||||
// Finally, we can encrypt the cipher with the decrypted cipher key.
|
||||
@@ -1339,7 +1342,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
return (
|
||||
flagEnabled("enableCipherKeyEncryption") &&
|
||||
(await firstValueFrom(
|
||||
this.configService.checkServerMeetsVersionRequirement$(CIPHER_KEY_ENC_MIN_SERVER_VER)
|
||||
this.configService.checkServerMeetsVersionRequirement$(CIPHER_KEY_ENC_MIN_SERVER_VER),
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export class CollectionService implements CollectionServiceAbstraction {
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
private i18nService: I18nService,
|
||||
private stateService: StateService
|
||||
private stateService: StateService,
|
||||
) {}
|
||||
|
||||
async clearCache(userId?: string): Promise<void> {
|
||||
|
||||
@@ -85,7 +85,7 @@ export class SimpleValue {
|
||||
export function decode<T = any>(
|
||||
data: ArrayBuffer | SharedArrayBuffer,
|
||||
tagger?: TaggedValueFunction,
|
||||
simpleValue?: SimpleValueFunction
|
||||
simpleValue?: SimpleValueFunction,
|
||||
): T {
|
||||
let dataView = new DataView(data);
|
||||
let ta = new Uint8Array(data);
|
||||
@@ -485,7 +485,7 @@ export const CBOR: {
|
||||
decode: <T = any>(
|
||||
data: ArrayBuffer | SharedArrayBuffer,
|
||||
tagger?: TaggedValueFunction,
|
||||
simpleValue?: SimpleValueFunction
|
||||
simpleValue?: SimpleValueFunction,
|
||||
) => T;
|
||||
encode: <T = any>(value: T) => ArrayBuffer;
|
||||
} = {
|
||||
|
||||
@@ -78,7 +78,7 @@ export function joseToDer(signature: Uint8Array, alg: Alg) {
|
||||
paramBytes * 2 +
|
||||
'" bytes, saw "' +
|
||||
signatureBytes +
|
||||
'"'
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
beforeEach(async () => {
|
||||
excludedCipher = createCipherView(
|
||||
{ type: CipherType.Login },
|
||||
{ credentialId: Utils.newGuid() }
|
||||
{ credentialId: Utils.newGuid() },
|
||||
);
|
||||
params = await createParams({
|
||||
excludeCredentialDescriptorList: [
|
||||
@@ -126,7 +126,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
],
|
||||
});
|
||||
cipherService.get.mockImplementation(async (id) =>
|
||||
id === excludedCipher.id ? ({ decrypt: () => excludedCipher } as any) : undefined
|
||||
id === excludedCipher.id ? ({ decrypt: () => excludedCipher } as any) : undefined,
|
||||
);
|
||||
cipherService.getAllDecrypted.mockResolvedValue([excludedCipher]);
|
||||
});
|
||||
@@ -182,7 +182,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
});
|
||||
|
||||
it.todo(
|
||||
"should not throw error if the excluded credential has been marked as deleted in the vault"
|
||||
"should not throw error if the excluded credential has been marked as deleted in the vault",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -194,7 +194,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
existingCipher = createCipherView({ type: CipherType.Login });
|
||||
params = await createParams({ requireResidentKey: false });
|
||||
cipherService.get.mockImplementation(async (id) =>
|
||||
id === existingCipher.id ? ({ decrypt: () => existingCipher } as any) : undefined
|
||||
id === existingCipher.id ? ({ decrypt: () => existingCipher } as any) : undefined,
|
||||
);
|
||||
cipherService.getAllDecrypted.mockResolvedValue([existingCipher]);
|
||||
});
|
||||
@@ -254,7 +254,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
}),
|
||||
],
|
||||
}),
|
||||
})
|
||||
}),
|
||||
);
|
||||
expect(cipherService.updateWithServer).toHaveBeenCalledWith(encryptedCipher);
|
||||
});
|
||||
@@ -319,7 +319,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
userVerified: false,
|
||||
});
|
||||
cipherService.get.mockImplementation(async (cipherId) =>
|
||||
cipherId === cipher.id ? ({ decrypt: () => cipher } as any) : undefined
|
||||
cipherId === cipher.id ? ({ decrypt: () => cipher } as any) : undefined,
|
||||
);
|
||||
cipherService.getAllDecrypted.mockResolvedValue([await cipher]);
|
||||
cipherService.encrypt.mockImplementation(async (cipher) => {
|
||||
@@ -340,7 +340,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
const result = await authenticator.makeCredential(params, tab);
|
||||
|
||||
const attestationObject = CBOR.decode(
|
||||
Fido2Utils.bufferSourceToUint8Array(result.attestationObject).buffer
|
||||
Fido2Utils.bufferSourceToUint8Array(result.attestationObject).buffer,
|
||||
);
|
||||
|
||||
const encAuthData: Uint8Array = attestationObject.authData;
|
||||
@@ -361,7 +361,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
0x22, 0x6b, 0xb3, 0x92, 0x02, 0xff, 0xf9, 0x22, 0xdc, 0x74, 0x05, 0xcd, 0x28, 0xa8,
|
||||
0x34, 0x5a, 0xc4, 0xf2, 0x64, 0x51, 0xd7, 0x3d, 0x0b, 0x40, 0xef, 0xf3, 0x1d, 0xc1,
|
||||
0xd0, 0x5c, 0x3d, 0xc3,
|
||||
])
|
||||
]),
|
||||
);
|
||||
expect(flags).toEqual(new Uint8Array([0b01000001])); // UP = true, AD = true
|
||||
expect(counter).toEqual(new Uint8Array([0, 0, 0, 0])); // 0 because of new counter
|
||||
@@ -372,7 +372,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
});
|
||||
|
||||
async function createParams(
|
||||
params: Partial<Fido2AuthenticatorMakeCredentialsParams> = {}
|
||||
params: Partial<Fido2AuthenticatorMakeCredentialsParams> = {},
|
||||
): Promise<Fido2AuthenticatorMakeCredentialsParams> {
|
||||
return {
|
||||
hash: params.hash ?? (await createClientDataHash()),
|
||||
@@ -540,11 +540,11 @@ describe("FidoAuthenticatorService", () => {
|
||||
ciphers = [
|
||||
await createCipherView(
|
||||
{ type: CipherType.Login },
|
||||
{ credentialId: credentialIds[0], rpId: RpId, discoverable: false }
|
||||
{ credentialId: credentialIds[0], rpId: RpId, discoverable: false },
|
||||
),
|
||||
await createCipherView(
|
||||
{ type: CipherType.Login },
|
||||
{ credentialId: credentialIds[1], rpId: RpId, discoverable: true }
|
||||
{ credentialId: credentialIds[1], rpId: RpId, discoverable: true },
|
||||
),
|
||||
];
|
||||
params = await createParams({
|
||||
@@ -642,13 +642,13 @@ describe("FidoAuthenticatorService", () => {
|
||||
keyPair = await createKeyPair();
|
||||
credentialIds = [Utils.newGuid(), Utils.newGuid()];
|
||||
const keyValue = Fido2Utils.bufferToString(
|
||||
await crypto.subtle.exportKey("pkcs8", keyPair.privateKey)
|
||||
await crypto.subtle.exportKey("pkcs8", keyPair.privateKey),
|
||||
);
|
||||
ciphers = credentialIds.map((id) =>
|
||||
createCipherView(
|
||||
{ type: CipherType.Login },
|
||||
{ credentialId: id, rpId: RpId, counter: 9000, keyValue }
|
||||
)
|
||||
{ credentialId: id, rpId: RpId, counter: 9000, keyValue },
|
||||
),
|
||||
);
|
||||
fido2Credentials = ciphers.map((c) => c.login.fido2Credentials[0]);
|
||||
selectedCredentialId = credentialIds[0];
|
||||
@@ -686,7 +686,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
}),
|
||||
],
|
||||
}),
|
||||
})
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -700,14 +700,14 @@ describe("FidoAuthenticatorService", () => {
|
||||
|
||||
expect(result.selectedCredential.id).toEqual(guidToRawFormat(selectedCredentialId));
|
||||
expect(result.selectedCredential.userHandle).toEqual(
|
||||
Fido2Utils.stringToBuffer(fido2Credentials[0].userHandle)
|
||||
Fido2Utils.stringToBuffer(fido2Credentials[0].userHandle),
|
||||
);
|
||||
expect(rpIdHash).toEqual(
|
||||
new Uint8Array([
|
||||
0x22, 0x6b, 0xb3, 0x92, 0x02, 0xff, 0xf9, 0x22, 0xdc, 0x74, 0x05, 0xcd, 0x28, 0xa8,
|
||||
0x34, 0x5a, 0xc4, 0xf2, 0x64, 0x51, 0xd7, 0x3d, 0x0b, 0x40, 0xef, 0xf3, 0x1d, 0xc1,
|
||||
0xd0, 0x5c, 0x3d, 0xc3,
|
||||
])
|
||||
]),
|
||||
);
|
||||
expect(flags).toEqual(new Uint8Array([0b00000001])); // UP = true
|
||||
expect(counter).toEqual(new Uint8Array([0, 0, 0x23, 0x29])); // 9001 in hex
|
||||
@@ -756,7 +756,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
});
|
||||
|
||||
async function createParams(
|
||||
params: Partial<Fido2AuthenticatorGetAssertionParams> = {}
|
||||
params: Partial<Fido2AuthenticatorGetAssertionParams> = {},
|
||||
): Promise<Fido2AuthenticatorGetAssertionParams> {
|
||||
return {
|
||||
rpId: params.rpId ?? RpId,
|
||||
@@ -784,7 +784,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
|
||||
function createCipherView(
|
||||
data: Partial<Omit<CipherView, "fido2Credential">> = {},
|
||||
fido2Credential: Partial<Fido2CredentialView> = {}
|
||||
fido2Credential: Partial<Fido2CredentialView> = {},
|
||||
): CipherView {
|
||||
const cipher = new CipherView();
|
||||
cipher.id = data.id ?? Utils.newGuid();
|
||||
@@ -819,7 +819,7 @@ async function createClientDataHash() {
|
||||
challenge: Fido2Utils.bufferToString(randomBytes(16)),
|
||||
origin: RpId,
|
||||
crossOrigin: false,
|
||||
})
|
||||
}),
|
||||
);
|
||||
return await crypto.subtle.digest({ name: "SHA-256" }, clientData);
|
||||
}
|
||||
@@ -836,6 +836,6 @@ async function createKeyPair() {
|
||||
namedCurve: "P-256",
|
||||
},
|
||||
true,
|
||||
["sign", "verify"]
|
||||
["sign", "verify"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,25 +43,25 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
private cipherService: CipherService,
|
||||
private userInterface: Fido2UserInterfaceService,
|
||||
private syncService: SyncService,
|
||||
private logService?: LogService
|
||||
private logService?: LogService,
|
||||
) {}
|
||||
|
||||
async makeCredential(
|
||||
params: Fido2AuthenticatorMakeCredentialsParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
): Promise<Fido2AuthenticatorMakeCredentialResult> {
|
||||
const userInterfaceSession = await this.userInterface.newSession(
|
||||
params.fallbackSupported,
|
||||
tab,
|
||||
abortController
|
||||
abortController,
|
||||
);
|
||||
|
||||
try {
|
||||
if (params.credTypesAndPubKeyAlgs.every((p) => p.alg !== Fido2AlgorithmIdentifier.ES256)) {
|
||||
const requestedAlgorithms = params.credTypesAndPubKeyAlgs.map((p) => p.alg).join(", ");
|
||||
this.logService?.warning(
|
||||
`[Fido2Authenticator] No compatible algorithms found, RP requested: ${requestedAlgorithms}`
|
||||
`[Fido2Authenticator] No compatible algorithms found, RP requested: ${requestedAlgorithms}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotSupported);
|
||||
}
|
||||
@@ -72,8 +72,8 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Invalid 'requireResidentKey' value: ${String(
|
||||
params.requireResidentKey
|
||||
)}`
|
||||
params.requireResidentKey,
|
||||
)}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
}
|
||||
@@ -84,8 +84,8 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Invalid 'requireUserVerification' value: ${String(
|
||||
params.requireUserVerification
|
||||
)}`
|
||||
params.requireUserVerification,
|
||||
)}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
}
|
||||
@@ -94,11 +94,11 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
await this.syncService.fullSync(false);
|
||||
|
||||
const existingCipherIds = await this.findExcludedCredentials(
|
||||
params.excludeCredentialDescriptorList
|
||||
params.excludeCredentialDescriptorList,
|
||||
);
|
||||
if (existingCipherIds.length > 0) {
|
||||
this.logService?.info(
|
||||
`[Fido2Authenticator] Aborting due to excluded credential found in vault.`
|
||||
`[Fido2Authenticator] Aborting due to excluded credential found in vault.`,
|
||||
);
|
||||
await userInterfaceSession.informExcludedCredential(existingCipherIds);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotAllowed);
|
||||
@@ -120,7 +120,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
|
||||
if (cipherId === undefined) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Authenticator] Aborting because user confirmation was not recieved.`
|
||||
`[Fido2Authenticator] Aborting because user confirmation was not recieved.`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotAllowed);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
pubKeyDer = await crypto.subtle.exportKey("spki", keyPair.publicKey);
|
||||
const encrypted = await this.cipherService.get(cipherId);
|
||||
cipher = await encrypted.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(encrypted)
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(encrypted),
|
||||
);
|
||||
|
||||
if (
|
||||
@@ -138,7 +138,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
(params.requireUserVerification || cipher.reprompt !== CipherRepromptType.None)
|
||||
) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Authenticator] Aborting because user verification was unsuccessful.`
|
||||
`[Fido2Authenticator] Aborting because user verification was unsuccessful.`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotAllowed);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
credentialId = fido2Credential.credentialId;
|
||||
} catch (error) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Aborting because of unknown error when creating credential: ${error}`
|
||||
`[Fido2Authenticator] Aborting because of unknown error when creating credential: ${error}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
fmt: "none",
|
||||
attStmt: {},
|
||||
authData,
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -186,12 +186,12 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
async getAssertion(
|
||||
params: Fido2AuthenticatorGetAssertionParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController?: AbortController
|
||||
abortController?: AbortController,
|
||||
): Promise<Fido2AuthenticatorGetAssertionResult> {
|
||||
const userInterfaceSession = await this.userInterface.newSession(
|
||||
params.fallbackSupported,
|
||||
tab,
|
||||
abortController
|
||||
abortController,
|
||||
);
|
||||
try {
|
||||
if (
|
||||
@@ -200,8 +200,8 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Invalid 'requireUserVerification' value: ${String(
|
||||
params.requireUserVerification
|
||||
)}`
|
||||
params.requireUserVerification,
|
||||
)}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
if (params.allowCredentialDescriptorList?.length > 0) {
|
||||
cipherOptions = await this.findCredentialsById(
|
||||
params.allowCredentialDescriptorList,
|
||||
params.rpId
|
||||
params.rpId,
|
||||
);
|
||||
} else {
|
||||
cipherOptions = await this.findCredentialsByRp(params.rpId);
|
||||
@@ -222,7 +222,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
|
||||
if (cipherOptions.length === 0) {
|
||||
this.logService?.info(
|
||||
`[Fido2Authenticator] Aborting because no matching credentials were found in the vault.`
|
||||
`[Fido2Authenticator] Aborting because no matching credentials were found in the vault.`,
|
||||
);
|
||||
|
||||
if (params.fallbackSupported) {
|
||||
@@ -243,7 +243,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
|
||||
if (selectedCipher === undefined) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Aborting because the selected credential could not be found.`
|
||||
`[Fido2Authenticator] Aborting because the selected credential could not be found.`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotAllowed);
|
||||
}
|
||||
@@ -253,7 +253,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
(params.requireUserVerification || selectedCipher.reprompt !== CipherRepromptType.None)
|
||||
) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Authenticator] Aborting because user verification was unsuccessful.`
|
||||
`[Fido2Authenticator] Aborting because user verification was unsuccessful.`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.NotAllowed);
|
||||
}
|
||||
@@ -295,7 +295,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
};
|
||||
} catch (error) {
|
||||
this.logService?.error(
|
||||
`[Fido2Authenticator] Aborting because of unknown error when asserting credential: ${error}`
|
||||
`[Fido2Authenticator] Aborting because of unknown error when asserting credential: ${error}`,
|
||||
);
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
}
|
||||
@@ -306,7 +306,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
|
||||
/** Finds existing crendetials and returns the `cipherId` for each one */
|
||||
private async findExcludedCredentials(
|
||||
credentials: PublicKeyCredentialDescriptor[]
|
||||
credentials: PublicKeyCredentialDescriptor[],
|
||||
): Promise<string[]> {
|
||||
const ids: string[] = [];
|
||||
|
||||
@@ -329,14 +329,14 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
cipher.organizationId == undefined &&
|
||||
cipher.type === CipherType.Login &&
|
||||
cipher.login.hasFido2Credentials &&
|
||||
ids.includes(cipher.login.fido2Credentials[0].credentialId)
|
||||
ids.includes(cipher.login.fido2Credentials[0].credentialId),
|
||||
)
|
||||
.map((cipher) => cipher.id);
|
||||
}
|
||||
|
||||
private async findCredentialsById(
|
||||
credentials: PublicKeyCredentialDescriptor[],
|
||||
rpId: string
|
||||
rpId: string,
|
||||
): Promise<CipherView[]> {
|
||||
const ids: string[] = [];
|
||||
|
||||
@@ -358,7 +358,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
cipher.type === CipherType.Login &&
|
||||
cipher.login.hasFido2Credentials &&
|
||||
cipher.login.fido2Credentials[0].rpId === rpId &&
|
||||
ids.includes(cipher.login.fido2Credentials[0].credentialId)
|
||||
ids.includes(cipher.login.fido2Credentials[0].credentialId),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
|
||||
cipher.type === CipherType.Login &&
|
||||
cipher.login.hasFido2Credentials &&
|
||||
cipher.login.fido2Credentials[0].rpId === rpId &&
|
||||
cipher.login.fido2Credentials[0].discoverable
|
||||
cipher.login.fido2Credentials[0].discoverable,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -382,13 +382,13 @@ async function createKeyPair() {
|
||||
namedCurve: "P-256",
|
||||
},
|
||||
true,
|
||||
KeyUsages
|
||||
KeyUsages,
|
||||
);
|
||||
}
|
||||
|
||||
async function createKeyView(
|
||||
params: Fido2AuthenticatorMakeCredentialsParams,
|
||||
keyValue: CryptoKey
|
||||
keyValue: CryptoKey,
|
||||
): Promise<Fido2CredentialView> {
|
||||
if (keyValue.algorithm.name !== "ECDSA" && (keyValue.algorithm as any).namedCurve !== "P-256") {
|
||||
throw new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.Unknown);
|
||||
@@ -414,7 +414,7 @@ async function createKeyView(
|
||||
}
|
||||
|
||||
async function getPrivateKeyFromFido2Credential(
|
||||
fido2Credential: Fido2CredentialView
|
||||
fido2Credential: Fido2CredentialView,
|
||||
): Promise<CryptoKey> {
|
||||
const keyBuffer = Fido2Utils.stringToBuffer(fido2Credential.keyValue);
|
||||
return await crypto.subtle.importKey(
|
||||
@@ -425,7 +425,7 @@ async function getPrivateKeyFromFido2Credential(
|
||||
namedCurve: fido2Credential.keyCurve,
|
||||
} as EcKeyImportParams,
|
||||
true,
|
||||
KeyUsages
|
||||
KeyUsages,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ async function generateAuthData(params: AuthDataParams) {
|
||||
const authData: Array<number> = [];
|
||||
|
||||
const rpIdHash = new Uint8Array(
|
||||
await crypto.subtle.digest({ name: "SHA-256" }, Utils.fromByteStringToArray(params.rpId))
|
||||
await crypto.subtle.digest({ name: "SHA-256" }, Utils.fromByteStringToArray(params.rpId)),
|
||||
);
|
||||
authData.push(...rpIdHash);
|
||||
|
||||
@@ -461,7 +461,7 @@ async function generateAuthData(params: AuthDataParams) {
|
||||
((counter & 0xff000000) >> 24) & 0xff,
|
||||
((counter & 0x00ff0000) >> 16) & 0xff,
|
||||
((counter & 0x0000ff00) >> 8) & 0xff,
|
||||
counter & 0x000000ff
|
||||
counter & 0x000000ff,
|
||||
);
|
||||
|
||||
if (params.keyPair) {
|
||||
@@ -515,8 +515,8 @@ async function generateSignature(params: SignatureParams) {
|
||||
hash: { name: "SHA-256" },
|
||||
},
|
||||
params.privateKey,
|
||||
sigBase
|
||||
)
|
||||
sigBase,
|
||||
),
|
||||
);
|
||||
|
||||
const asn1Der_signature = joseToDer(p1336_signature, "ES256");
|
||||
|
||||
@@ -190,7 +190,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
}),
|
||||
}),
|
||||
tab,
|
||||
expect.anything()
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -198,7 +198,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
it("should throw error if authenticator throws InvalidState", async () => {
|
||||
const params = createParams();
|
||||
authenticator.makeCredential.mockRejectedValue(
|
||||
new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.InvalidState)
|
||||
new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.InvalidState),
|
||||
);
|
||||
|
||||
const result = async () => await client.createCredential(params, tab);
|
||||
@@ -369,7 +369,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
it("should throw error if authenticator throws InvalidState", async () => {
|
||||
const params = createParams();
|
||||
authenticator.getAssertion.mockRejectedValue(
|
||||
new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.InvalidState)
|
||||
new Fido2AuthenticatorError(Fido2AuthenticatorErrorCode.InvalidState),
|
||||
);
|
||||
|
||||
const result = async () => await client.assertCredential(params, tab);
|
||||
@@ -454,7 +454,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
],
|
||||
}),
|
||||
tab,
|
||||
expect.anything()
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -476,7 +476,7 @@ describe("FidoAuthenticatorService", () => {
|
||||
allowCredentialDescriptorList: [],
|
||||
}),
|
||||
tab,
|
||||
expect.anything()
|
||||
expect.anything(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,12 +42,12 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
private configService: ConfigServiceAbstraction,
|
||||
private authService: AuthService,
|
||||
private stateService: StateService,
|
||||
private logService?: LogService
|
||||
private logService?: LogService,
|
||||
) {}
|
||||
|
||||
async isFido2FeatureEnabled(): Promise<boolean> {
|
||||
const featureFlagEnabled = await this.configService.getFeatureFlag<boolean>(
|
||||
FeatureFlag.Fido2VaultCredentials
|
||||
FeatureFlag.Fido2VaultCredentials,
|
||||
);
|
||||
const userEnabledPasskeys = await this.stateService.getEnablePasskeys();
|
||||
return featureFlagEnabled && userEnabledPasskeys;
|
||||
@@ -56,7 +56,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
async createCredential(
|
||||
params: CreateCredentialParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController = new AbortController()
|
||||
abortController = new AbortController(),
|
||||
): Promise<CreateCredentialResult> {
|
||||
const enableFido2VaultCredentials = await this.isFido2FeatureEnabled();
|
||||
|
||||
@@ -74,7 +74,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
|
||||
if (!params.sameOriginWithAncestors) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] Invalid 'sameOriginWithAncestors' value: ${params.sameOriginWithAncestors}`
|
||||
`[Fido2Client] Invalid 'sameOriginWithAncestors' value: ${params.sameOriginWithAncestors}`,
|
||||
);
|
||||
throw new DOMException("Invalid 'sameOriginWithAncestors' value", "NotAllowedError");
|
||||
}
|
||||
@@ -82,7 +82,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
const userId = Fido2Utils.stringToBuffer(params.user.id);
|
||||
if (userId.length < 1 || userId.length > 64) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] Invalid 'user.id' length: ${params.user.id} (${userId.length})`
|
||||
`[Fido2Client] Invalid 'user.id' length: ${params.user.id} (${userId.length})`,
|
||||
);
|
||||
throw new TypeError("Invalid 'user.id' length");
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
|
||||
if (!isValidRpId(params.rp.id, params.origin)) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] 'rp.id' cannot be used with the current origin: rp.id = ${params.rp.id}; origin = ${params.origin}`
|
||||
`[Fido2Client] 'rp.id' cannot be used with the current origin: rp.id = ${params.rp.id}; origin = ${params.origin}`,
|
||||
);
|
||||
throw new DOMException("'rp.id' cannot be used with the current origin", "SecurityError");
|
||||
}
|
||||
@@ -112,7 +112,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
if (params.pubKeyCredParams?.length > 0) {
|
||||
// Filter out all unsupported algorithms
|
||||
credTypesAndPubKeyAlgs = params.pubKeyCredParams.filter(
|
||||
(kp) => kp.alg === -7 && kp.type === "public-key"
|
||||
(kp) => kp.alg === -7 && kp.type === "public-key",
|
||||
);
|
||||
} else {
|
||||
// Assign default algorithms
|
||||
@@ -125,7 +125,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
if (credTypesAndPubKeyAlgs.length === 0) {
|
||||
const requestedAlgorithms = credTypesAndPubKeyAlgs.map((p) => p.alg).join(", ");
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] No compatible algorithms found, RP requested: ${requestedAlgorithms}`
|
||||
`[Fido2Client] No compatible algorithms found, RP requested: ${requestedAlgorithms}`,
|
||||
);
|
||||
throw new DOMException("No supported key algorithms were found", "NotSupportedError");
|
||||
}
|
||||
@@ -154,7 +154,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
const timeout = setAbortTimeout(
|
||||
abortController,
|
||||
params.authenticatorSelection?.userVerification,
|
||||
params.timeout
|
||||
params.timeout,
|
||||
);
|
||||
|
||||
let makeCredentialResult;
|
||||
@@ -162,7 +162,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
makeCredentialResult = await this.authenticator.makeCredential(
|
||||
makeCredentialParams,
|
||||
tab,
|
||||
abortController
|
||||
abortController,
|
||||
);
|
||||
} catch (error) {
|
||||
if (
|
||||
@@ -184,7 +184,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
this.logService?.info(`[Fido2Client] Aborted by user: ${error}`);
|
||||
throw new DOMException(
|
||||
"The operation either timed out or was not allowed.",
|
||||
"NotAllowedError"
|
||||
"NotAllowedError",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
async assertCredential(
|
||||
params: AssertCredentialParams,
|
||||
tab: chrome.tabs.Tab,
|
||||
abortController = new AbortController()
|
||||
abortController = new AbortController(),
|
||||
): Promise<AssertCredentialResult> {
|
||||
const enableFido2VaultCredentials = await this.isFido2FeatureEnabled();
|
||||
|
||||
@@ -240,7 +240,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
|
||||
if (!isValidRpId(params.rpId, params.origin)) {
|
||||
this.logService?.warning(
|
||||
`[Fido2Client] 'rp.id' cannot be used with the current origin: rp.id = ${params.rpId}; origin = ${params.origin}`
|
||||
`[Fido2Client] 'rp.id' cannot be used with the current origin: rp.id = ${params.rpId}; origin = ${params.origin}`,
|
||||
);
|
||||
throw new DOMException("'rp.id' cannot be used with the current origin", "SecurityError");
|
||||
}
|
||||
@@ -269,7 +269,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
getAssertionResult = await this.authenticator.getAssertion(
|
||||
getAssertionParams,
|
||||
tab,
|
||||
abortController
|
||||
abortController,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof FallbackRequestedError) {
|
||||
@@ -296,7 +296,7 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
|
||||
this.logService?.info(`[Fido2Client] Aborted by user: ${error}`);
|
||||
throw new DOMException(
|
||||
"The operation either timed out or was not allowed.",
|
||||
"NotAllowedError"
|
||||
"NotAllowedError",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ const TIMEOUTS = {
|
||||
function setAbortTimeout(
|
||||
abortController: AbortController,
|
||||
userVerification?: UserVerification,
|
||||
timeout?: number
|
||||
timeout?: number,
|
||||
): number {
|
||||
let clampedTimeout: number;
|
||||
|
||||
@@ -343,13 +343,13 @@ function setAbortTimeout(
|
||||
timeout = timeout ?? TIMEOUTS.WITH_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(
|
||||
TIMEOUTS.WITH_VERIFICATION.MIN,
|
||||
Math.min(timeout, TIMEOUTS.WITH_VERIFICATION.MAX)
|
||||
Math.min(timeout, TIMEOUTS.WITH_VERIFICATION.MAX),
|
||||
);
|
||||
} else {
|
||||
timeout = timeout ?? TIMEOUTS.NO_VERIFICATION.DEFAULT;
|
||||
clampedTimeout = Math.max(
|
||||
TIMEOUTS.NO_VERIFICATION.MIN,
|
||||
Math.min(timeout, TIMEOUTS.NO_VERIFICATION.MAX)
|
||||
Math.min(timeout, TIMEOUTS.NO_VERIFICATION.MAX),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,17 @@ import { AttachmentUploadDataResponse } from "../../models/response/attachment-u
|
||||
import { CipherResponse } from "../../models/response/cipher.response";
|
||||
|
||||
export class CipherFileUploadService implements CipherFileUploadServiceAbstraction {
|
||||
constructor(private apiService: ApiService, private fileUploadService: FileUploadService) {}
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private fileUploadService: FileUploadService,
|
||||
) {}
|
||||
|
||||
async upload(
|
||||
cipher: Cipher,
|
||||
encFileName: EncString,
|
||||
encData: EncArrayBuffer,
|
||||
admin: boolean,
|
||||
dataEncKey: [SymmetricCryptoKey, EncString]
|
||||
dataEncKey: [SymmetricCryptoKey, EncString],
|
||||
): Promise<CipherResponse> {
|
||||
const request: AttachmentRequest = {
|
||||
key: dataEncKey[1].encryptedString,
|
||||
@@ -39,7 +42,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
uploadDataResponse,
|
||||
encFileName,
|
||||
encData,
|
||||
this.generateMethods(uploadDataResponse, response, request.adminRequest)
|
||||
this.generateMethods(uploadDataResponse, response, request.adminRequest),
|
||||
);
|
||||
} catch (e) {
|
||||
if (
|
||||
@@ -51,7 +54,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
cipher.id,
|
||||
encFileName,
|
||||
encData,
|
||||
dataEncKey[1]
|
||||
dataEncKey[1],
|
||||
);
|
||||
} else if (e instanceof ErrorResponse) {
|
||||
throw new Error((e as ErrorResponse).getSingleMessage());
|
||||
@@ -65,7 +68,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
private generateMethods(
|
||||
uploadData: AttachmentUploadDataResponse,
|
||||
response: CipherResponse,
|
||||
isAdmin: boolean
|
||||
isAdmin: boolean,
|
||||
): FileUploadApiMethods {
|
||||
return {
|
||||
postDirect: this.generatePostDirectCallback(uploadData, isAdmin),
|
||||
@@ -84,12 +87,12 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
private generateRenewFileUploadUrlCallback(
|
||||
uploadData: AttachmentUploadDataResponse,
|
||||
response: CipherResponse,
|
||||
isAdmin: boolean
|
||||
isAdmin: boolean,
|
||||
) {
|
||||
return async () => {
|
||||
const renewResponse = await this.apiService.renewAttachmentUploadUrl(
|
||||
response.id,
|
||||
uploadData.attachmentId
|
||||
uploadData.attachmentId,
|
||||
);
|
||||
return renewResponse?.url;
|
||||
};
|
||||
@@ -98,7 +101,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
private generateRollbackCallback(
|
||||
response: CipherResponse,
|
||||
uploadData: AttachmentUploadDataResponse,
|
||||
isAdmin: boolean
|
||||
isAdmin: boolean,
|
||||
) {
|
||||
return () => {
|
||||
if (isAdmin) {
|
||||
@@ -118,7 +121,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
cipherId: string,
|
||||
encFileName: EncString,
|
||||
encData: EncArrayBuffer,
|
||||
key: EncString
|
||||
key: EncString,
|
||||
) {
|
||||
const fd = new FormData();
|
||||
try {
|
||||
@@ -134,7 +137,7 @@ export class CipherFileUploadService implements CipherFileUploadServiceAbstracti
|
||||
{
|
||||
filepath: encFileName.encryptedString,
|
||||
contentType: "application/octet-stream",
|
||||
} as any
|
||||
} as any,
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
|
||||
@@ -7,7 +7,10 @@ import { FolderRequest } from "../../../vault/models/request/folder.request";
|
||||
import { FolderResponse } from "../../../vault/models/response/folder.response";
|
||||
|
||||
export class FolderApiService implements FolderApiServiceAbstraction {
|
||||
constructor(private folderService: InternalFolderService, private apiService: ApiService) {}
|
||||
constructor(
|
||||
private folderService: InternalFolderService,
|
||||
private apiService: ApiService,
|
||||
) {}
|
||||
|
||||
async save(folder: Folder): Promise<any> {
|
||||
const request = new FolderRequest(folder);
|
||||
|
||||
@@ -43,7 +43,7 @@ describe("Folder Service", () => {
|
||||
|
||||
cryptoService.hasUserKey.mockResolvedValue(true);
|
||||
cryptoService.getUserKeyWithLegacySupport.mockResolvedValue(
|
||||
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey
|
||||
new SymmetricCryptoKey(makeStaticByteArray(32)) as UserKey,
|
||||
);
|
||||
encryptService.decryptToUtf8.mockResolvedValue("DEC");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
private cryptoService: CryptoService,
|
||||
private i18nService: I18nService,
|
||||
private cipherService: CipherService,
|
||||
private stateService: StateService
|
||||
private stateService: StateService,
|
||||
) {
|
||||
this.stateService.activeAccountUnlocked$
|
||||
.pipe(
|
||||
@@ -41,7 +41,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
|
||||
const data = await this.stateService.getEncryptedFolders();
|
||||
|
||||
await this.updateObservables(data);
|
||||
})
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
private folderApiService: FolderApiServiceAbstraction,
|
||||
private organizationService: InternalOrganizationServiceAbstraction,
|
||||
private sendApiService: SendApiService,
|
||||
private logoutCallback: (expired: boolean) => Promise<void>
|
||||
private logoutCallback: (expired: boolean) => Promise<void>,
|
||||
) {}
|
||||
|
||||
async getLastSync(): Promise<Date> {
|
||||
@@ -339,7 +339,7 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
// The `forcePasswordReset` flag indicates an admin has reset the user's password and must be updated
|
||||
if (profileResponse.forcePasswordReset) {
|
||||
await this.stateService.setForceSetPasswordReason(
|
||||
ForceSetPasswordReason.AdminForcePasswordReset
|
||||
ForceSetPasswordReason.AdminForcePasswordReset,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ export class SyncService implements SyncServiceAbstraction {
|
||||
// TDE user w/out MP went from having no password reset permission to having it.
|
||||
// Must set the force password reset reason so the auth guard will redirect to the set password page.
|
||||
await this.stateService.setForceSetPasswordReason(
|
||||
ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission
|
||||
ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const SteamChars = "23456789BCDFGHJKMNPQRTVWXY";
|
||||
export class TotpService implements TotpServiceAbstraction {
|
||||
constructor(
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private logService: LogService
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
async getCode(key: string): Promise<string> {
|
||||
@@ -160,7 +160,7 @@ export class TotpService implements TotpServiceAbstraction {
|
||||
private async sign(
|
||||
keyBytes: Uint8Array,
|
||||
timeBytes: Uint8Array,
|
||||
alg: "sha1" | "sha256" | "sha512"
|
||||
alg: "sha1" | "sha256" | "sha512",
|
||||
) {
|
||||
const signature = await this.cryptoFunctionService.hmac(timeBytes, keyBytes, alg);
|
||||
return new Uint8Array(signature);
|
||||
|
||||
@@ -32,7 +32,7 @@ export type SyncEventArgs =
|
||||
* ```
|
||||
*/
|
||||
export function isSuccessfullyCompleted(
|
||||
syncEvent: SyncEventArgs
|
||||
syncEvent: SyncEventArgs,
|
||||
): syncEvent is SyncSuccessfullyCompletedEventArgs {
|
||||
return syncEvent.status === "Completed" && syncEvent.successfully;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user