1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-04 10:43:47 +00:00

Updated fido2Credentials to initialize as null instead of empty array (#6548)

* Updated fido2Credentials to be null instead of empty string

* Updated cipher tests.

* Fixed tests.

* Updated view and clone logic.

* Updated templates to handle null value.

* Further null checks.
This commit is contained in:
Todd Martin
2023-10-11 17:38:53 -04:00
committed by GitHub
parent a10a53aa15
commit 80c94bf9b7
14 changed files with 27 additions and 24 deletions

View File

@@ -235,7 +235,7 @@ export class Fido2Component implements OnInit, OnDestroy {
} else if (data?.type === "ConfirmNewCredentialRequest") {
let userVerified = false;
if (this.cipher.login.fido2Credentials.length > 0) {
if (this.cipher.login.hasFido2Credentials) {
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "overwritePasskey" },
content: { key: "overwritePasskeyAlert" },

View File

@@ -131,7 +131,7 @@
</div>
<!--Passkey-->
<div class="box" *ngIf="cipher.login.fido2Credentials[0] && !cloneMode">
<div class="box" *ngIf="cipher.login.hasFido2Credentials && !cloneMode">
<div class="box-content">
<div class="box-content-row text-muted">
<span class="row-label">{{ "typePasskey" | i18n }}</span>

View File

@@ -144,7 +144,7 @@
</div>
<!--Passkey-->
<div class="box" *ngIf="cipher.login.fido2Credentials[0]">
<div class="box" *ngIf="cipher.login.hasFido2Credentials">
<div class="box-content">
<div class="box-content-row text-muted">
<span class="row-label">{{ "typePasskey" | i18n }}</span>

View File

@@ -117,7 +117,7 @@
<!--Passkey-->
<div
class="box-content-row text-muted"
*ngIf="cipher.login.fido2Credentials[0] && !cloneMode"
*ngIf="cipher.login.hasFido2Credentials && !cloneMode"
appBoxRow
>
<span class="row-label">{{ "typePasskey" | i18n }}</span>

View File

@@ -119,7 +119,7 @@
</div>
</div>
<!--Passkey-->
<div class="box-content-row text-muted" *ngIf="cipher.login.fido2Credentials[0]">
<div class="box-content-row text-muted" *ngIf="cipher.login.hasFido2Credentials">
<span class="row-label">{{ "typePasskey" | i18n }}</span>
{{ "dateCreated" | i18n }}
{{ cipher.login.fido2Credentials[0].creationDate | date : "short" }}

View File

@@ -191,7 +191,7 @@
</button>
</div>
</div>
<ng-container *ngIf="cipher.login.fido2Credentials[0]">
<ng-container *ngIf="cipher.login.hasFido2Credentials">
<div class="row">
<div class="col-6 form-group">
<label for="loginFido2credential">{{ "typePasskey" | i18n }}</label>

View File

@@ -721,7 +721,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
async cloneCipher(cipher: CipherView) {
if (cipher.login?.fido2Credentials.length > 0) {
if (cipher.login?.hasFido2Credentials) {
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "passkeyNotCopied" },
content: { key: "passkeyNotCopiedAlert" },

View File

@@ -328,8 +328,8 @@ export class AddEditComponent implements OnInit, OnDestroy {
if (this.cloneMode) {
this.cipher.id = null;
if (this.cipher.type === CipherType.Login && this.cipher.login.fido2Credentials.length > 0) {
this.cipher.login.fido2Credentials = [];
if (this.cipher.type === CipherType.Login && this.cipher.login.hasFido2Credentials) {
this.cipher.login.fido2Credentials = null;
}
}

View File

@@ -157,7 +157,7 @@ export class ViewComponent implements OnDestroy, OnInit {
}
async clone() {
if (this.cipher.login?.fido2Credentials.length > 0) {
if (this.cipher.login?.hasFido2Credentials) {
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "passkeyNotCopied" },
content: { key: "passkeyNotCopiedAlert" },

View File

@@ -82,7 +82,6 @@ describe("Cipher DTO", () => {
passwordRevisionDate: "2022-01-31T12:00:00.000Z",
totp: "EncryptedString",
autofillOnPageLoad: false,
fido2Credentials: [],
},
passwordHistory: [
{ password: "EncryptedString", lastUsedDate: "2022-01-31T12:00:00.000Z" },
@@ -151,7 +150,6 @@ describe("Cipher DTO", () => {
password: { encryptedString: "EncryptedString", encryptionType: 0 },
totp: { encryptedString: "EncryptedString", encryptionType: 0 },
uris: [{ match: 0, uri: { encryptedString: "EncryptedString", encryptionType: 0 } }],
fido2Credentials: [],
},
attachments: [
{

View File

@@ -25,7 +25,6 @@ describe("Login DTO", () => {
username: null,
password: null,
totp: null,
fido2Credentials: [],
});
});
@@ -56,9 +55,7 @@ describe("Login DTO", () => {
it("Initialize without LoginData", () => {
const login = new Login();
expect(login).toEqual({
fido2Credentials: [],
});
expect(login).toEqual({});
});
it("Decrypts correctly", async () => {

View File

@@ -16,7 +16,7 @@ export class Login extends Domain {
passwordRevisionDate?: Date;
totp: EncString;
autofillOnPageLoad: boolean;
fido2Credentials: Fido2Credential[] = [];
fido2Credentials: Fido2Credential[];
constructor(obj?: LoginData) {
super();
@@ -46,6 +46,7 @@ export class Login extends Domain {
}
if (obj.fido2Credentials) {
this.fido2Credentials = [];
this.fido2Credentials = obj.fido2Credentials.map((key) => new Fido2Credential(key));
}
}
@@ -71,6 +72,7 @@ export class Login extends Domain {
}
if (this.fido2Credentials != null) {
view.fido2Credentials = [];
view.fido2Credentials = await Promise.all(
this.fido2Credentials.map((key) => key.decrypt(orgId, encKey))
);
@@ -97,7 +99,10 @@ export class Login extends Domain {
});
}
l.fido2Credentials = this.fido2Credentials.map((key) => key.toFido2CredentialData());
if (this.fido2Credentials != null && this.fido2Credentials.length > 0) {
l.fido2Credentials = [];
l.fido2Credentials = this.fido2Credentials.map((key) => key.toFido2CredentialData());
}
return l;
}

View File

@@ -19,7 +19,7 @@ export class LoginView extends ItemView {
totp: string = null;
uris: LoginUriView[] = null;
autofillOnPageLoad: boolean = null;
fido2Credentials: Fido2CredentialView[] = [];
fido2Credentials: Fido2CredentialView[] = null;
constructor(l?: Login) {
super();
@@ -65,6 +65,10 @@ export class LoginView extends ItemView {
return this.uris != null && this.uris.length > 0;
}
get hasFido2Credentials(): boolean {
return this.fido2Credentials != null && this.fido2Credentials.length > 0;
}
matchesUri(
targetUri: string,
equivalentDomains: Set<string>,
@@ -81,8 +85,7 @@ export class LoginView extends ItemView {
const passwordRevisionDate =
obj.passwordRevisionDate == null ? null : new Date(obj.passwordRevisionDate);
const uris = obj.uris?.map((uri: any) => LoginUriView.fromJSON(uri));
const fido2Credentials =
obj.fido2Credentials?.map((key) => Fido2CredentialView.fromJSON(key)) ?? [];
const fido2Credentials = obj.fido2Credentials?.map((key) => Fido2CredentialView.fromJSON(key));
return Object.assign(new LoginView(), obj, {
passwordRevisionDate,

View File

@@ -312,7 +312,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
!cipher.isDeleted &&
cipher.organizationId == undefined &&
cipher.type === CipherType.Login &&
cipher.login.fido2Credentials.length > 0 &&
cipher.login.hasFido2Credentials &&
ids.includes(cipher.login.fido2Credentials[0].credentialId)
)
.map((cipher) => cipher.id);
@@ -340,7 +340,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
(cipher) =>
!cipher.isDeleted &&
cipher.type === CipherType.Login &&
cipher.login.fido2Credentials.length > 0 &&
cipher.login.hasFido2Credentials &&
cipher.login.fido2Credentials[0].rpId === rpId &&
ids.includes(cipher.login.fido2Credentials[0].credentialId)
);
@@ -352,7 +352,7 @@ export class Fido2AuthenticatorService implements Fido2AuthenticatorServiceAbstr
(cipher) =>
!cipher.isDeleted &&
cipher.type === CipherType.Login &&
cipher.login.fido2Credentials.length > 0 &&
cipher.login.hasFido2Credentials &&
cipher.login.fido2Credentials[0].rpId === rpId &&
cipher.login.fido2Credentials[0].discoverable
);