mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
[PM-10607] Require userId for getKeyForCipherKeyDecryption (#10509)
* updated cipher service to stop using the deprecated getUserKeyWithLegacySupport and use the version that requires a user id * Added account service mock * fixed cipher test * Fixed test * removed async from encryptCipher * updated encryptSharedCipher to pass userId to the encrypt function * Pass userId to getUserKeyWithLegacySupport on encryptSharedCipher * pass in userid when setting masterKeyEncryptedUserKey * Added activer usedId to new web refresh function
This commit is contained in:
@@ -3,11 +3,13 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||
@@ -15,6 +17,8 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { ButtonComponent, ToastService } from "@bitwarden/components";
|
||||
import { DownloadAttachmentComponent } from "@bitwarden/vault";
|
||||
|
||||
import { FakeAccountService, mockAccountServiceWith } from "../../../../../common/spec";
|
||||
|
||||
import { CipherAttachmentsComponent } from "./cipher-attachments.component";
|
||||
import { DeleteAttachmentComponent } from "./delete-attachment/delete-attachment.component";
|
||||
|
||||
@@ -49,6 +53,9 @@ describe("CipherAttachmentsComponent", () => {
|
||||
const cipherServiceGet = jest.fn().mockResolvedValue(cipherDomain);
|
||||
const saveAttachmentWithServer = jest.fn().mockResolvedValue(cipherDomain);
|
||||
|
||||
const mockUserId = Utils.newGuid() as UserId;
|
||||
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
|
||||
|
||||
beforeEach(async () => {
|
||||
cipherServiceGet.mockClear();
|
||||
showToast.mockClear();
|
||||
@@ -75,6 +82,10 @@ describe("CipherAttachmentsComponent", () => {
|
||||
{ provide: LogService, useValue: mock<LogService>() },
|
||||
{ provide: ConfigService, useValue: mock<ConfigService>() },
|
||||
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
|
||||
{
|
||||
provide: AccountService,
|
||||
useValue: accountService,
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideComponent(CipherAttachmentsComponent, {
|
||||
@@ -219,7 +230,7 @@ describe("CipherAttachmentsComponent", () => {
|
||||
it("calls `saveAttachmentWithServer`", async () => {
|
||||
await component.submit();
|
||||
|
||||
expect(saveAttachmentWithServer).toHaveBeenCalledWith(cipherDomain, file);
|
||||
expect(saveAttachmentWithServer).toHaveBeenCalledWith(cipherDomain, file, mockUserId);
|
||||
});
|
||||
|
||||
it("resets form and input values", async () => {
|
||||
|
||||
@@ -19,11 +19,13 @@ import {
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from "@angular/forms";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||
@@ -90,6 +92,7 @@ export class CipherAttachmentsComponent implements OnInit, AfterViewInit {
|
||||
});
|
||||
|
||||
private cipherDomain: Cipher;
|
||||
private activeUserId: UserId;
|
||||
private destroy$ = inject(DestroyRef);
|
||||
|
||||
constructor(
|
||||
@@ -98,6 +101,7 @@ export class CipherAttachmentsComponent implements OnInit, AfterViewInit {
|
||||
private formBuilder: FormBuilder,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
this.attachmentForm.statusChanges.pipe(takeUntilDestroyed()).subscribe((status) => {
|
||||
if (!this.submitBtn) {
|
||||
@@ -110,8 +114,11 @@ export class CipherAttachmentsComponent implements OnInit, AfterViewInit {
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.cipherDomain = await this.cipherService.get(this.cipherId);
|
||||
this.activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
this.cipher = await this.cipherDomain.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain, this.activeUserId),
|
||||
);
|
||||
|
||||
// Update the initial state of the submit button
|
||||
@@ -178,11 +185,12 @@ export class CipherAttachmentsComponent implements OnInit, AfterViewInit {
|
||||
this.cipherDomain = await this.cipherService.saveAttachmentWithServer(
|
||||
this.cipherDomain,
|
||||
file,
|
||||
this.activeUserId,
|
||||
);
|
||||
|
||||
// re-decrypt the cipher to update the attachments
|
||||
this.cipher = await this.cipherDomain.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain, this.activeUserId),
|
||||
);
|
||||
|
||||
// Reset reactive form and input element
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@@ -14,15 +16,25 @@ function isSetEqual(a: Set<string>, b: Set<string>) {
|
||||
@Injectable()
|
||||
export class DefaultCipherFormService implements CipherFormService {
|
||||
private cipherService: CipherService = inject(CipherService);
|
||||
private accountService: AccountService = inject(AccountService);
|
||||
|
||||
async decryptCipher(cipher: Cipher): Promise<CipherView> {
|
||||
return await cipher.decrypt(await this.cipherService.getKeyForCipherKeyDecryption(cipher));
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
return await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
}
|
||||
|
||||
async saveCipher(cipher: CipherView, config: CipherFormConfig): Promise<CipherView> {
|
||||
// Passing the original cipher is important here as it is responsible for appending to password history
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const encryptedCipher = await this.cipherService.encrypt(
|
||||
cipher,
|
||||
activeUserId,
|
||||
null,
|
||||
null,
|
||||
config.originalCipher ?? null,
|
||||
@@ -34,7 +46,7 @@ export class DefaultCipherFormService implements CipherFormService {
|
||||
if (cipher.id == null) {
|
||||
savedCipher = await this.cipherService.createWithServer(encryptedCipher, config.admin);
|
||||
return await savedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(savedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(savedCipher, activeUserId),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -68,7 +80,7 @@ export class DefaultCipherFormService implements CipherFormService {
|
||||
}
|
||||
|
||||
return await savedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(savedCipher),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(savedCipher, activeUserId),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user