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

[PM-21451] [Vault] [CLI] Changes to Enforce "Remove card item type policy" (#15187)

* Created new service to get restricted types for the CLI

* Created service for cli to get restricted types

* Utilized restriction service in commands

* Renamed function

* Refactored service and made it simpler to check when a cipher type is restricted or not

* Moved service to common so it can be utilized on the cli

* Refactored service to use restricted type service

* Removed userId passing from commands

* Exclude restrict types from export

* Added missing dependency

* Added missing dependency

* Added missing dependency

* Added service utils commit from desktop PR

* refactored to use reusable function

* updated reference

* updated reference

* Fixed merge conflicts

* Refactired services to use isCipherRestricted

* Refactored restricted item types service

* Updated services to use the reafctored item types service
This commit is contained in:
SmithThe4th
2025-06-23 12:04:56 -04:00
committed by GitHub
parent 2e8c0de719
commit e291e2df0a
24 changed files with 444 additions and 113 deletions

View File

@@ -3,7 +3,6 @@
import { Unassigned } from "@bitwarden/admin-console/common";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { RestrictedCipherType } from "@bitwarden/common/vault/services/restricted-item-types.service";
import { createFilterFunction } from "./filter-function";
import { All } from "./routed-vault-filter.model";
@@ -215,46 +214,6 @@ describe("createFilter", () => {
expect(result).toBe(true);
});
});
describe("given restricted types", () => {
const restrictedTypes: RestrictedCipherType[] = [
{ cipherType: CipherType.Login, allowViewOrgIds: [] },
];
it("should filter out a cipher whose type is fully restricted", () => {
const cipher = createCipher({ type: CipherType.Login });
const filterFunction = createFilterFunction({}, restrictedTypes);
expect(filterFunction(cipher)).toBe(false);
});
it("should allow a cipher when the cipher's organization allows it", () => {
const cipher = createCipher({ type: CipherType.Login, organizationId: "org1" });
const restricted: RestrictedCipherType[] = [
{ cipherType: CipherType.Login, allowViewOrgIds: ["org1"] },
];
const filterFunction2 = createFilterFunction({}, restricted);
expect(filterFunction2(cipher)).toBe(true);
});
it("should filter out a personal vault cipher when the owning orgs does not allow it", () => {
const cipher = createCipher({ type: CipherType.Card, organizationId: "org1" });
const restricted2: RestrictedCipherType[] = [
{ cipherType: CipherType.Card, allowViewOrgIds: [] },
];
const filterFunction3 = createFilterFunction({}, restricted2);
expect(filterFunction3(cipher)).toBe(false);
});
it("should not filter a cipher if there are no restricted types", () => {
const cipher = createCipher({ type: CipherType.Login });
const filterFunction = createFilterFunction({}, []);
expect(filterFunction(cipher)).toBe(true);
});
});
});
function createCipher(options: Partial<CipherView> = {}) {

View File

@@ -1,19 +1,12 @@
import { Unassigned } from "@bitwarden/admin-console/common";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import {
isCipherViewRestricted,
RestrictedCipherType,
} from "@bitwarden/common/vault/services/restricted-item-types.service";
import { All, RoutedVaultFilterModel } from "./routed-vault-filter.model";
export type FilterFunction = (cipher: CipherView) => boolean;
export function createFilterFunction(
filter: RoutedVaultFilterModel,
restrictedTypes?: RestrictedCipherType[],
): FilterFunction {
export function createFilterFunction(filter: RoutedVaultFilterModel): FilterFunction {
return (cipher) => {
if (filter.type === "favorites" && !cipher.favorite) {
return false;
@@ -86,10 +79,7 @@ export function createFilterFunction(
) {
return false;
}
// Restricted types
if (restrictedTypes && isCipherViewRestricted(cipher, restrictedTypes)) {
return false;
}
return true;
};
}

View File

@@ -354,17 +354,26 @@ export class VaultComponent implements OnInit, OnDestroy {
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
const ciphers$ = combineLatest([
/**
* This observable filters the ciphers based on the active user ID and the restricted item types.
*/
const allowedCiphers$ = combineLatest([
this.cipherService.cipherViews$(activeUserId).pipe(filter((c) => c !== null)),
filter$,
this.currentSearchText$,
this.restrictedItemTypesService.restricted$,
]).pipe(
map(([ciphers, restrictedTypes]) =>
ciphers.filter(
(cipher) => !this.restrictedItemTypesService.isCipherRestricted(cipher, restrictedTypes),
),
),
);
const ciphers$ = combineLatest([allowedCiphers$, filter$, this.currentSearchText$]).pipe(
filter(([ciphers, filter]) => ciphers != undefined && filter != undefined),
concatMap(async ([ciphers, filter, searchText, restrictedTypes]) => {
concatMap(async ([ciphers, filter, searchText]) => {
const failedCiphers =
(await firstValueFrom(this.cipherService.failedToDecryptCiphers$(activeUserId))) ?? [];
const filterFunction = createFilterFunction(filter, restrictedTypes);
const filterFunction = createFilterFunction(filter);
// Append any failed to decrypt ciphers to the top of the cipher list
const allCiphers = [...failedCiphers, ...ciphers];