diff --git a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/member-access-report.component.ts b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/member-access-report.component.ts index ad15edd84df..445cee6683c 100644 --- a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/member-access-report.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/member-access-report.component.ts @@ -8,12 +8,15 @@ import { BehaviorSubject, debounceTime, firstValueFrom, lastValueFrom } from "rx import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe"; import { safeProvider } from "@bitwarden/angular/platform/utils/safe-provider"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { OrganizationMetadataServiceAbstraction } from "@bitwarden/common/billing/abstractions/organization-metadata.service.abstraction"; +import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { OrganizationId } from "@bitwarden/common/types/guid"; import { DialogService, SearchModule, TableDataSource } from "@bitwarden/components"; +import { KeyService } from "@bitwarden/key-management"; import { ExportHelper } from "@bitwarden/vault-export-core"; import { CoreOrganizationModule } from "@bitwarden/web-vault/app/admin-console/organizations/core"; import { @@ -41,7 +44,7 @@ import { MemberAccessReportView } from "./view/member-access-report.view"; safeProvider({ provide: MemberAccessReportServiceAbstraction, useClass: MemberAccessReportService, - deps: [MemberAccessReportApiService, I18nService], + deps: [MemberAccessReportApiService, I18nService, EncryptService, KeyService, AccountService], }), ], }) diff --git a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.spec.ts b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.spec.ts index ad388cfed04..615e6d079b2 100644 --- a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.spec.ts +++ b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.spec.ts @@ -1,7 +1,13 @@ import { mock } from "jest-mock-extended"; +import { of } from "rxjs"; +import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { OrganizationId } from "@bitwarden/common/types/guid"; +import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; +import { mockAccountServiceWith } from "@bitwarden/common/spec"; +import { OrganizationId, UserId } from "@bitwarden/common/types/guid"; +import { newGuid } from "@bitwarden/guid"; +import { KeyService } from "@bitwarden/key-management"; import { MemberAccessReportApiService } from "./member-access-report-api.service"; import { @@ -9,9 +15,14 @@ import { memberAccessWithoutAccessDetailsReportsMock, } from "./member-access-report.mock"; import { MemberAccessReportService } from "./member-access-report.service"; + describe("ImportService", () => { const mockOrganizationId = "mockOrgId" as OrganizationId; const reportApiService = mock(); + const mockEncryptService = mock(); + const userId = newGuid() as UserId; + const mockAccountService = mockAccountServiceWith(userId); + const mockKeyService = mock(); let memberAccessReportService: MemberAccessReportService; const i18nMock = mock({ t(key) { @@ -20,10 +31,19 @@ describe("ImportService", () => { }); beforeEach(() => { + mockKeyService.orgKeys$.mockReturnValue( + of({ mockOrgId: new SymmetricCryptoKey(new Uint8Array(64)) }), + ); reportApiService.getMemberAccessData.mockImplementation(() => Promise.resolve(memberAccessReportsMock), ); - memberAccessReportService = new MemberAccessReportService(reportApiService, i18nMock); + memberAccessReportService = new MemberAccessReportService( + reportApiService, + i18nMock, + mockEncryptService, + mockKeyService, + mockAccountService, + ); }); describe("generateMemberAccessReportView", () => { diff --git a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.ts b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.ts index caa27a75b82..f6d1139f619 100644 --- a/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.ts +++ b/bitwarden_license/bit-web/src/app/dirt/reports/member-access-report/services/member-access-report.service.ts @@ -1,11 +1,16 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { Injectable } from "@angular/core"; +import { firstValueFrom, map } from "rxjs"; import { CollectionAccessSelectionView } from "@bitwarden/admin-console/common"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { getUserId } from "@bitwarden/common/auth/services/account.service"; +import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Guid, OrganizationId } from "@bitwarden/common/types/guid"; +import { KeyService } from "@bitwarden/key-management"; import { getPermissionList, convertToPermission, @@ -22,6 +27,9 @@ export class MemberAccessReportService { constructor( private reportApiService: MemberAccessReportApiService, private i18nService: I18nService, + private encryptService: EncryptService, + private keyService: KeyService, + private accountService: AccountService, ) {} /** * Transforms user data into a MemberAccessReportView. @@ -78,14 +86,22 @@ export class MemberAccessReportService { async generateUserReportExportItems( organizationId: OrganizationId, ): Promise { + const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); + const organizationSymmetricKey = await firstValueFrom( + this.keyService.orgKeys$(activeUserId).pipe(map((keys) => keys[organizationId])), + ); + const memberAccessReports = await this.reportApiService.getMemberAccessData(organizationId); const collectionNames = memberAccessReports.map((item) => item.collectionName.encryptedString); const collectionNameMap = new Map(collectionNames.map((col) => [col, ""])); for await (const key of collectionNameMap.keys()) { - const decrypted = new EncString(key); - await decrypted.decrypt(organizationId); - collectionNameMap.set(key, decrypted.decryptedValue); + const encryptedCollectionName = new EncString(key); + const collectionName = await this.encryptService.decryptString( + encryptedCollectionName, + organizationSymmetricKey, + ); + collectionNameMap.set(key, collectionName); } const exportItems = memberAccessReports.map((report) => {