1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-08 12:40:26 +00:00

PM-20578 Added api to fetch and save data (#15334)

This commit is contained in:
Vijay Oommen
2025-07-01 13:39:23 -05:00
committed by GitHub
parent cf2c8733ca
commit e591773d4b
3 changed files with 242 additions and 0 deletions

View File

@@ -167,4 +167,32 @@ export enum DrawerType {
OrgAtRiskApps = 3,
}
export interface RiskInsightsReport {
organizationId: OrganizationId;
date: string;
reportData: string;
reportKey: string;
}
export interface ReportInsightsReportData {
data: string;
key: string;
}
export interface SaveRiskInsightsReportRequest {
data: RiskInsightsReport;
}
export interface SaveRiskInsightsReportResponse {
id: string;
}
export interface GetRiskInsightsReportResponse {
id: string;
organizationId: OrganizationId;
date: string;
reportData: string;
reportKey: string;
}
export type PasswordHealthReportApplicationId = Opaque<string, "PasswordHealthReportApplicationId">;

View File

@@ -0,0 +1,173 @@
import { mock } from "jest-mock-extended";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { SaveRiskInsightsReportRequest } from "../models/password-health";
import { RiskInsightsApiService } from "./risk-insights-api.service";
describe("RiskInsightsApiService", () => {
let service: RiskInsightsApiService;
const apiService = mock<ApiService>();
const orgId = "org1" as OrganizationId;
const getRiskInsightsReportResponse = {
organizationId: orgId,
date: new Date().toISOString(),
reportData: "test",
reportKey: "test-key",
};
const saveRiskInsightsReportRequest: SaveRiskInsightsReportRequest = {
data: {
organizationId: orgId,
date: new Date().toISOString(),
reportData: "test",
reportKey: "test-key",
},
};
const saveRiskInsightsReportResponse = {
...saveRiskInsightsReportRequest.data,
};
beforeEach(() => {
service = new RiskInsightsApiService(apiService);
});
it("should be created", () => {
expect(service).toBeTruthy();
});
it("should call apiService.send with correct parameters for saveRiskInsightsReport", (done) => {
apiService.send.mockReturnValue(Promise.resolve(saveRiskInsightsReportResponse));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest).subscribe((result) => {
expect(result).toEqual(saveRiskInsightsReportResponse);
expect(apiService.send).toHaveBeenCalledWith(
"POST",
`/reports/organization-reports`,
saveRiskInsightsReportRequest.data,
true,
true,
);
done();
});
});
it("should call apiService.send with correct parameters and return the response for saveRiskInsightsReport ", (done) => {
apiService.send.mockReturnValue(Promise.resolve(saveRiskInsightsReportResponse));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest).subscribe((result) => {
expect(result).toEqual(saveRiskInsightsReportResponse);
expect(apiService.send).toHaveBeenCalledWith(
"POST",
`/reports/organization-reports`,
saveRiskInsightsReportRequest.data,
true,
true,
);
done();
});
});
it("should propagate errors from apiService.send for saveRiskInsightsReport - 1", (done) => {
const error = { statusCode: 500, message: "Internal Server Error" };
apiService.send.mockReturnValue(Promise.reject(error));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest).subscribe({
next: () => {
fail("Expected error to be thrown");
},
error: () => {
expect(apiService.send).toHaveBeenCalledWith(
"POST",
`/reports/organization-reports`,
saveRiskInsightsReportRequest.data,
true,
true,
);
done();
},
complete: () => {
done();
},
});
});
it("should propagate network errors from apiService.send for saveRiskInsightsReport - 2", (done) => {
const error = new Error("Network error");
apiService.send.mockReturnValue(Promise.reject(error));
service.saveRiskInsightsReport(saveRiskInsightsReportRequest).subscribe({
next: () => {
fail("Expected error to be thrown");
},
error: () => {
expect(apiService.send).toHaveBeenCalledWith(
"POST",
`/reports/organization-reports`,
saveRiskInsightsReportRequest.data,
true,
true,
);
done();
},
complete: () => {
done();
},
});
});
it("should call apiService.send with correct parameters and return the response for getRiskInsightsReport ", (done) => {
apiService.send.mockReturnValue(Promise.resolve(getRiskInsightsReportResponse));
service.getRiskInsightsReport(orgId).subscribe((result) => {
expect(result).toEqual(getRiskInsightsReportResponse);
expect(apiService.send).toHaveBeenCalledWith(
"GET",
`/reports/organization-reports/latest/${orgId.toString()}`,
null,
true,
true,
);
done();
});
});
it("should return null if apiService.send rejects with 404 error for getRiskInsightsReport", (done) => {
const error = { statusCode: 404 };
apiService.send.mockReturnValue(Promise.reject(error));
service.getRiskInsightsReport(orgId).subscribe((result) => {
expect(result).toBeNull();
done();
});
});
it("should throw error if apiService.send rejects with non-404 error for getRiskInsightsReport", (done) => {
const error = { statusCode: 500, message: "Server error" };
apiService.send.mockReturnValue(Promise.reject(error));
service.getRiskInsightsReport(orgId).subscribe({
next: () => {
// Should not reach here
fail("Expected error to be thrown");
},
error: () => {
expect(apiService.send).toHaveBeenCalledWith(
"GET",
`/reports/organization-reports/latest/${orgId.toString()}`,
null,
true,
true,
);
done();
},
complete: () => {
done();
},
});
});
});

View File

@@ -0,0 +1,41 @@
import { from, Observable } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationId } from "@bitwarden/common/types/guid";
import {
GetRiskInsightsReportResponse,
SaveRiskInsightsReportRequest,
SaveRiskInsightsReportResponse,
} from "../models/password-health";
export class RiskInsightsApiService {
constructor(private apiService: ApiService) {}
saveRiskInsightsReport(
request: SaveRiskInsightsReportRequest,
): Observable<SaveRiskInsightsReportResponse> {
const dbResponse = this.apiService.send(
"POST",
`/reports/organization-reports`,
request.data,
true,
true,
);
return from(dbResponse as Promise<SaveRiskInsightsReportResponse>);
}
getRiskInsightsReport(orgId: OrganizationId): Observable<GetRiskInsightsReportResponse | null> {
const dbResponse = this.apiService
.send("GET", `/reports/organization-reports/latest/${orgId.toString()}`, null, true, true)
.catch((error: any): any => {
if (error.statusCode === 404) {
return null; // Handle 404 by returning null or an appropriate default value
}
throw error; // Re-throw other errors
});
return from(dbResponse as Promise<GetRiskInsightsReportResponse>);
}
}