1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 18:23:31 +00:00

[PM-19810] Member Access Report - CSV export fix (#14313)

This commit is contained in:
Vijay Oommen
2025-04-18 08:45:05 -05:00
committed by GitHub
parent 7bf4bae7c6
commit d6beca569c
3 changed files with 91 additions and 1 deletions

View File

@@ -229,3 +229,41 @@ export const memberAccessReportsMock: MemberAccessResponse[] = [
], ],
} as MemberAccessResponse, } as MemberAccessResponse,
]; ];
export const memberAccessWithoutAccessDetailsReportsMock: MemberAccessResponse[] = [
{
userName: "Alice Smith",
email: "asmith@email.com",
twoFactorEnabled: true,
accountRecoveryEnabled: true,
groupsCount: 2,
collectionsCount: 4,
totalItemCount: 20,
userGuid: "1234",
usesKeyConnector: false,
accessDetails: [
{
groupId: "",
collectionId: "c1",
collectionName: new EncString("Collection 1"),
groupName: "Alice Group 1",
itemCount: 10,
readOnly: false,
hidePasswords: false,
manage: false,
} as MemberAccessDetails,
],
} as MemberAccessResponse,
{
userName: "Robert Brown",
email: "rbrown@email.com",
twoFactorEnabled: false,
accountRecoveryEnabled: false,
groupsCount: 2,
collectionsCount: 4,
totalItemCount: 20,
userGuid: "5678",
usesKeyConnector: false,
accessDetails: [] as MemberAccessDetails[],
} as MemberAccessResponse,
];

View File

@@ -4,7 +4,10 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { OrganizationId } from "@bitwarden/common/types/guid"; import { OrganizationId } from "@bitwarden/common/types/guid";
import { MemberAccessReportApiService } from "./member-access-report-api.service"; import { MemberAccessReportApiService } from "./member-access-report-api.service";
import { memberAccessReportsMock } from "./member-access-report.mock"; import {
memberAccessReportsMock,
memberAccessWithoutAccessDetailsReportsMock,
} from "./member-access-report.mock";
import { MemberAccessReportService } from "./member-access-report.service"; import { MemberAccessReportService } from "./member-access-report.service";
describe("ImportService", () => { describe("ImportService", () => {
const mockOrganizationId = "mockOrgId" as OrganizationId; const mockOrganizationId = "mockOrgId" as OrganizationId;
@@ -112,5 +115,34 @@ describe("ImportService", () => {
]), ]),
); );
}); });
it("should generate user report export items and include users with no access", async () => {
reportApiService.getMemberAccessData.mockImplementation(() =>
Promise.resolve(memberAccessWithoutAccessDetailsReportsMock),
);
const result =
await memberAccessReportService.generateUserReportExportItems(mockOrganizationId);
expect(result).toEqual(
expect.arrayContaining([
expect.objectContaining({
email: "asmith@email.com",
name: "Alice Smith",
twoStepLogin: "memberAccessReportTwoFactorEnabledTrue",
accountRecovery: "memberAccessReportAuthenticationEnabledTrue",
group: "Alice Group 1",
totalItems: "10",
}),
expect.objectContaining({
email: "rbrown@email.com",
name: "Robert Brown",
twoStepLogin: "memberAccessReportTwoFactorEnabledFalse",
accountRecovery: "memberAccessReportAuthenticationEnabledFalse",
group: "memberAccessReportNoGroup",
totalItems: "0",
}),
]),
);
});
}); });
}); });

View File

@@ -65,6 +65,26 @@ export class MemberAccessReportService {
} }
const exportItems = memberAccessReports.flatMap((report) => { const exportItems = memberAccessReports.flatMap((report) => {
// to include users without access details
// which means a user has no groups, collections or items
if (report.accessDetails.length === 0) {
return [
{
email: report.email,
name: report.userName,
twoStepLogin: report.twoFactorEnabled
? this.i18nService.t("memberAccessReportTwoFactorEnabledTrue")
: this.i18nService.t("memberAccessReportTwoFactorEnabledFalse"),
accountRecovery: report.accountRecoveryEnabled
? this.i18nService.t("memberAccessReportAuthenticationEnabledTrue")
: this.i18nService.t("memberAccessReportAuthenticationEnabledFalse"),
group: this.i18nService.t("memberAccessReportNoGroup"),
collection: this.i18nService.t("memberAccessReportNoCollection"),
collectionPermission: this.i18nService.t("memberAccessReportNoCollectionPermission"),
totalItems: "0",
},
];
}
const userDetails = report.accessDetails.map((detail) => { const userDetails = report.accessDetails.map((detail) => {
const collectionName = collectionNameMap.get(detail.collectionName.encryptedString); const collectionName = collectionNameMap.get(detail.collectionName.encryptedString);
return { return {