1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 13:53:34 +00:00

[PM- 25678] Applications api endpoints (#16387)

* Adding the applications api endpoints and test cases

* Changing observable names
This commit is contained in:
Tom
2025-09-12 10:09:12 -04:00
committed by GitHub
parent 7ac75a6c52
commit f20ed9f0e9
4 changed files with 101 additions and 28 deletions

View File

@@ -44,10 +44,10 @@ describe("RiskInsightsApiService", () => {
expect(service).toBeTruthy(); 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)); mockApiService.send.mockReturnValue(Promise.resolve(getRiskInsightsReportResponse));
service.getRiskInsightsReport(orgId).subscribe((result) => { service.getRiskInsightsReport$(orgId).subscribe((result) => {
expect(result).toEqual(getRiskInsightsReportResponse); expect(result).toEqual(getRiskInsightsReportResponse);
expect(mockApiService.send).toHaveBeenCalledWith( expect(mockApiService.send).toHaveBeenCalledWith(
"GET", "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 }; const error = { statusCode: 404 };
mockApiService.send.mockReturnValue(Promise.reject(error)); mockApiService.send.mockReturnValue(Promise.reject(error));
service.getRiskInsightsReport(orgId).subscribe((result) => { service.getRiskInsightsReport$(orgId).subscribe((result) => {
expect(result).toBeNull(); expect(result).toBeNull();
done(); 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" }; const error = { statusCode: 500, message: "Server error" };
mockApiService.send.mockReturnValue(Promise.reject(error)); mockApiService.send.mockReturnValue(Promise.reject(error));
service.getRiskInsightsReport(orgId).subscribe({ service.getRiskInsightsReport$(orgId).subscribe({
next: () => { next: () => {
// Should not reach here // Should not reach here
fail("Expected error to be thrown"); 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)); mockApiService.send.mockReturnValue(Promise.resolve(saveRiskInsightsReportResponse));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe((result) => { service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe((result) => {
expect(result).toEqual(saveRiskInsightsReportResponse); expect(result).toEqual(saveRiskInsightsReportResponse);
expect(mockApiService.send).toHaveBeenCalledWith( expect(mockApiService.send).toHaveBeenCalledWith(
"POST", "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" }; const error = { statusCode: 500, message: "Internal Server Error" };
mockApiService.send.mockReturnValue(Promise.reject(error)); mockApiService.send.mockReturnValue(Promise.reject(error));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe({ service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe({
next: () => { next: () => {
fail("Expected error to be thrown"); 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"); const error = new Error("Network error");
mockApiService.send.mockReturnValue(Promise.reject(error)); mockApiService.send.mockReturnValue(Promise.reject(error));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest, orgId).subscribe({ service.saveRiskInsightsReport$(saveRiskInsightsReportRequest, orgId).subscribe({
next: () => { next: () => {
fail("Expected error to be thrown"); 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 minDate = new Date("2024-01-01");
const maxDate = new Date("2024-01-31"); const maxDate = new Date("2024-01-31");
const mockResponse: EncryptedDataModel[] = [{ encryptedData: "abc" } as EncryptedDataModel]; const mockResponse: EncryptedDataModel[] = [{ encryptedData: "abc" } as EncryptedDataModel];
mockApiService.send.mockResolvedValueOnce(mockResponse); mockApiService.send.mockResolvedValueOnce(mockResponse);
service.getRiskInsightsSummary(orgId, minDate, maxDate).subscribe((result) => { service.getRiskInsightsSummary$(orgId, minDate, maxDate).subscribe((result) => {
expect(mockApiService.send).toHaveBeenCalledWith( expect(mockApiService.send).toHaveBeenCalledWith(
"GET", "GET",
`/reports/organizations/${orgId.toString()}/data/summary?startDate=${minDate.toISOString().split("T")[0]}&endDate=${maxDate.toISOString().split("T")[0]}`, `/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 data: EncryptedDataModel = { encryptedData: "xyz" } as EncryptedDataModel;
const reportId = "report123" as OrganizationReportId; const reportId = "report123" as OrganizationReportId;
mockApiService.send.mockResolvedValueOnce(undefined); mockApiService.send.mockResolvedValueOnce(undefined);
service.updateRiskInsightsSummary(data, orgId, reportId).subscribe((result) => { service.updateRiskInsightsSummary$(data, orgId, reportId).subscribe((result) => {
expect(mockApiService.send).toHaveBeenCalledWith( expect(mockApiService.send).toHaveBeenCalledWith(
"PATCH", "PATCH",
`/reports/organizations/${orgId.toString()}/data/summary/${reportId.toString()}`, `/reports/organizations/${orgId.toString()}/data/summary/${reportId.toString()}`,
@@ -197,4 +197,44 @@ describe("RiskInsightsApiService", () => {
done(); 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();
});
});
}); });

View File

@@ -13,7 +13,7 @@ import {
export class RiskInsightsApiService { export class RiskInsightsApiService {
constructor(private apiService: ApiService) {} constructor(private apiService: ApiService) {}
getRiskInsightsReport(orgId: OrganizationId): Observable<GetRiskInsightsReportResponse | null> { getRiskInsightsReport$(orgId: OrganizationId): Observable<GetRiskInsightsReportResponse | null> {
const dbResponse = this.apiService const dbResponse = this.apiService
.send("GET", `/reports/organizations/${orgId.toString()}/latest`, null, true, true) .send("GET", `/reports/organizations/${orgId.toString()}/latest`, null, true, true)
.catch((error: any): any => { .catch((error: any): any => {
@@ -26,7 +26,7 @@ export class RiskInsightsApiService {
return from(dbResponse as Promise<GetRiskInsightsReportResponse>); return from(dbResponse as Promise<GetRiskInsightsReportResponse>);
} }
saveRiskInsightsReport( saveRiskInsightsReport$(
request: SaveRiskInsightsReportRequest, request: SaveRiskInsightsReportRequest,
organizationId: OrganizationId, organizationId: OrganizationId,
): Observable<SaveRiskInsightsReportResponse> { ): Observable<SaveRiskInsightsReportResponse> {
@@ -41,7 +41,7 @@ export class RiskInsightsApiService {
return from(dbResponse as Promise<SaveRiskInsightsReportResponse>); return from(dbResponse as Promise<SaveRiskInsightsReportResponse>);
} }
getRiskInsightsSummary( getRiskInsightsSummary$(
orgId: string, orgId: string,
minDate: Date, minDate: Date,
maxDate: Date, maxDate: Date,
@@ -59,15 +59,46 @@ export class RiskInsightsApiService {
return from(dbResponse as Promise<EncryptedDataModel[]>); return from(dbResponse as Promise<EncryptedDataModel[]>);
} }
updateRiskInsightsSummary( updateRiskInsightsSummary$(
data: EncryptedDataModel, summaryData: EncryptedDataModel,
organizationId: OrganizationId, organizationId: OrganizationId,
reportId: OrganizationReportId, reportId: OrganizationReportId,
): Observable<void> { ): Observable<void> {
const dbResponse = this.apiService.send( const dbResponse = this.apiService.send(
"PATCH", "PATCH",
`/reports/organizations/${organizationId.toString()}/data/summary/${reportId.toString()}`, `/reports/organizations/${organizationId.toString()}/data/summary/${reportId.toString()}`,
data, summaryData,
true,
true,
);
return from(dbResponse as Promise<void>);
}
getRiskInsightsApplicationData$(
orgId: OrganizationId,
reportId: OrganizationReportId,
): Observable<EncryptedDataModel | null> {
const dbResponse = this.apiService.send(
"GET",
`/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`,
null,
true,
true,
);
return from(dbResponse as Promise<EncryptedDataModel | null>);
}
updateRiskInsightsApplicationData$(
applicationData: EncryptedDataModel,
orgId: OrganizationId,
reportId: OrganizationReportId,
): Observable<void> {
const dbResponse = this.apiService.send(
"PATCH",
`/reports/organizations/${orgId.toString()}/data/application/${reportId.toString()}`,
applicationData,
true, true,
true, true,
); );

View File

@@ -171,7 +171,7 @@ describe("RiskInsightsReportService", () => {
); );
const saveResponse = { id: "" }; // Simulating no ID in response 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 reportSubjectSpy = jest.spyOn((service as any).riskInsightsReportSubject, "next");
const summarySubjectSpy = jest.spyOn((service as any).riskInsightsSummarySubject, "next"); const summarySubjectSpy = jest.spyOn((service as any).riskInsightsSummarySubject, "next");
@@ -202,9 +202,11 @@ describe("RiskInsightsReportService", () => {
const organizationId = "orgId" as OrganizationId; const organizationId = "orgId" as OrganizationId;
const userId = "userId" as UserId; const userId = "userId" as UserId;
mockRiskInsightsApiService.getRiskInsightsReport.mockReturnValue(of(apiResponse)); mockRiskInsightsApiService.getRiskInsightsReport$.mockReturnValue(of(apiResponse));
service.getRiskInsightsReport(organizationId, userId); service.getRiskInsightsReport(organizationId, userId);
expect(mockRiskInsightsApiService.getRiskInsightsReport).toHaveBeenCalledWith(organizationId); expect(mockRiskInsightsApiService.getRiskInsightsReport$).toHaveBeenCalledWith(
organizationId,
);
expect(mockRiskInsightsEncryptionService.decryptRiskInsightsReport).toHaveBeenCalledWith( expect(mockRiskInsightsEncryptionService.decryptRiskInsightsReport).toHaveBeenCalledWith(
organizationId, organizationId,
userId, userId,
@@ -231,7 +233,7 @@ describe("RiskInsightsReportService", () => {
const decryptedReport = { const decryptedReport = {
data: [{ foo: "bar" }], data: [{ foo: "bar" }],
}; };
mockRiskInsightsApiService.getRiskInsightsReport.mockReturnValue(of(mockResponse)); mockRiskInsightsApiService.getRiskInsightsReport$.mockReturnValue(of(mockResponse));
mockRiskInsightsEncryptionService.decryptRiskInsightsReport.mockResolvedValue( mockRiskInsightsEncryptionService.decryptRiskInsightsReport.mockResolvedValue(
decryptedReport, decryptedReport,
); );

View File

@@ -216,7 +216,7 @@ export class RiskInsightsReportService {
getRiskInsightsReport(organizationId: OrganizationId, userId: UserId): void { getRiskInsightsReport(organizationId: OrganizationId, userId: UserId): void {
this.riskInsightsApiService this.riskInsightsApiService
.getRiskInsightsReport(organizationId) .getRiskInsightsReport$(organizationId)
.pipe( .pipe(
switchMap((response) => { switchMap((response) => {
if (!response) { if (!response) {
@@ -275,7 +275,7 @@ export class RiskInsightsReportService {
}; };
const response = await firstValueFrom( const response = await firstValueFrom(
this.riskInsightsApiService.saveRiskInsightsReport(saveRequest, organizationId), this.riskInsightsApiService.saveRiskInsightsReport$(saveRequest, organizationId),
); );
if (response && response.id) { if (response && response.id) {