1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-28370] fix defect for self-hosted metadata (#17464)

This commit is contained in:
Kyle Denney
2025-11-18 15:24:36 -06:00
committed by GitHub
parent bf8976ca66
commit fde1e26ad9
5 changed files with 51 additions and 3 deletions

View File

@@ -1451,7 +1451,7 @@ const safeProviders: SafeProvider[] = [
safeProvider({
provide: OrganizationMetadataServiceAbstraction,
useClass: DefaultOrganizationMetadataService,
deps: [BillingApiServiceAbstraction, ConfigService],
deps: [BillingApiServiceAbstraction, ConfigService, PlatformUtilsServiceAbstraction],
}),
safeProvider({
provide: BillingAccountProfileStateService,

View File

@@ -25,6 +25,10 @@ export abstract class BillingApiServiceAbstraction {
organizationId: OrganizationId,
): Promise<OrganizationBillingMetadataResponse>;
abstract getOrganizationBillingMetadataVNextSelfHost(
organizationId: OrganizationId,
): Promise<OrganizationBillingMetadataResponse>;
abstract getPlans(): Promise<ListResponse<PlanResponse>>;
abstract getPremiumPlan(): Promise<PremiumPlanResponse>;

View File

@@ -62,6 +62,20 @@ export class BillingApiService implements BillingApiServiceAbstraction {
return new OrganizationBillingMetadataResponse(r);
}
async getOrganizationBillingMetadataVNextSelfHost(
organizationId: OrganizationId,
): Promise<OrganizationBillingMetadataResponse> {
const r = await this.apiService.send(
"GET",
"/organizations/" + organizationId + "/billing/vnext/self-host/metadata",
null,
true,
true,
);
return new OrganizationBillingMetadataResponse(r);
}
async getPlans(): Promise<ListResponse<PlanResponse>> {
const r = await this.apiService.send("GET", "/plans", null, true, true);
return new ListResponse(r, PlanResponse);

View File

@@ -4,6 +4,7 @@ import { BehaviorSubject, firstValueFrom } from "rxjs";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
import { OrganizationBillingMetadataResponse } from "@bitwarden/common/billing/models/response/organization-billing-metadata.response";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { newGuid } from "@bitwarden/guid";
import { FeatureFlag } from "../../../enums/feature-flag.enum";
@@ -15,6 +16,7 @@ describe("DefaultOrganizationMetadataService", () => {
let service: DefaultOrganizationMetadataService;
let billingApiService: jest.Mocked<BillingApiServiceAbstraction>;
let configService: jest.Mocked<ConfigService>;
let platformUtilsService: jest.Mocked<PlatformUtilsService>;
let featureFlagSubject: BehaviorSubject<boolean>;
const mockOrganizationId = newGuid() as OrganizationId;
@@ -33,11 +35,17 @@ describe("DefaultOrganizationMetadataService", () => {
beforeEach(() => {
billingApiService = mock<BillingApiServiceAbstraction>();
configService = mock<ConfigService>();
platformUtilsService = mock<PlatformUtilsService>();
featureFlagSubject = new BehaviorSubject<boolean>(false);
configService.getFeatureFlag$.mockReturnValue(featureFlagSubject.asObservable());
platformUtilsService.isSelfHost.mockReturnValue(false);
service = new DefaultOrganizationMetadataService(billingApiService, configService);
service = new DefaultOrganizationMetadataService(
billingApiService,
configService,
platformUtilsService,
);
});
afterEach(() => {
@@ -142,6 +150,24 @@ describe("DefaultOrganizationMetadataService", () => {
expect(result3).toEqual(mockResponse1);
expect(result4).toEqual(mockResponse2);
});
it("calls getOrganizationBillingMetadataVNextSelfHost when feature flag is on and isSelfHost is true", async () => {
platformUtilsService.isSelfHost.mockReturnValue(true);
const mockResponse = createMockMetadataResponse(true, 25);
billingApiService.getOrganizationBillingMetadataVNextSelfHost.mockResolvedValue(
mockResponse,
);
const result = await firstValueFrom(service.getOrganizationMetadata$(mockOrganizationId));
expect(platformUtilsService.isSelfHost).toHaveBeenCalled();
expect(billingApiService.getOrganizationBillingMetadataVNextSelfHost).toHaveBeenCalledWith(
mockOrganizationId,
);
expect(billingApiService.getOrganizationBillingMetadataVNext).not.toHaveBeenCalled();
expect(billingApiService.getOrganizationBillingMetadata).not.toHaveBeenCalled();
expect(result).toEqual(mockResponse);
});
});
describe("shareReplay behavior", () => {

View File

@@ -1,6 +1,7 @@
import { BehaviorSubject, combineLatest, from, Observable, shareReplay, switchMap } from "rxjs";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { FeatureFlag } from "../../../enums/feature-flag.enum";
import { ConfigService } from "../../../platform/abstractions/config/config.service";
@@ -17,6 +18,7 @@ export class DefaultOrganizationMetadataService implements OrganizationMetadataS
constructor(
private billingApiService: BillingApiServiceAbstraction,
private configService: ConfigService,
private platformUtilsService: PlatformUtilsService,
) {}
private refreshMetadataTrigger = new BehaviorSubject<void>(undefined);
@@ -67,7 +69,9 @@ export class DefaultOrganizationMetadataService implements OrganizationMetadataS
featureFlagEnabled: boolean,
): Promise<OrganizationBillingMetadataResponse> {
return featureFlagEnabled
? await this.billingApiService.getOrganizationBillingMetadataVNext(organizationId)
? this.platformUtilsService.isSelfHost()
? await this.billingApiService.getOrganizationBillingMetadataVNextSelfHost(organizationId)
: await this.billingApiService.getOrganizationBillingMetadataVNext(organizationId)
: await this.billingApiService.getOrganizationBillingMetadata(organizationId);
}
}