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

[PM-23303] Cards showing in trash (#15517)

* Filter out restricted items from all decrypted ciphers

* Fixed tests
This commit is contained in:
SmithThe4th
2025-07-08 13:59:00 -04:00
committed by GitHub
parent d1b1b5c57b
commit 609ca43693
4 changed files with 24 additions and 12 deletions

View File

@@ -19,6 +19,10 @@ import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data"; import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
import { LocalData } from "@bitwarden/common/vault/models/data/local.data"; import { LocalData } from "@bitwarden/common/vault/models/data/local.data";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import {
RestrictedCipherType,
RestrictedItemTypesService,
} from "@bitwarden/common/vault/services/restricted-item-types.service";
import { InlineMenuFieldQualificationService } from "../../../autofill/services/inline-menu-field-qualification.service"; import { InlineMenuFieldQualificationService } from "../../../autofill/services/inline-menu-field-qualification.service";
import { BrowserApi } from "../../../platform/browser/browser-api"; import { BrowserApi } from "../../../platform/browser/browser-api";
@@ -58,6 +62,11 @@ describe("VaultPopupItemsService", () => {
const userId = Utils.newGuid() as UserId; const userId = Utils.newGuid() as UserId;
const accountServiceMock = mockAccountServiceWith(userId); const accountServiceMock = mockAccountServiceWith(userId);
const restrictedItemTypesService = {
restricted$: new BehaviorSubject<RestrictedCipherType[]>([]),
isCipherRestricted: jest.fn().mockReturnValue(false),
};
beforeEach(() => { beforeEach(() => {
allCiphers = cipherFactory(10); allCiphers = cipherFactory(10);
const cipherList = Object.values(allCiphers); const cipherList = Object.values(allCiphers);
@@ -154,6 +163,10 @@ describe("VaultPopupItemsService", () => {
useValue: inlineMenuFieldQualificationServiceMock, useValue: inlineMenuFieldQualificationServiceMock,
}, },
{ provide: PopupViewCacheService, useValue: viewCacheService }, { provide: PopupViewCacheService, useValue: viewCacheService },
{
provide: RestrictedItemTypesService,
useValue: restrictedItemTypesService,
},
], ],
}); });

View File

@@ -31,6 +31,7 @@ import { SearchService } from "@bitwarden/common/vault/abstractions/search.servi
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service"; import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
import { CipherType } from "@bitwarden/common/vault/enums"; import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/restricted-item-types.service";
import { runInsideAngular } from "../../../platform/browser/run-inside-angular.operator"; import { runInsideAngular } from "../../../platform/browser/run-inside-angular.operator";
import { PopupViewCacheService } from "../../../platform/popup/view-cache/popup-view-cache.service"; import { PopupViewCacheService } from "../../../platform/popup/view-cache/popup-view-cache.service";
@@ -107,9 +108,16 @@ export class VaultPopupItemsService {
combineLatest([ combineLatest([
Utils.asyncToObservable(() => this.cipherService.getAllDecrypted(userId)), Utils.asyncToObservable(() => this.cipherService.getAllDecrypted(userId)),
this.cipherService.failedToDecryptCiphers$(userId), this.cipherService.failedToDecryptCiphers$(userId),
this.restrictedItemTypesService.restricted$.pipe(startWith([])),
]), ]),
), ),
map(([ciphers, failedToDecryptCiphers]) => [...(failedToDecryptCiphers || []), ...ciphers]), map(([ciphers, failedToDecryptCiphers, restrictions]) => {
const allCiphers = [...(failedToDecryptCiphers || []), ...ciphers];
return allCiphers.filter(
(cipher) => !this.restrictedItemTypesService.isCipherRestricted(cipher, restrictions),
);
}),
), ),
), ),
shareReplay({ refCount: true, bufferSize: 1 }), shareReplay({ refCount: true, bufferSize: 1 }),
@@ -307,6 +315,7 @@ export class VaultPopupItemsService {
private syncService: SyncService, private syncService: SyncService,
private accountService: AccountService, private accountService: AccountService,
private ngZone: NgZone, private ngZone: NgZone,
private restrictedItemTypesService: RestrictedItemTypesService,
) {} ) {}
applyFilter(newSearchText: string) { applyFilter(newSearchText: string) {

View File

@@ -486,10 +486,6 @@ describe("VaultPopupListFiltersService", () => {
{ type: CipherType.SecureNote, collectionIds: [], organizationId: null }, { type: CipherType.SecureNote, collectionIds: [], organizationId: null },
] as CipherView[]; ] as CipherView[];
beforeEach(() => {
restrictedItemTypesService.restricted$.next([]);
});
it("filters by cipherType", (done) => { it("filters by cipherType", (done) => {
service.filterFunction$.subscribe((filterFunction) => { service.filterFunction$.subscribe((filterFunction) => {
expect(filterFunction(ciphers)).toEqual([ciphers[0]]); expect(filterFunction(ciphers)).toEqual([ciphers[0]]);

View File

@@ -215,10 +215,9 @@ export class VaultPopupListFiltersService {
*/ */
filterFunction$: Observable<(ciphers: CipherView[]) => CipherView[]> = combineLatest([ filterFunction$: Observable<(ciphers: CipherView[]) => CipherView[]> = combineLatest([
this.filters$, this.filters$,
this.restrictedItemTypesService.restricted$.pipe(startWith([])),
]).pipe( ]).pipe(
map( map(
([filters, restrictions]) => ([filters]) =>
(ciphers: CipherView[]) => (ciphers: CipherView[]) =>
ciphers.filter((cipher) => { ciphers.filter((cipher) => {
// Vault popup lists never shows deleted ciphers // Vault popup lists never shows deleted ciphers
@@ -226,11 +225,6 @@ export class VaultPopupListFiltersService {
return false; return false;
} }
// Check if cipher type is restricted (with organization exemptions)
if (this.restrictedItemTypesService.isCipherRestricted(cipher, restrictions)) {
return false;
}
if (filters.cipherType !== null && cipher.type !== filters.cipherType) { if (filters.cipherType !== null && cipher.type !== filters.cipherType) {
return false; return false;
} }