diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.spec.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.spec.ts index 19172d2e7fb..50051c39861 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.spec.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.spec.ts @@ -44,10 +44,10 @@ describe("RiskInsightsApiService", () => { expect(service).toBeTruthy(); }); - it("should call apiService.send with correct parameters and return the response for getRiskInsightsReport ", (done) => { + it("Get Report: should call apiService.send with correct parameters and return the response for getRiskInsightsReport ", (done) => { mockApiService.send.mockReturnValue(Promise.resolve(getRiskInsightsReportResponse)); - service.getRiskInsightsReport(orgId).subscribe((result) => { + service.getRiskInsightsReport$(orgId).subscribe((result) => { expect(result).toEqual(getRiskInsightsReportResponse); expect(mockApiService.send).toHaveBeenCalledWith( "GET", @@ -60,21 +60,21 @@ describe("RiskInsightsApiService", () => { }); }); - it("should return null if apiService.send rejects with 404 error for getRiskInsightsReport", (done) => { + it("Get Report: should return null if apiService.send rejects with 404 error for getRiskInsightsReport", (done) => { const error = { statusCode: 404 }; mockApiService.send.mockReturnValue(Promise.reject(error)); - service.getRiskInsightsReport(orgId).subscribe((result) => { + service.getRiskInsightsReport$(orgId).subscribe((result) => { expect(result).toBeNull(); done(); }); }); - it("should throw error if apiService.send rejects with non-404 error for getRiskInsightsReport", (done) => { + it("Get Report: should throw error if apiService.send rejects with non-404 error for getRiskInsightsReport", (done) => { const error = { statusCode: 500, message: "Server error" }; mockApiService.send.mockReturnValue(Promise.reject(error)); - service.getRiskInsightsReport(orgId).subscribe({ + service.getRiskInsightsReport$(orgId).subscribe({ next: () => { // Should not reach here fail("Expected error to be thrown"); @@ -95,10 +95,10 @@ describe("RiskInsightsApiService", () => { }); }); - it("should call apiService.send with correct parameters for saveRiskInsightsReport", (done) => { + it("Save Report: should call apiService.send with correct parameters for saveRiskInsightsReport", (done) => { mockApiService.send.mockReturnValue(Promise.resolve(saveRiskInsightsReportResponse)); - service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe((result) => { + service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe((result) => { expect(result).toEqual(saveRiskInsightsReportResponse); expect(mockApiService.send).toHaveBeenCalledWith( "POST", @@ -111,11 +111,11 @@ describe("RiskInsightsApiService", () => { }); }); - it("should propagate errors from apiService.send for saveRiskInsightsReport - 1", (done) => { + it("Save Report: should propagate errors from apiService.send for saveRiskInsightsReport - 1", (done) => { const error = { statusCode: 500, message: "Internal Server Error" }; mockApiService.send.mockReturnValue(Promise.reject(error)); - service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe({ + service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe({ next: () => { fail("Expected error to be thrown"); }, @@ -135,11 +135,11 @@ describe("RiskInsightsApiService", () => { }); }); - it("should propagate network errors from apiService.send for saveRiskInsightsReport - 2", (done) => { + it("Save Report: should propagate network errors from apiService.send for saveRiskInsightsReport - 2", (done) => { const error = new Error("Network error"); mockApiService.send.mockReturnValue(Promise.reject(error)); - service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe({ + service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe({ next: () => { fail("Expected error to be thrown"); }, @@ -159,14 +159,14 @@ describe("RiskInsightsApiService", () => { }); }); - it("should call apiService.send with correct parameters and return an Observable", (done) => { + it("Get Summary: should call apiService.send with correct parameters and return an Observable", (done) => { const minDate = new Date("2024-01-01"); const maxDate = new Date("2024-01-31"); const mockResponse: EncryptedDataModel[] = [{ encryptedData: "abc" } as EncryptedDataModel]; mockApiService.send.mockResolvedValueOnce(mockResponse); - service.getRiskInsightsSummary(orgId, minDate, maxDate).subscribe((result) => { + service.getRiskInsightsSummary$(orgId, minDate, maxDate).subscribe((result) => { expect(mockApiService.send).toHaveBeenCalledWith( "GET", `/reports/organizations/${orgId.toString()}/data/summary?startDate=${minDate.toISOString().split("T")[0]}&endDate=${maxDate.toISOString().split("T")[0]}`, @@ -179,13 +179,13 @@ describe("RiskInsightsApiService", () => { }); }); - it("should call apiService.send with correct parameters and return an Observable", (done) => { + it("Update Summary: should call apiService.send with correct parameters and return an Observable", (done) => { const data: EncryptedDataModel = { encryptedData: "xyz" } as EncryptedDataModel; const reportId = "report123" as OrganizationReportId; mockApiService.send.mockResolvedValueOnce(undefined); - service.updateRiskInsightsSummary(data, orgId, reportId).subscribe((result) => { + service.updateRiskInsightsSummary$(data, orgId, reportId).subscribe((result) => { expect(mockApiService.send).toHaveBeenCalledWith( "PATCH", `/reports/organizations/${orgId.toString()}/data/summary/${reportId.toString()}`, @@ -197,4 +197,44 @@ describe("RiskInsightsApiService", () => { done(); }); }); + + it("Get Applications: should call apiService.send with correct parameters and return an Observable", (done) => { + const reportId = "report123" as OrganizationReportId; + const mockResponse: EncryptedDataModel | null = { encryptedData: "abc" } as EncryptedDataModel; + + mockApiService.send.mockResolvedValueOnce(mockResponse); + + service.getRiskInsightsApplicationData$(orgId, reportId).subscribe((result) => { + expect(mockApiService.send).toHaveBeenCalledWith( + "GET", + `/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`, + null, + true, + true, + ); + expect(result).toEqual(mockResponse); + done(); + }); + }); + + it("Update Applications: should call apiService.send with correct parameters and return an Observable", (done) => { + const applicationData: EncryptedDataModel = { encryptedData: "xyz" } as EncryptedDataModel; + const reportId = "report123" as OrganizationReportId; + + mockApiService.send.mockResolvedValueOnce(undefined); + + service + .updateRiskInsightsApplicationData$(applicationData, orgId, reportId) + .subscribe((result) => { + expect(mockApiService.send).toHaveBeenCalledWith( + "PATCH", + `/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`, + applicationData, + true, + true, + ); + expect(result).toBeUndefined(); + done(); + }); + }); }); diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.ts index 6beef8d1401..29df485da03 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-api.service.ts @@ -13,7 +13,7 @@ import { export class RiskInsightsApiService { constructor(private apiService: ApiService) {} - getRiskInsightsReport(orgId: OrganizationId): Observable { + getRiskInsightsReport$(orgId: OrganizationId): Observable { const dbResponse = this.apiService .send("GET", `/reports/organizations/${orgId.toString()}/latest`, null, true, true) .catch((error: any): any => { @@ -26,7 +26,7 @@ export class RiskInsightsApiService { return from(dbResponse as Promise); } - saveRiskInsightsReport( + saveRiskInsightsReport$( request: SaveRiskInsightsReportRequest, organizationId: OrganizationId, ): Observable { @@ -41,7 +41,7 @@ export class RiskInsightsApiService { return from(dbResponse as Promise); } - getRiskInsightsSummary( + getRiskInsightsSummary$( orgId: string, minDate: Date, maxDate: Date, @@ -59,15 +59,46 @@ export class RiskInsightsApiService { return from(dbResponse as Promise); } - updateRiskInsightsSummary( - data: EncryptedDataModel, + updateRiskInsightsSummary$( + summaryData: EncryptedDataModel, organizationId: OrganizationId, reportId: OrganizationReportId, ): Observable { const dbResponse = this.apiService.send( "PATCH", `/reports/organizations/${organizationId.toString()}/data/summary/${reportId.toString()}`, - data, + summaryData, + true, + true, + ); + + return from(dbResponse as Promise); + } + + getRiskInsightsApplicationData$( + orgId: OrganizationId, + reportId: OrganizationReportId, + ): Observable { + const dbResponse = this.apiService.send( + "GET", + `/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`, + null, + true, + true, + ); + + return from(dbResponse as Promise); + } + + updateRiskInsightsApplicationData$( + applicationData: EncryptedDataModel, + orgId: OrganizationId, + reportId: OrganizationReportId, + ): Observable { + const dbResponse = this.apiService.send( + "PATCH", + `/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`, + applicationData, true, true, ); diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.spec.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.spec.ts index b066bc7c16c..1d090f52299 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.spec.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.spec.ts @@ -171,7 +171,7 @@ describe("RiskInsightsReportService", () => { ); const saveResponse = { id: "" }; // Simulating no ID in response - mockRiskInsightsApiService.saveRiskInsightsReport.mockReturnValue(of(saveResponse)); + mockRiskInsightsApiService.saveRiskInsightsReport$.mockReturnValue(of(saveResponse)); const reportSubjectSpy = jest.spyOn((service as any).riskInsightsReportSubject, "next"); const summarySubjectSpy = jest.spyOn((service as any).riskInsightsSummarySubject, "next"); @@ -202,9 +202,11 @@ describe("RiskInsightsReportService", () => { const organizationId = "orgId" as OrganizationId; const userId = "userId" as UserId; - mockRiskInsightsApiService.getRiskInsightsReport.mockReturnValue(of(apiResponse)); + mockRiskInsightsApiService.getRiskInsightsReport$.mockReturnValue(of(apiResponse)); service.getRiskInsightsReport(organizationId, userId); - expect(mockRiskInsightsApiService.getRiskInsightsReport).toHaveBeenCalledWith(organizationId); + expect(mockRiskInsightsApiService.getRiskInsightsReport$).toHaveBeenCalledWith( + organizationId, + ); expect(mockRiskInsightsEncryptionService.decryptRiskInsightsReport).toHaveBeenCalledWith( organizationId, userId, @@ -231,7 +233,7 @@ describe("RiskInsightsReportService", () => { const decryptedReport = { data: [{ foo: "bar" }], }; - mockRiskInsightsApiService.getRiskInsightsReport.mockReturnValue(of(mockResponse)); + mockRiskInsightsApiService.getRiskInsightsReport$.mockReturnValue(of(mockResponse)); mockRiskInsightsEncryptionService.decryptRiskInsightsReport.mockResolvedValue( decryptedReport, ); diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.ts index 23471327fe0..1d63d34762f 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/risk-insights-report.service.ts @@ -216,7 +216,7 @@ export class RiskInsightsReportService { getRiskInsightsReport(organizationId: OrganizationId, userId: UserId): void { this.riskInsightsApiService - .getRiskInsightsReport(organizationId) + .getRiskInsightsReport$(organizationId) .pipe( switchMap((response) => { if (!response) { @@ -275,7 +275,7 @@ export class RiskInsightsReportService { }; const response = await firstValueFrom( - this.riskInsightsApiService.saveRiskInsightsReport(saveRequest, organizationId), + this.riskInsightsApiService.saveRiskInsightsReport$(saveRequest, organizationId), ); if (response && response.id) {