From ebe3e98a1fbf4ace7a9f14795120840d64c9427e Mon Sep 17 00:00:00 2001 From: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> Date: Fri, 2 May 2025 10:11:29 -0500 Subject: [PATCH] [PM-21022] Remove fido2Credentials when cloning a cipher (#14573) * remove fido2Credentials from cipherView when cloning a cipher * add check for login on cloning cipher --- .../components/cipher-form.component.spec.ts | 39 ++++++++++++++++++- .../components/cipher-form.component.ts | 4 ++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts b/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts index f53dbfbbda..4c61ad5d2d 100644 --- a/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts +++ b/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts @@ -1,13 +1,17 @@ import { ChangeDetectorRef } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { ReactiveFormsModule } from "@angular/forms"; +import { mock } from "jest-mock-extended"; import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { Fido2CredentialView } from "@bitwarden/common/vault/models/view/fido2-credential.view"; import { ToastService } from "@bitwarden/components"; +import { CipherFormConfig } from "../abstractions/cipher-form-config.service"; import { CipherFormService } from "../abstractions/cipher-form.service"; import { CipherFormCacheService } from "../services/default-cipher-form-cache.service"; @@ -17,20 +21,24 @@ describe("CipherFormComponent", () => { let component: CipherFormComponent; let fixture: ComponentFixture; + const decryptCipher = jest.fn().mockResolvedValue(new CipherView()); + beforeEach(async () => { + decryptCipher.mockClear(); + await TestBed.configureTestingModule({ imports: [CipherFormComponent, ReactiveFormsModule], providers: [ { provide: ChangeDetectorRef, useValue: {} }, { provide: I18nService, useValue: { t: (key: string) => key } }, { provide: ToastService, useValue: { showToast: jest.fn() } }, - { provide: CipherFormService, useValue: { saveCipher: jest.fn() } }, + { provide: CipherFormService, useValue: { saveCipher: jest.fn(), decryptCipher } }, { provide: CipherFormCacheService, useValue: { init: jest.fn(), getCachedCipherView: jest.fn() }, }, { provide: ViewCacheService, useValue: { signal: jest.fn(() => () => null) } }, - { provide: ConfigService, useValue: {} }, + { provide: ConfigService, useValue: mock() }, ], }).compileComponents(); }); @@ -87,4 +95,31 @@ describe("CipherFormComponent", () => { expect(component.website).toEqual("https://example.com"); }); }); + + describe("clone", () => { + const cipherView = new CipherView(); + cipherView.id = "test-id"; + cipherView.login.fido2Credentials = [new Fido2CredentialView()]; + + beforeEach(() => { + component.config = { + mode: "clone", + originalCipher: new Cipher(), + } as CipherFormConfig; + + decryptCipher.mockResolvedValue(cipherView); + }); + + it("clears id on updatedCipherView", async () => { + await component.ngOnInit(); + + expect(component["updatedCipherView"]?.id).toBeNull(); + }); + + it("clears fido2Credentials on updatedCipherView", async () => { + await component.ngOnInit(); + + expect(component["updatedCipherView"]?.login.fido2Credentials).toBeNull(); + }); + }); }); diff --git a/libs/vault/src/cipher-form/components/cipher-form.component.ts b/libs/vault/src/cipher-form/components/cipher-form.component.ts index 96e1328338..8b99b60bc1 100644 --- a/libs/vault/src/cipher-form/components/cipher-form.component.ts +++ b/libs/vault/src/cipher-form/components/cipher-form.component.ts @@ -243,6 +243,10 @@ export class CipherFormComponent implements AfterViewInit, OnInit, OnChanges, Ci if (this.config.mode === "clone") { this.updatedCipherView.id = null; + + if (this.updatedCipherView.login) { + this.updatedCipherView.login.fido2Credentials = null; + } } } else { this.updatedCipherView.type = this.config.cipherType;