diff --git a/apps/web/src/app/dirt/reports/pages/organizations/exposed-passwords-report.component.ts b/apps/web/src/app/dirt/reports/pages/organizations/exposed-passwords-report.component.ts index 90e21292f3e..c4e0b8f874c 100644 --- a/apps/web/src/app/dirt/reports/pages/organizations/exposed-passwords-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/organizations/exposed-passwords-report.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { firstValueFrom, takeUntil, tap } from "rxjs"; +import { CollectionService } from "@bitwarden/admin-console/common"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; @@ -10,8 +11,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { getById } from "@bitwarden/common/platform/misc"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLikeUtils } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { BerryComponent, ChipFilterComponent, DialogService } from "@bitwarden/components"; import { PasswordRepromptService, @@ -54,7 +55,8 @@ export class ExposedPasswordsReportComponent extends BaseExposedPasswordsReportComponent implements OnInit { - private manageableCiphers: Cipher[] = []; + private manageableCipherIds = new Set(); + private sharedCollectionIds = new Set(); constructor( cipherService: CipherService, @@ -68,6 +70,7 @@ export class ExposedPasswordsReportComponent syncService: SyncService, cipherFormService: CipherFormConfigService, adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService, + private collectionService: CollectionService, ) { super( cipherService, @@ -92,7 +95,17 @@ export class ExposedPasswordsReportComponent this.organization = await firstValueFrom( this.organizationService.organizations$(userId).pipe(getById(params.organizationId)), ); - this.manageableCiphers = await this.cipherService.getAll(userId); + const manageableCiphers = await this.cipherService.getAll(userId); + this.manageableCipherIds = new Set(manageableCiphers.map((c) => c.id)); + const collections = await firstValueFrom( + this.collectionService.decryptedCollections$(userId), + ); + this.sharedCollectionIds = new Set( + collections + .filter((c) => !c.isDefaultCollection && c.organizationId === this.organization?.id) + .map((c) => c.id as string), + ); + await super.ngOnInit(); }), takeUntil(this.destroyed$), ) @@ -107,12 +120,15 @@ export class ExposedPasswordsReportComponent } canManageCipher(c: CipherView): boolean { - if (c.collectionIds.length === 0) { - return true; + if ( + CipherViewLikeUtils.isUnassigned(c) || + !c.collectionIds?.some((id) => this.sharedCollectionIds.has(id)) + ) { + return false; } if (this.organization?.allowAdminAccessToAllCollectionItems) { return true; } - return this.manageableCiphers.some((x) => x.id === c.id); + return this.manageableCipherIds.has(c.id); } } diff --git a/apps/web/src/app/dirt/reports/pages/organizations/inactive-two-factor-report.component.ts b/apps/web/src/app/dirt/reports/pages/organizations/inactive-two-factor-report.component.ts index ad80dffc43c..b1ee7a2d1dd 100644 --- a/apps/web/src/app/dirt/reports/pages/organizations/inactive-two-factor-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/organizations/inactive-two-factor-report.component.ts @@ -4,6 +4,7 @@ import { ChangeDetectorRef, Component, OnInit, ChangeDetectionStrategy } from "@ import { ActivatedRoute } from "@angular/router"; import { firstValueFrom, takeUntil, tap } from "rxjs"; +import { CollectionService } from "@bitwarden/admin-console/common"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; @@ -12,8 +13,8 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { getById } from "@bitwarden/common/platform/misc"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLikeUtils } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { BerryComponent, ChipActionComponent, @@ -61,8 +62,8 @@ export class InactiveTwoFactorReportComponent extends BaseInactiveTwoFactorReportComponent implements OnInit { - // Contains a list of ciphers, the user running the report, can manage - private manageableCiphers: Cipher[] = []; + private manageableCipherIds = new Set(); + private sharedCollectionIds = new Set(); constructor( cipherService: CipherService, @@ -77,6 +78,7 @@ export class InactiveTwoFactorReportComponent cipherFormConfigService: CipherFormConfigService, adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService, protected changeDetectorRef: ChangeDetectorRef, + private collectionService: CollectionService, ) { super( cipherService, @@ -103,7 +105,16 @@ export class InactiveTwoFactorReportComponent this.organization = await firstValueFrom( this.organizationService.organizations$(userId).pipe(getById(params.organizationId)), ); - this.manageableCiphers = await this.cipherService.getAll(userId); + const manageableCiphers = await this.cipherService.getAll(userId); + this.manageableCipherIds = new Set(manageableCiphers.map((c) => c.id)); + const collections = await firstValueFrom( + this.collectionService.decryptedCollections$(userId), + ); + this.sharedCollectionIds = new Set( + collections + .filter((c) => !c.isDefaultCollection && c.organizationId === this.organization?.id) + .map((c) => c.id as string), + ); await super.ngOnInit(); this.changeDetectorRef.markForCheck(); }), @@ -120,12 +131,15 @@ export class InactiveTwoFactorReportComponent } protected canManageCipher(c: CipherView): boolean { - if (c.collectionIds.length === 0) { - return true; + if ( + CipherViewLikeUtils.isUnassigned(c) || + !c.collectionIds?.some((id) => this.sharedCollectionIds.has(id)) + ) { + return false; } if (this.organization?.allowAdminAccessToAllCollectionItems) { return true; } - return this.manageableCiphers.some((x) => x.id === c.id); + return this.manageableCipherIds.has(c.id); } } diff --git a/apps/web/src/app/dirt/reports/pages/organizations/reused-passwords-report.component.ts b/apps/web/src/app/dirt/reports/pages/organizations/reused-passwords-report.component.ts index 5dbaff9057d..efc73a43102 100644 --- a/apps/web/src/app/dirt/reports/pages/organizations/reused-passwords-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/organizations/reused-passwords-report.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { firstValueFrom, takeUntil, tap } from "rxjs"; +import { CollectionService } from "@bitwarden/admin-console/common"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; @@ -9,8 +10,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { getById } from "@bitwarden/common/platform/misc"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLikeUtils } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { BerryComponent, ChipFilterComponent, DialogService } from "@bitwarden/components"; import { CipherFormConfigService, @@ -53,7 +54,8 @@ export class ReusedPasswordsReportComponent extends BaseReusedPasswordsReportComponent implements OnInit { - manageableCiphers: Cipher[] = []; + private manageableCipherIds = new Set(); + private sharedCollectionIds = new Set(); constructor( cipherService: CipherService, @@ -66,6 +68,7 @@ export class ReusedPasswordsReportComponent syncService: SyncService, cipherFormConfigService: CipherFormConfigService, adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService, + private collectionService: CollectionService, ) { super( cipherService, @@ -90,7 +93,16 @@ export class ReusedPasswordsReportComponent this.organization = await firstValueFrom( this.organizationService.organizations$(userId).pipe(getById(params.organizationId)), ); - this.manageableCiphers = await this.cipherService.getAll(userId); + const manageableCiphers = await this.cipherService.getAll(userId); + this.manageableCipherIds = new Set(manageableCiphers.map((c) => c.id)); + const collections = await firstValueFrom( + this.collectionService.decryptedCollections$(userId), + ); + this.sharedCollectionIds = new Set( + collections + .filter((c) => !c.isDefaultCollection && c.organizationId === this.organization?.id) + .map((c) => c.id as string), + ); await super.ngOnInit(); }), takeUntil(this.destroyed$), @@ -106,12 +118,15 @@ export class ReusedPasswordsReportComponent } canManageCipher(c: CipherView): boolean { - if (c.collectionIds.length === 0) { - return true; + if ( + CipherViewLikeUtils.isUnassigned(c) || + !c.collectionIds?.some((id) => this.sharedCollectionIds.has(id)) + ) { + return false; } if (this.organization?.allowAdminAccessToAllCollectionItems) { return true; } - return this.manageableCiphers.some((x) => x.id === c.id); + return this.manageableCipherIds.has(c.id); } } diff --git a/apps/web/src/app/dirt/reports/pages/organizations/unsecured-websites-report.component.ts b/apps/web/src/app/dirt/reports/pages/organizations/unsecured-websites-report.component.ts index 984b0138304..a40a3d1951e 100644 --- a/apps/web/src/app/dirt/reports/pages/organizations/unsecured-websites-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/organizations/unsecured-websites-report.component.ts @@ -10,8 +10,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { getById } from "@bitwarden/common/platform/misc"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLikeUtils } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { BerryComponent, ChipFilterComponent, DialogService } from "@bitwarden/components"; import { CipherFormConfigService, @@ -54,8 +54,8 @@ export class UnsecuredWebsitesReportComponent extends BaseUnsecuredWebsitesReportComponent implements OnInit { - // Contains a list of ciphers, the user running the report, can manage - private manageableCiphers: Cipher[] = []; + private manageableCipherIds = new Set(); + private sharedCollectionIds = new Set(); constructor( cipherService: CipherService, @@ -93,7 +93,16 @@ export class UnsecuredWebsitesReportComponent this.organization = await firstValueFrom( this.organizationService.organizations$(userId).pipe(getById(params.organizationId)), ); - this.manageableCiphers = await this.cipherService.getAll(userId); + const manageableCiphers = await this.cipherService.getAll(userId); + this.manageableCipherIds = new Set(manageableCiphers.map((c) => c.id)); + const collections = await firstValueFrom( + this.collectionService.decryptedCollections$(userId), + ); + this.sharedCollectionIds = new Set( + collections + .filter((c) => !c.isDefaultCollection && c.organizationId === this.organization?.id) + .map((c) => c.id as string), + ); await super.ngOnInit(); }), takeUntil(this.destroyed$), @@ -109,12 +118,15 @@ export class UnsecuredWebsitesReportComponent } protected canManageCipher(c: CipherView): boolean { - if (c.collectionIds.length === 0) { - return true; + if ( + CipherViewLikeUtils.isUnassigned(c) || + !c.collectionIds?.some((id) => this.sharedCollectionIds.has(id)) + ) { + return false; } if (this.organization?.allowAdminAccessToAllCollectionItems) { return true; } - return this.manageableCiphers.some((x) => x.id === c.id); + return this.manageableCipherIds.has(c.id); } } diff --git a/apps/web/src/app/dirt/reports/pages/organizations/weak-passwords-report.component.ts b/apps/web/src/app/dirt/reports/pages/organizations/weak-passwords-report.component.ts index e9a3ee0740a..7ede41ab1f8 100644 --- a/apps/web/src/app/dirt/reports/pages/organizations/weak-passwords-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/organizations/weak-passwords-report.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { firstValueFrom, takeUntil, tap } from "rxjs"; +import { CollectionService } from "@bitwarden/admin-console/common"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; @@ -10,8 +11,8 @@ import { getById } from "@bitwarden/common/platform/misc"; import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; -import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLikeUtils } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { BerryComponent, ChipFilterComponent, DialogService } from "@bitwarden/components"; import { CipherFormConfigService, @@ -54,7 +55,8 @@ export class WeakPasswordsReportComponent extends BaseWeakPasswordsReportComponent implements OnInit { - private manageableCiphers: Cipher[] = []; + private manageableCipherIds = new Set(); + private sharedCollectionIds = new Set(); constructor( cipherService: CipherService, @@ -68,6 +70,7 @@ export class WeakPasswordsReportComponent cipherFormConfigService: CipherFormConfigService, protected accountService: AccountService, adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService, + private collectionService: CollectionService, ) { super( cipherService, @@ -92,7 +95,16 @@ export class WeakPasswordsReportComponent this.organization = await firstValueFrom( this.organizationService.organizations$(userId).pipe(getById(params.organizationId)), ); - this.manageableCiphers = await this.cipherService.getAll(userId); + const manageableCiphers = await this.cipherService.getAll(userId); + this.manageableCipherIds = new Set(manageableCiphers.map((c) => c.id)); + const collections = await firstValueFrom( + this.collectionService.decryptedCollections$(userId), + ); + this.sharedCollectionIds = new Set( + collections + .filter((c) => !c.isDefaultCollection && c.organizationId === this.organization?.id) + .map((c) => c.id as string), + ); await super.ngOnInit(); }), takeUntil(this.destroyed$), @@ -108,12 +120,15 @@ export class WeakPasswordsReportComponent } canManageCipher(c: CipherView): boolean { - if (c.collectionIds.length === 0) { - return true; + if ( + CipherViewLikeUtils.isUnassigned(c) || + !c.collectionIds?.some((id) => this.sharedCollectionIds.has(id)) + ) { + return false; } if (this.organization?.allowAdminAccessToAllCollectionItems) { return true; } - return this.manageableCiphers.some((x) => x.id === c.id); + return this.manageableCipherIds.has(c.id); } } diff --git a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.ts b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.ts index 4a2c0677574..5ce3609b001 100644 --- a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.ts +++ b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.ts @@ -34,7 +34,7 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl passwordRepromptService: PasswordRepromptService, i18nService: I18nService, syncService: SyncService, - private collectionService: CollectionService, + protected collectionService: CollectionService, cipherFormConfigService: CipherFormConfigService, adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService, ) {