1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

[PM-12047] Remove usage of ActiveUserState from cipher.service (#12814)

* Cipher service web changes

* Updated browser client to pass user id to cipher service observable changes

* Cli changes

* desktop changes

* Fixed test

* Libs changes

* Fixed merge conflicts

* Fixed merge conflicts

* removed duplicate reference fixed conflict

* Fixed test

* Fixed test

* Fixed test

* Fixed desturcturing issue on failed to decrypt ciphers cipher service

* Updated abstraction to use method syntax

* Fixed conflicts

* Fixed test on add edit v2

Passed active userId to delete function

* Used getUserId utility function

* made vault changes

* made suggestion changes

* made suggestion changes

* made suggestion changes

* Replace getUserId function calls with pipe operator syntax for better consistency

* fixed merge conflicts

* revert mistake made of usinf account activity during merge conflict fix

* fixed conflicts

* fixed tests
This commit is contained in:
SmithThe4th
2025-02-12 08:53:31 -05:00
committed by GitHub
parent e45ef6b924
commit a2945203f4
98 changed files with 1174 additions and 725 deletions

View File

@@ -151,11 +151,15 @@ export class DefaultNotificationsService implements NotificationsServiceAbstract
await this.syncService.syncUpsertCipher(
notification.payload as SyncCipherNotification,
notification.type === NotificationType.SyncCipherUpdate,
payloadUserId,
);
break;
case NotificationType.SyncCipherDelete:
case NotificationType.SyncLoginDelete:
await this.syncService.syncDeleteCipher(notification.payload as SyncCipherNotification);
await this.syncService.syncDeleteCipher(
notification.payload as SyncCipherNotification,
payloadUserId,
);
break;
case NotificationType.SyncFolderCreate:
case NotificationType.SyncFolderUpdate:

View File

@@ -3,7 +3,8 @@ import { TextEncoder } from "util";
import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject, of } from "rxjs";
import { Account, AccountService } from "../../../auth/abstractions/account.service";
import { mockAccountServiceWith } from "../../../../spec";
import { Account } from "../../../auth/abstractions/account.service";
import { UserId } from "../../../types/guid";
import { CipherService } from "../../../vault/abstractions/cipher.service";
import { SyncService } from "../../../vault/abstractions/sync/sync.service.abstraction";
@@ -46,7 +47,6 @@ describe("FidoAuthenticatorService", () => {
let userInterface!: MockProxy<Fido2UserInterfaceService<ParentWindowReference>>;
let userInterfaceSession!: MockProxy<Fido2UserInterfaceSession>;
let syncService!: MockProxy<SyncService>;
let accountService!: MockProxy<AccountService>;
let authenticator!: Fido2AuthenticatorService<ParentWindowReference>;
let windowReference!: ParentWindowReference;
@@ -58,7 +58,7 @@ describe("FidoAuthenticatorService", () => {
syncService = mock<SyncService>({
activeUserLastSync$: () => of(new Date()),
});
accountService = mock<AccountService>();
const accountService = mockAccountServiceWith("testId" as UserId);
authenticator = new Fido2AuthenticatorService(
cipherService,
userInterface,

View File

@@ -1,8 +1,9 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { firstValueFrom, map } from "rxjs";
import { firstValueFrom } from "rxjs";
import { AccountService } from "../../../auth/abstractions/account.service";
import { getUserId } from "../../../auth/services/account.service";
import { CipherService } from "../../../vault/abstractions/cipher.service";
import { SyncService } from "../../../vault/abstractions/sync/sync.service.abstraction";
import { CipherRepromptType } from "../../../vault/enums/cipher-reprompt-type";
@@ -145,10 +146,10 @@ export class Fido2AuthenticatorService<ParentWindowReference>
try {
keyPair = await createKeyPair();
pubKeyDer = await crypto.subtle.exportKey("spki", keyPair.publicKey);
const encrypted = await this.cipherService.get(cipherId);
const activeUserId = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
this.accountService.activeAccount$.pipe(getUserId),
);
const encrypted = await this.cipherService.get(cipherId, activeUserId);
cipher = await encrypted.decrypt(
await this.cipherService.getKeyForCipherKeyDecryption(encrypted, activeUserId),
@@ -309,7 +310,7 @@ export class Fido2AuthenticatorService<ParentWindowReference>
if (selectedFido2Credential.counter > 0) {
const activeUserId = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
this.accountService.activeAccount$.pipe(getUserId),
);
const encrypted = await this.cipherService.encrypt(selectedCipher, activeUserId);
await this.cipherService.updateWithServer(encrypted);
@@ -400,7 +401,8 @@ export class Fido2AuthenticatorService<ParentWindowReference>
return [];
}
const ciphers = await this.cipherService.getAllDecrypted();
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const ciphers = await this.cipherService.getAllDecrypted(activeUserId);
return ciphers
.filter(
(cipher) =>
@@ -421,7 +423,8 @@ export class Fido2AuthenticatorService<ParentWindowReference>
return [];
}
const ciphers = await this.cipherService.getAllDecrypted();
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const ciphers = await this.cipherService.getAllDecrypted(activeUserId);
return ciphers.filter(
(cipher) =>
!cipher.isDeleted &&
@@ -438,7 +441,8 @@ export class Fido2AuthenticatorService<ParentWindowReference>
}
private async findCredentialsByRp(rpId: string): Promise<CipherView[]> {
const ciphers = await this.cipherService.getAllDecrypted();
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const ciphers = await this.cipherService.getAllDecrypted(activeUserId);
return ciphers.filter(
(cipher) =>
!cipher.isDeleted &&

View File

@@ -129,12 +129,18 @@ export abstract class CoreSyncService implements SyncService {
return this.syncCompleted(false);
}
async syncUpsertCipher(notification: SyncCipherNotification, isEdit: boolean): Promise<boolean> {
async syncUpsertCipher(
notification: SyncCipherNotification,
isEdit: boolean,
userId: UserId,
): Promise<boolean> {
this.syncStarted();
if (await this.stateService.getIsAuthenticated()) {
const authStatus = await firstValueFrom(this.authService.authStatusFor$(userId));
if (authStatus >= AuthenticationStatus.Locked) {
try {
let shouldUpdate = true;
const localCipher = await this.cipherService.get(notification.id);
const localCipher = await this.cipherService.get(notification.id, userId);
if (localCipher != null && localCipher.revisionDate >= notification.revisionDate) {
shouldUpdate = false;
}
@@ -182,7 +188,7 @@ export abstract class CoreSyncService implements SyncService {
}
} catch (e) {
if (e != null && e.statusCode === 404 && isEdit) {
await this.cipherService.delete(notification.id);
await this.cipherService.delete(notification.id, userId);
this.messageSender.send("syncedDeletedCipher", { cipherId: notification.id });
return this.syncCompleted(true);
}
@@ -191,10 +197,12 @@ export abstract class CoreSyncService implements SyncService {
return this.syncCompleted(false);
}
async syncDeleteCipher(notification: SyncCipherNotification): Promise<boolean> {
async syncDeleteCipher(notification: SyncCipherNotification, userId: UserId): Promise<boolean> {
this.syncStarted();
if (await this.stateService.getIsAuthenticated()) {
await this.cipherService.delete(notification.id);
const authStatus = await firstValueFrom(this.authService.authStatusFor$(userId));
if (authStatus >= AuthenticationStatus.Locked) {
await this.cipherService.delete(notification.id, userId);
this.messageSender.send("syncedDeletedCipher", { cipherId: notification.id });
return this.syncCompleted(true);
}

View File

@@ -62,8 +62,9 @@ export abstract class SyncService {
abstract syncUpsertCipher(
notification: SyncCipherNotification,
isEdit: boolean,
userId: UserId,
): Promise<boolean>;
abstract syncDeleteCipher(notification: SyncFolderNotification): Promise<boolean>;
abstract syncDeleteCipher(notification: SyncFolderNotification, userId: UserId): Promise<boolean>;
abstract syncUpsertSend(notification: SyncSendNotification, isEdit: boolean): Promise<boolean>;
abstract syncDeleteSend(notification: SyncSendNotification): Promise<boolean>;
}