mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +00:00
[PM-25858]Organization warnings endpoint should not be called from self-hosted instances (#16781)
* ensure that getWarnings from server is not called for selfhost * Refactor the code * move the selfhost check to getWarning message * Fix the failing test
This commit is contained in:
@@ -16,6 +16,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
|||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { DialogRef, DialogService } from "@bitwarden/components";
|
import { DialogRef, DialogService } from "@bitwarden/components";
|
||||||
import { OrganizationBillingClient } from "@bitwarden/web-vault/app/billing/clients";
|
import { OrganizationBillingClient } from "@bitwarden/web-vault/app/billing/clients";
|
||||||
import {
|
import {
|
||||||
@@ -37,6 +38,7 @@ describe("OrganizationWarningsService", () => {
|
|||||||
let i18nService: MockProxy<I18nService>;
|
let i18nService: MockProxy<I18nService>;
|
||||||
let organizationApiService: MockProxy<OrganizationApiServiceAbstraction>;
|
let organizationApiService: MockProxy<OrganizationApiServiceAbstraction>;
|
||||||
let organizationBillingClient: MockProxy<OrganizationBillingClient>;
|
let organizationBillingClient: MockProxy<OrganizationBillingClient>;
|
||||||
|
let platformUtilsService: MockProxy<PlatformUtilsService>;
|
||||||
let router: MockProxy<Router>;
|
let router: MockProxy<Router>;
|
||||||
|
|
||||||
const organization = {
|
const organization = {
|
||||||
@@ -58,10 +60,13 @@ describe("OrganizationWarningsService", () => {
|
|||||||
i18nService = mock<I18nService>();
|
i18nService = mock<I18nService>();
|
||||||
organizationApiService = mock<OrganizationApiServiceAbstraction>();
|
organizationApiService = mock<OrganizationApiServiceAbstraction>();
|
||||||
organizationBillingClient = mock<OrganizationBillingClient>();
|
organizationBillingClient = mock<OrganizationBillingClient>();
|
||||||
|
platformUtilsService = mock<PlatformUtilsService>();
|
||||||
router = mock<Router>();
|
router = mock<Router>();
|
||||||
|
|
||||||
(openChangePlanDialog as jest.Mock).mockReset();
|
(openChangePlanDialog as jest.Mock).mockReset();
|
||||||
|
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(false);
|
||||||
|
|
||||||
i18nService.t.mockImplementation((key: string, ...args: any[]) => {
|
i18nService.t.mockImplementation((key: string, ...args: any[]) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "freeTrialEndPromptCount":
|
case "freeTrialEndPromptCount":
|
||||||
@@ -94,6 +99,7 @@ describe("OrganizationWarningsService", () => {
|
|||||||
{ provide: I18nService, useValue: i18nService },
|
{ provide: I18nService, useValue: i18nService },
|
||||||
{ provide: OrganizationApiServiceAbstraction, useValue: organizationApiService },
|
{ provide: OrganizationApiServiceAbstraction, useValue: organizationApiService },
|
||||||
{ provide: OrganizationBillingClient, useValue: organizationBillingClient },
|
{ provide: OrganizationBillingClient, useValue: organizationBillingClient },
|
||||||
|
{ provide: PlatformUtilsService, useValue: platformUtilsService },
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -111,6 +117,16 @@ describe("OrganizationWarningsService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return null when platform is self-hosted", (done) => {
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(true);
|
||||||
|
|
||||||
|
service.getFreeTrialWarning$(organization).subscribe((result) => {
|
||||||
|
expect(result).toBeNull();
|
||||||
|
expect(organizationBillingClient.getWarnings).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should return warning with count message when remaining trial days >= 2", (done) => {
|
it("should return warning with count message when remaining trial days >= 2", (done) => {
|
||||||
const warning = { remainingTrialDays: 5 };
|
const warning = { remainingTrialDays: 5 };
|
||||||
organizationBillingClient.getWarnings.mockResolvedValue({
|
organizationBillingClient.getWarnings.mockResolvedValue({
|
||||||
@@ -206,6 +222,16 @@ describe("OrganizationWarningsService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return null when platform is self-hosted", (done) => {
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(true);
|
||||||
|
|
||||||
|
service.getResellerRenewalWarning$(organization).subscribe((result) => {
|
||||||
|
expect(result).toBeNull();
|
||||||
|
expect(organizationBillingClient.getWarnings).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should return upcoming warning with correct type and message", (done) => {
|
it("should return upcoming warning with correct type and message", (done) => {
|
||||||
const renewalDate = new Date(2024, 11, 31);
|
const renewalDate = new Date(2024, 11, 31);
|
||||||
const warning = {
|
const warning = {
|
||||||
@@ -298,6 +324,16 @@ describe("OrganizationWarningsService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return null when platform is self-hosted", (done) => {
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(true);
|
||||||
|
|
||||||
|
service.getTaxIdWarning$(organization).subscribe((result) => {
|
||||||
|
expect(result).toBeNull();
|
||||||
|
expect(organizationBillingClient.getWarnings).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should return tax_id_missing type when tax ID is missing", (done) => {
|
it("should return tax_id_missing type when tax ID is missing", (done) => {
|
||||||
const warning = { type: TaxIdWarningTypes.Missing };
|
const warning = { type: TaxIdWarningTypes.Missing };
|
||||||
organizationBillingClient.getWarnings.mockResolvedValue({
|
organizationBillingClient.getWarnings.mockResolvedValue({
|
||||||
@@ -427,6 +463,16 @@ describe("OrganizationWarningsService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not show dialog when platform is self-hosted", (done) => {
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(true);
|
||||||
|
|
||||||
|
service.showInactiveSubscriptionDialog$(organization).subscribe(() => {
|
||||||
|
expect(dialogService.openSimpleDialog).not.toHaveBeenCalled();
|
||||||
|
expect(organizationBillingClient.getWarnings).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should show contact provider dialog for contact_provider resolution", (done) => {
|
it("should show contact provider dialog for contact_provider resolution", (done) => {
|
||||||
const warning = { resolution: "contact_provider" };
|
const warning = { resolution: "contact_provider" };
|
||||||
organizationBillingClient.getWarnings.mockResolvedValue({
|
organizationBillingClient.getWarnings.mockResolvedValue({
|
||||||
@@ -570,6 +616,18 @@ describe("OrganizationWarningsService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not show dialog when platform is self-hosted", (done) => {
|
||||||
|
platformUtilsService.isSelfHost.mockReturnValue(true);
|
||||||
|
|
||||||
|
service.showSubscribeBeforeFreeTrialEndsDialog$(organization).subscribe({
|
||||||
|
complete: () => {
|
||||||
|
expect(organizationApiService.getSubscription).not.toHaveBeenCalled();
|
||||||
|
expect(organizationBillingClient.getWarnings).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should open trial payment dialog when free trial warning exists", (done) => {
|
it("should open trial payment dialog when free trial warning exists", (done) => {
|
||||||
const warning = { remainingTrialDays: 2 };
|
const warning = { remainingTrialDays: 2 };
|
||||||
const subscription = { id: "sub-123" } as OrganizationSubscriptionResponse;
|
const subscription = { id: "sub-123" } as OrganizationSubscriptionResponse;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
map,
|
map,
|
||||||
merge,
|
merge,
|
||||||
Observable,
|
Observable,
|
||||||
|
of,
|
||||||
Subject,
|
Subject,
|
||||||
switchMap,
|
switchMap,
|
||||||
tap,
|
tap,
|
||||||
@@ -17,6 +18,7 @@ import { take } from "rxjs/operators";
|
|||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
import { OrganizationBillingClient } from "@bitwarden/web-vault/app/billing/clients";
|
import { OrganizationBillingClient } from "@bitwarden/web-vault/app/billing/clients";
|
||||||
@@ -56,6 +58,7 @@ export class OrganizationWarningsService {
|
|||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private organizationBillingClient: OrganizationBillingClient,
|
private organizationBillingClient: OrganizationBillingClient,
|
||||||
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -281,12 +284,17 @@ export class OrganizationWarningsService {
|
|||||||
organization: Organization,
|
organization: Organization,
|
||||||
extract: (response: OrganizationWarningsResponse) => T | null | undefined,
|
extract: (response: OrganizationWarningsResponse) => T | null | undefined,
|
||||||
bypassCache: boolean = false,
|
bypassCache: boolean = false,
|
||||||
): Observable<T | null> =>
|
): Observable<T | null> => {
|
||||||
this.readThroughWarnings$(organization, bypassCache).pipe(
|
if (this.platformUtilsService.isSelfHost()) {
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.readThroughWarnings$(organization, bypassCache).pipe(
|
||||||
map((response) => {
|
map((response) => {
|
||||||
const value = extract(response);
|
const value = extract(response);
|
||||||
return value ? value : null;
|
return value ? value : null;
|
||||||
}),
|
}),
|
||||||
take(1),
|
take(1),
|
||||||
);
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user