Skip to content

Commit 43897df

Browse files
[PM-27287] Items in My Items should show in Inactive 2FA report (#17434)
1 parent 9afba33 commit 43897df

File tree

5 files changed

+56
-53
lines changed

5 files changed

+56
-53
lines changed

apps/web/src/app/dirt/reports/pages/cipher-report.component.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// FIXME: Update this file to be type safe and remove this and next line
2-
// @ts-strict-ignore
31
import { Directive, OnDestroy } from "@angular/core";
42
import {
53
BehaviorSubject,
@@ -36,24 +34,24 @@ import {
3634
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
3735

3836
@Directive()
39-
export class CipherReportComponent implements OnDestroy {
37+
export abstract class CipherReportComponent implements OnDestroy {
4038
isAdminConsoleActive = false;
4139

4240
loading = false;
4341
hasLoaded = false;
4442
ciphers: CipherView[] = [];
4543
allCiphers: CipherView[] = [];
4644
dataSource = new TableDataSource<CipherView>();
47-
organization: Organization;
48-
organizations: Organization[];
45+
organization: Organization | undefined = undefined;
46+
organizations: Organization[] = [];
4947
organizations$: Observable<Organization[]>;
5048

5149
filterStatus: any = [0];
5250
showFilterToggle: boolean = false;
5351
vaultMsg: string = "vault";
54-
currentFilterStatus: number | string;
52+
currentFilterStatus: number | string = 0;
5553
protected filterOrgStatus$ = new BehaviorSubject<number | string>(0);
56-
private destroyed$: Subject<void> = new Subject();
54+
protected destroyed$: Subject<void> = new Subject();
5755
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
5856

5957
constructor(
@@ -107,7 +105,7 @@ export class CipherReportComponent implements OnDestroy {
107105
if (filterId === 0) {
108106
cipherCount = this.allCiphers.length;
109107
} else if (filterId === 1) {
110-
cipherCount = this.allCiphers.filter((c) => c.organizationId === null).length;
108+
cipherCount = this.allCiphers.filter((c) => !c.organizationId).length;
111109
} else {
112110
this.organizations.filter((org: Organization) => {
113111
if (org.id === filterId) {
@@ -121,9 +119,9 @@ export class CipherReportComponent implements OnDestroy {
121119
}
122120

123121
async filterOrgToggle(status: any) {
124-
let filter = null;
122+
let filter = (c: CipherView) => true;
125123
if (typeof status === "number" && status === 1) {
126-
filter = (c: CipherView) => c.organizationId == null;
124+
filter = (c: CipherView) => !c.organizationId;
127125
} else if (typeof status === "string") {
128126
const orgId = status as OrganizationId;
129127
filter = (c: CipherView) => c.organizationId === orgId;
@@ -185,7 +183,7 @@ export class CipherReportComponent implements OnDestroy {
185183
cipher: CipherView,
186184
activeCollectionId?: CollectionId,
187185
) {
188-
const disableForm = cipher ? !cipher.edit && !this.organization.canEditAllCiphers : false;
186+
const disableForm = cipher ? !cipher.edit && !this.organization?.canEditAllCiphers : false;
189187

190188
this.vaultItemDialogRef = VaultItemDialogComponent.open(this.dialogService, {
191189
mode,
@@ -230,10 +228,11 @@ export class CipherReportComponent implements OnDestroy {
230228
let updatedCipher = await this.cipherService.get(cipher.id, activeUserId);
231229

232230
if (this.isAdminConsoleActive) {
233-
updatedCipher = await this.adminConsoleCipherFormConfigService.getCipher(
234-
cipher.id as CipherId,
235-
this.organization,
236-
);
231+
updatedCipher =
232+
(await this.adminConsoleCipherFormConfigService.getCipher(
233+
cipher.id as CipherId,
234+
this.organization!,
235+
)) ?? updatedCipher;
237236
}
238237

239238
// convert cipher to cipher view model

apps/web/src/app/dirt/reports/pages/exposed-passwords-report.component.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ describe("ExposedPasswordsReportComponent", () => {
9090
});
9191

9292
beforeEach(() => {
93+
jest.clearAllMocks();
9394
fixture = TestBed.createComponent(ExposedPasswordsReportComponent);
9495
component = fixture.componentInstance;
9596
fixture.detectChanges();

apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.spec.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
12
import { ComponentFixture, TestBed } from "@angular/core/testing";
23
import { MockProxy, mock } from "jest-mock-extended";
34
import { of } from "rxjs";
@@ -29,14 +30,13 @@ describe("InactiveTwoFactorReportComponent", () => {
2930
const userId = Utils.newGuid() as UserId;
3031
const accountService: FakeAccountService = mockAccountServiceWith(userId);
3132

32-
beforeEach(() => {
33+
beforeEach(async () => {
3334
let cipherFormConfigServiceMock: MockProxy<CipherFormConfigService>;
3435
organizationService = mock<OrganizationService>();
3536
organizationService.organizations$.mockReturnValue(of([]));
3637
syncServiceMock = mock<SyncService>();
37-
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
38-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
39-
TestBed.configureTestingModule({
38+
39+
await TestBed.configureTestingModule({
4040
declarations: [InactiveTwoFactorReportComponent, I18nPipe],
4141
providers: [
4242
{
@@ -80,9 +80,7 @@ describe("InactiveTwoFactorReportComponent", () => {
8080
useValue: adminConsoleCipherFormConfigServiceMock,
8181
},
8282
],
83-
schemas: [],
84-
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
85-
errorOnUnknownElements: false,
83+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
8684
}).compileComponents();
8785
});
8886

apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// FIXME: Update this file to be type safe and remove this and next line
2-
// @ts-strict-ignore
3-
import { Component, OnInit } from "@angular/core";
1+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from "@angular/core";
42

53
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
64
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
@@ -19,9 +17,8 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se
1917

2018
import { CipherReportComponent } from "./cipher-report.component";
2119

22-
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
23-
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
2420
@Component({
21+
changeDetection: ChangeDetectionStrategy.OnPush,
2522
selector: "app-inactive-two-factor-report",
2623
templateUrl: "inactive-two-factor-report.component.html",
2724
standalone: false,
@@ -42,6 +39,7 @@ export class InactiveTwoFactorReportComponent extends CipherReportComponent impl
4239
syncService: SyncService,
4340
cipherFormConfigService: CipherFormConfigService,
4441
adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
42+
protected changeDetectorRef: ChangeDetectorRef,
4543
) {
4644
super(
4745
cipherService,
@@ -86,6 +84,7 @@ export class InactiveTwoFactorReportComponent extends CipherReportComponent impl
8684

8785
this.filterCiphersByOrg(inactive2faCiphers);
8886
this.cipherDocs = docs;
87+
this.changeDetectorRef.markForCheck();
8988
}
9089
}
9190

@@ -157,6 +156,7 @@ export class InactiveTwoFactorReportComponent extends CipherReportComponent impl
157156
}
158157
this.services.set(serviceData.domain, serviceData.documentation);
159158
}
159+
this.changeDetectorRef.markForCheck();
160160
}
161161

162162
/**

apps/web/src/app/dirt/reports/pages/organizations/inactive-two-factor-report.component.ts

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
// FIXME: Update this file to be type safe and remove this and next line
2-
// @ts-strict-ignore
3-
import { Component, OnInit } from "@angular/core";
1+
import { ChangeDetectorRef, Component, OnInit, ChangeDetectionStrategy } from "@angular/core";
42
import { ActivatedRoute } from "@angular/router";
5-
import { firstValueFrom, map } from "rxjs";
3+
import { firstValueFrom, map, takeUntil } from "rxjs";
64

7-
import {
8-
getOrganizationById,
9-
OrganizationService,
10-
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
5+
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
116
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
127
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
138
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
9+
import { getById } from "@bitwarden/common/platform/misc";
1410
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
1511
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
1612
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
@@ -23,9 +19,8 @@ import { RoutedVaultFilterService } from "../../../../vault/individual-vault/vau
2319
import { AdminConsoleCipherFormConfigService } from "../../../../vault/org-vault/services/admin-console-cipher-form-config.service";
2420
import { InactiveTwoFactorReportComponent as BaseInactiveTwoFactorReportComponent } from "../inactive-two-factor-report.component";
2521

26-
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
27-
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
2822
@Component({
23+
changeDetection: ChangeDetectionStrategy.OnPush,
2924
selector: "app-inactive-two-factor-report",
3025
templateUrl: "../inactive-two-factor-report.component.html",
3126
providers: [
@@ -44,7 +39,7 @@ export class InactiveTwoFactorReportComponent
4439
implements OnInit
4540
{
4641
// Contains a list of ciphers, the user running the report, can manage
47-
private manageableCiphers: Cipher[];
42+
private manageableCiphers: Cipher[] = [];
4843

4944
constructor(
5045
cipherService: CipherService,
@@ -58,6 +53,7 @@ export class InactiveTwoFactorReportComponent
5853
syncService: SyncService,
5954
cipherFormConfigService: CipherFormConfigService,
6055
adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
56+
protected changeDetectorRef: ChangeDetectorRef,
6157
) {
6258
super(
6359
cipherService,
@@ -70,28 +66,37 @@ export class InactiveTwoFactorReportComponent
7066
syncService,
7167
cipherFormConfigService,
7268
adminConsoleCipherFormConfigService,
69+
changeDetectorRef,
7370
);
7471
}
7572

7673
async ngOnInit() {
7774
this.isAdminConsoleActive = true;
78-
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
79-
this.route.parent.parent.params.subscribe(async (params) => {
80-
const userId = await firstValueFrom(
81-
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
82-
);
83-
this.organization = await firstValueFrom(
84-
this.organizationService
85-
.organizations$(userId)
86-
.pipe(getOrganizationById(params.organizationId)),
87-
);
88-
this.manageableCiphers = await this.cipherService.getAll(userId);
89-
await super.ngOnInit();
90-
});
75+
76+
this.route.parent?.parent?.params
77+
?.pipe(takeUntil(this.destroyed$))
78+
// eslint-disable-next-line rxjs/no-async-subscribe
79+
.subscribe(async (params) => {
80+
const userId = await firstValueFrom(
81+
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
82+
);
83+
84+
if (userId) {
85+
this.organization = await firstValueFrom(
86+
this.organizationService.organizations$(userId).pipe(getById(params.organizationId)),
87+
);
88+
this.manageableCiphers = await this.cipherService.getAll(userId);
89+
await super.ngOnInit();
90+
}
91+
this.changeDetectorRef.markForCheck();
92+
});
9193
}
9294

93-
getAllCiphers(): Promise<CipherView[]> {
94-
return this.cipherService.getAllFromApiForOrganization(this.organization.id);
95+
async getAllCiphers(): Promise<CipherView[]> {
96+
if (this.organization) {
97+
return await this.cipherService.getAllFromApiForOrganization(this.organization.id, true);
98+
}
99+
return [];
95100
}
96101

97102
protected canManageCipher(c: CipherView): boolean {

0 commit comments

Comments
 (0)