1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-23 03:33:54 +00:00

[PM-24100] Remove GetOrgKey from key Service (#15823)

* Remove GetOrgKey from key Service

* adding back accidentally removed line

* Fixing spec

* fixing spec

* specs

* spec fixes

* spec changes omg

* lint fixes

* fixing test?

* test fixes..maybe
This commit is contained in:
cd-bitwarden
2025-08-14 14:25:36 -04:00
committed by GitHub
parent 41ad0a7ef9
commit ff4952c113
9 changed files with 206 additions and 36 deletions

View File

@@ -1,13 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { filter, firstValueFrom, map, Subject, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { ProjectListView } from "../models/view/project-list.view"; import { ProjectListView } from "../models/view/project-list.view";
@@ -29,8 +32,22 @@ export class ProjectService {
private keyService: KeyService, private keyService: KeyService,
private apiService: ApiService, private apiService: ApiService,
private encryptService: EncryptService, private encryptService: EncryptService,
private accountService: AccountService,
) {} ) {}
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async getByProjectId(projectId: string): Promise<ProjectView> { async getByProjectId(projectId: string): Promise<ProjectView> {
const r = await this.apiService.send("GET", "/projects/" + projectId, null, true, true); const r = await this.apiService.send("GET", "/projects/" + projectId, null, true, true);
const projectResponse = new ProjectResponse(r); const projectResponse = new ProjectResponse(r);
@@ -83,10 +100,6 @@ export class ProjectService {
}); });
} }
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.keyService.getOrgKey(organizationId);
}
private async getProjectRequest( private async getProjectRequest(
organizationId: string, organizationId: string,
projectView: ProjectView, projectView: ProjectView,

View File

@@ -1,8 +1,14 @@
import { mock } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { CsprngArray } from "@bitwarden/common/types/csprng";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { SecretAccessPoliciesView } from "../models/view/access-policies/secret-access-policies.view"; import { SecretAccessPoliciesView } from "../models/view/access-policies/secret-access-policies.view";
@@ -11,6 +17,16 @@ import { AccessPolicyService } from "../shared/access-policies/access-policy.ser
import { SecretService } from "./secret.service"; import { SecretService } from "./secret.service";
const SomeCsprngArray = new Uint8Array(64) as CsprngArray;
const SomeOrganization = "some organization" as OrganizationId;
const AnotherOrganization = "another organization" as OrganizationId;
const SomeOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const AnotherOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const OrgRecords: Record<OrganizationId, OrgKey> = {
[SomeOrganization]: SomeOrgKey,
[AnotherOrganization]: AnotherOrgKey,
};
describe("SecretService", () => { describe("SecretService", () => {
let sut: SecretService; let sut: SecretService;
@@ -18,11 +34,30 @@ describe("SecretService", () => {
const apiService = mock<ApiService>(); const apiService = mock<ApiService>();
const encryptService = mock<EncryptService>(); const encryptService = mock<EncryptService>();
const accessPolicyService = mock<AccessPolicyService>(); const accessPolicyService = mock<AccessPolicyService>();
let accountService: MockProxy<AccountService> = mock<AccountService>();
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>({
id: "testId" as UserId,
email: "test@example.com",
emailVerified: true,
name: "Test User",
});
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
sut = new SecretService(keyService, apiService, encryptService, accessPolicyService); const orgKey$ = new BehaviorSubject(OrgRecords);
keyService.orgKeys$.mockReturnValue(orgKey$);
accountService = mock<AccountService>();
accountService.activeAccount$ = activeAccountSubject;
sut = new SecretService(
keyService,
apiService,
encryptService,
accessPolicyService,
accountService,
);
encryptService.encryptString.mockResolvedValue({ encryptService.encryptString.mockResolvedValue({
encryptedString: "mockEncryptedString", encryptedString: "mockEncryptedString",

View File

@@ -1,12 +1,15 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { Subject, firstValueFrom, switchMap, map, filter } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { SecretAccessPoliciesView } from "../models/view/access-policies/secret-access-policies.view"; import { SecretAccessPoliciesView } from "../models/view/access-policies/secret-access-policies.view";
@@ -27,7 +30,6 @@ import { SecretResponse } from "./responses/secret.response";
}) })
export class SecretService { export class SecretService {
protected _secret: Subject<SecretView> = new Subject(); protected _secret: Subject<SecretView> = new Subject();
secret$ = this._secret.asObservable(); secret$ = this._secret.asObservable();
constructor( constructor(
@@ -35,8 +37,22 @@ export class SecretService {
private apiService: ApiService, private apiService: ApiService,
private encryptService: EncryptService, private encryptService: EncryptService,
private accessPolicyService: AccessPolicyService, private accessPolicyService: AccessPolicyService,
private accountService: AccountService,
) {} ) {}
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async getBySecretId(secretId: string): Promise<SecretView> { async getBySecretId(secretId: string): Promise<SecretView> {
const r = await this.apiService.send("GET", "/secrets/" + secretId, null, true, true); const r = await this.apiService.send("GET", "/secrets/" + secretId, null, true, true);
const secretResponse = new SecretResponse(r); const secretResponse = new SecretResponse(r);
@@ -154,10 +170,6 @@ export class SecretService {
this._secret.next(null); this._secret.next(null);
} }
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.keyService.getOrgKey(organizationId);
}
private async getSecretRequest( private async getSecretRequest(
organizationId: string, organizationId: string,
secretView: SecretView, secretView: SecretView,

View File

@@ -1,15 +1,18 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { filter, firstValueFrom, map, Subject, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/key-generation.service"; import { KeyGenerationService } from "@bitwarden/common/platform/abstractions/key-generation.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { AccessTokenRequest } from "../models/requests/access-token.request"; import { AccessTokenRequest } from "../models/requests/access-token.request";
@@ -32,6 +35,7 @@ export class AccessService {
private apiService: ApiService, private apiService: ApiService,
private keyGenerationService: KeyGenerationService, private keyGenerationService: KeyGenerationService,
private encryptService: EncryptService, private encryptService: EncryptService,
private accountService: AccountService,
) {} ) {}
async getAccessTokens( async getAccessTokens(
@@ -50,6 +54,19 @@ export class AccessService {
return await this.createAccessTokenViews(organizationId, results.data); return await this.createAccessTokenViews(organizationId, results.data);
} }
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async createAccessToken( async createAccessToken(
organizationId: string, organizationId: string,
serviceAccountId: string, serviceAccountId: string,
@@ -117,10 +134,6 @@ export class AccessService {
return accessTokenRequest; return accessTokenRequest;
} }
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.keyService.getOrgKey(organizationId);
}
private async createAccessTokenViews( private async createAccessTokenViews(
organizationId: string, organizationId: string,
accessTokenResponses: AccessTokenResponse[], accessTokenResponses: AccessTokenResponse[],

View File

@@ -1,13 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { filter, firstValueFrom, map, Subject, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { import {
@@ -34,8 +37,22 @@ export class ServiceAccountService {
private keyService: KeyService, private keyService: KeyService,
private apiService: ApiService, private apiService: ApiService,
private encryptService: EncryptService, private encryptService: EncryptService,
private accountService: AccountService,
) {} ) {}
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async getServiceAccounts( async getServiceAccounts(
organizationId: string, organizationId: string,
includeAccessToSecrets?: boolean, includeAccessToSecrets?: boolean,
@@ -129,10 +146,6 @@ export class ServiceAccountService {
}); });
} }
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.keyService.getOrgKey(organizationId);
}
private async getServiceAccountRequest( private async getServiceAccountRequest(
organizationKey: SymmetricCryptoKey, organizationKey: SymmetricCryptoKey,
serviceAccountView: ServiceAccountView, serviceAccountView: ServiceAccountView,

View File

@@ -1,11 +1,14 @@
import { mock } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { CsprngArray } from "@bitwarden/common/types/csprng"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key"; import { OrgKey } from "@bitwarden/common/types/key";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
@@ -16,17 +19,43 @@ import { SecretsManagerImportedSecretRequest } from "../models/requests/sm-impor
import { SecretsManagerPortingApiService } from "./sm-porting-api.service"; import { SecretsManagerPortingApiService } from "./sm-porting-api.service";
const SomeCsprngArray = new Uint8Array(64) as CsprngArray;
const SomeOrganization = "some organization" as OrganizationId;
const AnotherOrganization = "another organization" as OrganizationId;
const SomeOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const AnotherOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const OrgRecords: Record<OrganizationId, OrgKey> = {
[SomeOrganization]: SomeOrgKey,
[AnotherOrganization]: AnotherOrgKey,
};
describe("SecretsManagerPortingApiService", () => { describe("SecretsManagerPortingApiService", () => {
let sut: SecretsManagerPortingApiService; let sut: SecretsManagerPortingApiService;
const apiService = mock<ApiService>(); const apiService = mock<ApiService>();
const encryptService = mock<EncryptService>(); const encryptService = mock<EncryptService>();
const keyService = mock<KeyService>(); const keyService = mock<KeyService>();
let accountService: MockProxy<AccountService>;
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>({
id: "testId" as UserId,
email: "test@example.com",
emailVerified: true,
name: "Test User",
});
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
sut = new SecretsManagerPortingApiService(apiService, encryptService, keyService); const orgKey$ = new BehaviorSubject(OrgRecords);
keyService.orgKeys$.mockReturnValue(orgKey$);
accountService = mock<AccountService>();
accountService.activeAccount$ = activeAccountSubject;
sut = new SecretsManagerPortingApiService(
apiService,
encryptService,
keyService,
accountService,
);
encryptService.encryptString.mockResolvedValue(mockEncryptedString); encryptService.encryptString.mockResolvedValue(mockEncryptedString);
encryptService.decryptString.mockResolvedValue(mockUnencryptedString); encryptService.decryptString.mockResolvedValue(mockUnencryptedString);
@@ -51,7 +80,6 @@ describe("SecretsManagerPortingApiService", () => {
it("emits the import successful", async () => { it("emits the import successful", async () => {
const expectedRequest = toRequest([project1, project2], [secret1, secret2]); const expectedRequest = toRequest([project1, project2], [secret1, secret2]);
let subscriptionCount = 0; let subscriptionCount = 0;
sut.imports$.subscribe((request) => { sut.imports$.subscribe((request) => {
expect(request).toBeDefined(); expect(request).toBeDefined();

View File

@@ -1,12 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { filter, firstValueFrom, map, Subject, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { SecretsManagerImportError } from "../models/error/sm-import-error"; import { SecretsManagerImportError } from "../models/error/sm-import-error";
@@ -31,8 +35,22 @@ export class SecretsManagerPortingApiService {
private apiService: ApiService, private apiService: ApiService,
private encryptService: EncryptService, private encryptService: EncryptService,
private keyService: KeyService, private keyService: KeyService,
private accountService: AccountService,
) {} ) {}
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async export(organizationId: string): Promise<string> { async export(organizationId: string): Promise<string> {
const response = await this.apiService.send( const response = await this.apiService.send(
"GET", "GET",
@@ -78,7 +96,7 @@ export class SecretsManagerPortingApiService {
const encryptedImport = new SecretsManagerImportRequest(); const encryptedImport = new SecretsManagerImportRequest();
try { try {
const orgKey = await this.keyService.getOrgKey(organizationId); const orgKey = await this.getOrganizationKey(organizationId);
encryptedImport.projects = []; encryptedImport.projects = [];
encryptedImport.secrets = []; encryptedImport.secrets = [];
@@ -120,7 +138,7 @@ export class SecretsManagerPortingApiService {
organizationId: string, organizationId: string,
exportData: SecretsManagerExportResponse, exportData: SecretsManagerExportResponse,
): Promise<SecretsManagerExport> { ): Promise<SecretsManagerExport> {
const orgKey = await this.keyService.getOrgKey(organizationId); const orgKey = await this.getOrganizationKey(organizationId);
const decryptedExport = new SecretsManagerExport(); const decryptedExport = new SecretsManagerExport();
decryptedExport.projects = []; decryptedExport.projects = [];
decryptedExport.secrets = []; decryptedExport.secrets = [];

View File

@@ -1,12 +1,15 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { mock } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { CsprngArray } from "@bitwarden/common/types/csprng"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
import { OrgKey } from "@bitwarden/common/types/key"; import { OrgKey } from "@bitwarden/common/types/key";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
@@ -30,17 +33,39 @@ import { ServiceAccountGrantedPoliciesRequest } from "./models/requests/service-
import { trackEmissions } from "@bitwarden/common/../spec"; import { trackEmissions } from "@bitwarden/common/../spec";
const SomeCsprngArray = new Uint8Array(64) as CsprngArray;
const SomeOrganization = "some organization" as OrganizationId;
const AnotherOrganization = "another organization" as OrganizationId;
const SomeOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const AnotherOrgKey = new SymmetricCryptoKey(SomeCsprngArray) as OrgKey;
const OrgRecords: Record<OrganizationId, OrgKey> = {
[SomeOrganization]: SomeOrgKey,
[AnotherOrganization]: AnotherOrgKey,
};
describe("AccessPolicyService", () => { describe("AccessPolicyService", () => {
let sut: AccessPolicyService; let sut: AccessPolicyService;
const keyService = mock<KeyService>(); const keyService = mock<KeyService>();
const apiService = mock<ApiService>(); const apiService = mock<ApiService>();
const encryptService = mock<EncryptService>(); const encryptService = mock<EncryptService>();
let accountService: MockProxy<AccountService>;
const activeAccountSubject = new BehaviorSubject<{ id: UserId } & AccountInfo>({
id: "testId" as UserId,
email: "test@example.com",
emailVerified: true,
name: "Test User",
});
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
sut = new AccessPolicyService(keyService, apiService, encryptService); const orgKey$ = new BehaviorSubject(OrgRecords);
keyService.orgKeys$.mockReturnValue(orgKey$);
accountService = mock<AccountService>();
accountService.activeAccount$ = activeAccountSubject;
sut = new AccessPolicyService(keyService, apiService, encryptService, accountService);
}); });
it("instantiates", () => { it("instantiates", () => {

View File

@@ -1,13 +1,16 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs"; import { filter, firstValueFrom, map, Subject, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string"; import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { KeyService } from "@bitwarden/key-management"; import { KeyService } from "@bitwarden/key-management";
import { import {
@@ -62,8 +65,22 @@ export class AccessPolicyService {
private keyService: KeyService, private keyService: KeyService,
protected apiService: ApiService, protected apiService: ApiService,
protected encryptService: EncryptService, protected encryptService: EncryptService,
private accountService: AccountService,
) {} ) {}
private getOrganizationKey$(organizationId: string) {
return this.accountService.activeAccount$.pipe(
getUserId,
switchMap((userId) => this.keyService.orgKeys$(userId)),
filter((orgKeys) => !!orgKeys),
map((organizationKeysById) => organizationKeysById[organizationId as OrganizationId]),
);
}
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await firstValueFrom(this.getOrganizationKey$(organizationId));
}
async getProjectPeopleAccessPolicies( async getProjectPeopleAccessPolicies(
projectId: string, projectId: string,
): Promise<ProjectPeopleAccessPoliciesView> { ): Promise<ProjectPeopleAccessPoliciesView> {
@@ -268,10 +285,6 @@ export class AccessPolicyService {
}; };
} }
private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.keyService.getOrgKey(organizationId);
}
private getAccessPolicyRequest( private getAccessPolicyRequest(
granteeId: string, granteeId: string,
view: UserAccessPolicyView | GroupAccessPolicyView | ServiceAccountAccessPolicyView, view: UserAccessPolicyView | GroupAccessPolicyView | ServiceAccountAccessPolicyView,