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

[PM-15498] - add risk insight data service (#12361)

* Adding more test cases

* Removing unnecessary file

* Test cases update

* Adding the fixme for strict types

* moving the fixme

* add risk insight data service and wire up components to it

* hook up all applications to risk insights report service. add loading state

* link up remaining props to risk insight report

* wire up children to risk insight data service

* add missing copy. remove loading state from risk insights

* fix types

* fix DI issue

* remove @Injectable from RiskInsightsDataService

---------

Co-authored-by: Tom <ttalty@bitwarden.com>
Co-authored-by: Tom <144813356+ttalty@users.noreply.github.com>
This commit is contained in:
Jordan Aasen
2024-12-18 10:03:15 -08:00
committed by GitHub
parent fc37d6df6b
commit da9e12dae6
13 changed files with 303 additions and 152 deletions

View File

@@ -25,7 +25,7 @@ export type ApplicationHealthReportDetail = {
passwordCount: number;
atRiskPasswordCount: number;
memberCount: number;
atRiskMemberCount: number;
memberDetails: MemberDetailsFlat[];
atRiskMemberDetails: MemberDetailsFlat[];
};

View File

@@ -1,3 +1,4 @@
export * from "./member-cipher-details-api.service";
export * from "./password-health.service";
export * from "./risk-insights-report.service";
export * from "./risk-insights-data.service";

View File

@@ -0,0 +1,60 @@
import { BehaviorSubject } from "rxjs";
import { finalize } from "rxjs/operators";
import { ApplicationHealthReportDetail } from "../models/password-health";
import { RiskInsightsReportService } from "./risk-insights-report.service";
export class RiskInsightsDataService {
private applicationsSubject = new BehaviorSubject<ApplicationHealthReportDetail[] | null>(null);
applications$ = this.applicationsSubject.asObservable();
private isLoadingSubject = new BehaviorSubject<boolean>(false);
isLoading$ = this.isLoadingSubject.asObservable();
private isRefreshingSubject = new BehaviorSubject<boolean>(false);
isRefreshing$ = this.isRefreshingSubject.asObservable();
private errorSubject = new BehaviorSubject<string | null>(null);
error$ = this.errorSubject.asObservable();
private dataLastUpdatedSubject = new BehaviorSubject<Date | null>(null);
dataLastUpdated$ = this.dataLastUpdatedSubject.asObservable();
constructor(private reportService: RiskInsightsReportService) {}
/**
* Fetches the applications report and updates the applicationsSubject.
* @param organizationId The ID of the organization.
*/
fetchApplicationsReport(organizationId: string, isRefresh?: boolean): void {
if (isRefresh) {
this.isRefreshingSubject.next(true);
} else {
this.isLoadingSubject.next(true);
}
this.reportService
.generateApplicationsReport$(organizationId)
.pipe(
finalize(() => {
this.isLoadingSubject.next(false);
this.isRefreshingSubject.next(false);
this.dataLastUpdatedSubject.next(new Date());
}),
)
.subscribe({
next: (reports: ApplicationHealthReportDetail[]) => {
this.applicationsSubject.next(reports);
this.errorSubject.next(null);
},
error: () => {
this.applicationsSubject.next([]);
},
});
}
refreshApplicationsReport(organizationId: string): void {
this.fetchApplicationsReport(organizationId, true);
}
}

View File

@@ -287,6 +287,7 @@ export class RiskInsightsReportService {
: newUriDetail.cipherMembers,
atRiskMemberDetails: existingUriDetail ? existingUriDetail.atRiskMemberDetails : [],
atRiskPasswordCount: existingUriDetail ? existingUriDetail.atRiskPasswordCount : 0,
atRiskMemberCount: existingUriDetail ? existingUriDetail.atRiskMemberDetails.length : 0,
} as ApplicationHealthReportDetail;
if (isAtRisk) {