mirror of
https://github.com/bitwarden/browser
synced 2026-02-06 03:33:30 +00:00
feat(dirt): add saveApplicationReviewStatus$ to orchestrator
Implement method to save application review status and critical flags. Updates all applications where reviewedDate === null to set current date, and marks selected applications as critical. - Add saveApplicationReviewStatus$() method - Add _updateReviewStatusAndCriticalFlags() helper - Uses existing encryption and API update patterns - Single API call for both review status and critical flags - Follows same pattern as saveCriticalApplications$() Related to PM-27284
This commit is contained in:
@@ -350,6 +350,118 @@ export class RiskInsightsOrchestratorService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves review status for new applications and optionally marks selected ones as critical.
|
||||
* This method:
|
||||
* 1. Sets reviewedDate to current date for all applications where reviewedDate === null
|
||||
* 2. Sets isCritical = true for applications in the selectedCriticalApps array
|
||||
*
|
||||
* @param selectedCriticalApps Array of application names to mark as critical (can be empty)
|
||||
* @returns Observable of updated ReportState
|
||||
*/
|
||||
saveApplicationReviewStatus$(selectedCriticalApps: string[]): Observable<ReportState> {
|
||||
this.logService.info(
|
||||
"[RiskInsightsOrchestratorService] Saving application review status",
|
||||
{
|
||||
criticalAppsCount: selectedCriticalApps.length,
|
||||
},
|
||||
);
|
||||
|
||||
return this.rawReportData$.pipe(
|
||||
take(1),
|
||||
filter((data) => !data.loading && data.data != null),
|
||||
withLatestFrom(
|
||||
this.organizationDetails$.pipe(filter((org) => !!org && !!org.organizationId)),
|
||||
this._userId$.pipe(filter((userId) => !!userId)),
|
||||
),
|
||||
map(([reportState, organizationDetails, userId]) => {
|
||||
const existingApplicationData = reportState?.data?.applicationData || [];
|
||||
const updatedApplicationData = this._updateReviewStatusAndCriticalFlags(
|
||||
existingApplicationData,
|
||||
selectedCriticalApps,
|
||||
);
|
||||
|
||||
const updatedState = {
|
||||
...reportState,
|
||||
data: {
|
||||
...reportState.data,
|
||||
applicationData: updatedApplicationData,
|
||||
},
|
||||
} as ReportState;
|
||||
|
||||
this.logService.debug(
|
||||
"[RiskInsightsOrchestratorService] Updated review status",
|
||||
{
|
||||
totalApps: updatedApplicationData.length,
|
||||
reviewedApps: updatedApplicationData.filter((app) => app.reviewedDate !== null).length,
|
||||
criticalApps: updatedApplicationData.filter((app) => app.isCritical).length,
|
||||
},
|
||||
);
|
||||
|
||||
return { reportState, organizationDetails, updatedState, userId };
|
||||
}),
|
||||
switchMap(({ reportState, organizationDetails, updatedState, userId }) => {
|
||||
return from(
|
||||
this.riskInsightsEncryptionService.encryptRiskInsightsReport(
|
||||
{
|
||||
organizationId: organizationDetails!.organizationId,
|
||||
userId: userId!,
|
||||
},
|
||||
{
|
||||
reportData: reportState?.data?.reportData ?? [],
|
||||
summaryData: reportState?.data?.summaryData ?? createNewSummaryData(),
|
||||
applicationData: updatedState?.data?.applicationData ?? [],
|
||||
},
|
||||
reportState?.data?.contentEncryptionKey,
|
||||
),
|
||||
).pipe(
|
||||
map((encryptedData) => ({
|
||||
reportState,
|
||||
organizationDetails,
|
||||
updatedState,
|
||||
encryptedData,
|
||||
})),
|
||||
);
|
||||
}),
|
||||
switchMap(({ reportState, organizationDetails, updatedState, encryptedData }) => {
|
||||
this.logService.debug(
|
||||
`[RiskInsightsOrchestratorService] Persisting review status - report id: ${reportState?.data?.id}`,
|
||||
);
|
||||
|
||||
if (!reportState?.data?.id || !organizationDetails?.organizationId) {
|
||||
this.logService.warning(
|
||||
"[RiskInsightsOrchestratorService] Cannot save review status - missing report id or org id",
|
||||
);
|
||||
return of({ ...reportState });
|
||||
}
|
||||
|
||||
return this.reportApiService
|
||||
.updateRiskInsightsApplicationData$(
|
||||
reportState.data.id,
|
||||
organizationDetails.organizationId,
|
||||
{
|
||||
data: {
|
||||
applicationData: encryptedData.encryptedApplicationData.toSdk(),
|
||||
},
|
||||
},
|
||||
)
|
||||
.pipe(
|
||||
map(() => updatedState),
|
||||
tap((finalState) => {
|
||||
this._markUnmarkUpdatesSubject.next(finalState);
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.logService.error(
|
||||
"[RiskInsightsOrchestratorService] Failed to save review status",
|
||||
error,
|
||||
);
|
||||
return of({ ...reportState, error: "Failed to save application review status" });
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private _fetchReport$(organizationId: OrganizationId, userId: UserId): Observable<ReportState> {
|
||||
return this.reportService.getRiskInsightsReport$(organizationId, userId).pipe(
|
||||
tap(() => this.logService.debug("[RiskInsightsOrchestratorService] Fetching report")),
|
||||
@@ -501,6 +613,39 @@ export class RiskInsightsOrchestratorService {
|
||||
return updatedApps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates review status and critical flags for applications.
|
||||
* Sets reviewedDate for all apps with null reviewedDate.
|
||||
* Sets isCritical flag for apps in the criticalApplications array.
|
||||
*
|
||||
* @param existingApplications Current application data
|
||||
* @param criticalApplications Array of application names to mark as critical
|
||||
* @returns Updated application data with review dates and critical flags
|
||||
*/
|
||||
private _updateReviewStatusAndCriticalFlags(
|
||||
existingApplications: OrganizationReportApplication[],
|
||||
criticalApplications: string[],
|
||||
): OrganizationReportApplication[] {
|
||||
const criticalSet = new Set(criticalApplications);
|
||||
const currentDate = new Date();
|
||||
|
||||
return existingApplications.map((app) => {
|
||||
const shouldMarkCritical = criticalSet.has(app.applicationName);
|
||||
const needsReviewDate = app.reviewedDate === null;
|
||||
|
||||
// Only create new object if changes are needed
|
||||
if (needsReviewDate || shouldMarkCritical) {
|
||||
return {
|
||||
...app,
|
||||
reviewedDate: needsReviewDate ? currentDate : app.reviewedDate,
|
||||
isCritical: shouldMarkCritical || app.isCritical,
|
||||
};
|
||||
}
|
||||
|
||||
return app;
|
||||
});
|
||||
}
|
||||
|
||||
// Toggles the isCritical flag on applications via criticalApplicationName
|
||||
private _removeCriticalApplication(
|
||||
applicationData: OrganizationReportApplication[],
|
||||
|
||||
Reference in New Issue
Block a user