1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-23479] - Can see card filter in AC if you belong to multiple orgs (#15661)

* hide card filter if user does not have a cipher with the allowing org

* fix restricted item type filter visibility

* do not include deleted ciphers
This commit is contained in:
Jordan Aasen
2025-07-23 09:33:29 -07:00
committed by GitHub
parent aee23f7206
commit 417c4cd13b
2 changed files with 45 additions and 8 deletions

View File

@@ -10,6 +10,7 @@ import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstract
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/restricted-item-types.service";
import { DialogService, ToastService } from "@bitwarden/components";
@@ -53,6 +54,7 @@ export class VaultFilterComponent
protected configService: ConfigService,
protected accountService: AccountService,
protected restrictedItemTypesService: RestrictedItemTypesService,
protected cipherService: CipherService,
) {
super(
vaultFilterService,
@@ -65,6 +67,7 @@ export class VaultFilterComponent
configService,
accountService,
restrictedItemTypesService,
cipherService,
);
}
@@ -131,7 +134,7 @@ export class VaultFilterComponent
async buildAllFilters(): Promise<VaultFilterList> {
const builderFilter = {} as VaultFilterList;
builderFilter.typeFilter = await this.addTypeFilter(["favorites"]);
builderFilter.typeFilter = await this.addTypeFilter(["favorites"], this._organization?.id);
builderFilter.collectionFilter = await this.addCollectionFilter();
builderFilter.trashFilter = await this.addTrashFilter();
return builderFilter;

View File

@@ -1,6 +1,7 @@
import { Component, EventEmitter, inject, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { Router } from "@angular/router";
import {
combineLatest,
distinctUntilChanged,
firstValueFrom,
map,
@@ -20,6 +21,7 @@ import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstract
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherType } from "@bitwarden/common/vault/enums";
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/restricted-item-types.service";
@@ -155,6 +157,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
protected configService: ConfigService,
protected accountService: AccountService,
protected restrictedItemTypesService: RestrictedItemTypesService,
protected cipherService: CipherService,
) {}
async ngOnInit(): Promise<void> {
@@ -292,16 +295,47 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
return orgFilterSection;
}
protected async addTypeFilter(excludeTypes: CipherStatus[] = []): Promise<VaultFilterSection> {
protected async addTypeFilter(
excludeTypes: CipherStatus[] = [],
organizationId?: string,
): Promise<VaultFilterSection> {
const allFilter: CipherTypeFilter = { id: "AllItems", name: "allItems", type: "all", icon: "" };
const data$ = this.restrictedItemTypesService.restricted$.pipe(
map((restricted) => {
// List of types restricted by all orgs
const restrictedByAll = restricted
.filter((r) => r.allowViewOrgIds.length === 0)
const userId = await firstValueFrom(this.activeUserId$);
const data$ = combineLatest([
this.restrictedItemTypesService.restricted$,
this.cipherService.cipherViews$(userId),
]).pipe(
map(([restrictedTypes, ciphers]) => {
const restrictedForUser = restrictedTypes
.filter((r) => {
// - All orgs restrict the type
if (r.allowViewOrgIds.length === 0) {
return true;
}
// - Admin console: user has no ciphers of that type in the selected org
// - Individual vault view: user has no ciphers of that type in any allowed org
return !ciphers?.some((c) => {
if (c.deletedDate || c.type !== r.cipherType) {
return false;
}
// If the cipher doesn't belong to an org it is automatically restricted
if (!c.organizationId) {
return false;
}
if (organizationId) {
return (
c.organizationId === organizationId &&
r.allowViewOrgIds.includes(c.organizationId)
);
}
return r.allowViewOrgIds.includes(c.organizationId);
});
})
.map((r) => r.cipherType);
const toExclude = [...excludeTypes, ...restrictedByAll];
const toExclude = [...excludeTypes, ...restrictedForUser];
return this.allTypeFilters.filter(
(f) => typeof f.type === "string" || !toExclude.includes(f.type),
);