diff --git a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.html b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.html index 400d34a184..d9f815c3e4 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.html +++ b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.html @@ -66,7 +66,7 @@ diff --git a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts index a8289db15c..06c474a6a1 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-selfhost.component.ts @@ -12,6 +12,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { OrganizationConnectionResponse } from "@bitwarden/common/admin-console/models/response/organization-connection.response"; import { BillingSyncConfigApi } from "@bitwarden/common/billing/models/api/billing-sync-config.api"; import { SelfHostedOrganizationSubscriptionView } from "@bitwarden/common/billing/models/view/self-hosted-organization-subscription.view"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -34,6 +35,7 @@ export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDest subscription: SelfHostedOrganizationSubscriptionView; organizationId: string; userOrg: Organization; + cloudWebVaultUrl: string; licenseOptions = LicenseOptions; form = new FormGroup({ @@ -82,8 +84,11 @@ export class OrganizationSubscriptionSelfhostComponent implements OnInit, OnDest private route: ActivatedRoute, private organizationApiService: OrganizationApiServiceAbstraction, private platformUtilsService: PlatformUtilsService, - private i18nService: I18nService - ) {} + private i18nService: I18nService, + private environmentService: EnvironmentService + ) { + this.cloudWebVaultUrl = this.environmentService.getCloudWebVaultUrl(); + } async ngOnInit() { this.route.params diff --git a/apps/web/src/app/billing/settings/user-subscription.component.html b/apps/web/src/app/billing/settings/user-subscription.component.html index 4aaece6cd8..4c600b421c 100644 --- a/apps/web/src/app/billing/settings/user-subscription.component.html +++ b/apps/web/src/app/billing/settings/user-subscription.component.html @@ -102,7 +102,7 @@ diff --git a/apps/web/src/app/billing/settings/user-subscription.component.ts b/apps/web/src/app/billing/settings/user-subscription.component.ts index 51bacdfd1e..278c39d22f 100644 --- a/apps/web/src/app/billing/settings/user-subscription.component.ts +++ b/apps/web/src/app/billing/settings/user-subscription.component.ts @@ -4,6 +4,7 @@ import { Router } from "@angular/router"; import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { SubscriptionResponse } from "@bitwarden/common/billing/models/response/subscription.response"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -22,6 +23,7 @@ export class UserSubscriptionComponent implements OnInit { showUpdateLicense = false; sub: SubscriptionResponse; selfHosted = false; + cloudWebVaultUrl: string; cancelPromise: Promise; reinstatePromise: Promise; @@ -34,9 +36,11 @@ export class UserSubscriptionComponent implements OnInit { private router: Router, private logService: LogService, private fileDownloadService: FileDownloadService, - private dialogService: DialogServiceAbstraction + private dialogService: DialogServiceAbstraction, + private environmentService: EnvironmentService ) { this.selfHosted = platformUtilsService.isSelfHost(); + this.cloudWebVaultUrl = this.environmentService.getCloudWebVaultUrl(); } async ngOnInit() { diff --git a/libs/common/src/platform/abstractions/environment.service.ts b/libs/common/src/platform/abstractions/environment.service.ts index 8d336084ba..bf91628caf 100644 --- a/libs/common/src/platform/abstractions/environment.service.ts +++ b/libs/common/src/platform/abstractions/environment.service.ts @@ -39,6 +39,19 @@ export abstract class EnvironmentService { hasBaseUrl: () => boolean; getNotificationsUrl: () => string; getWebVaultUrl: () => string; + /** + * Retrieves the URL of the cloud web vault app. + * + * @returns {string} The URL of the cloud web vault app. + * @remarks Use this method only in views exclusive to self-host instances. + */ + getCloudWebVaultUrl: () => string; + /** + * Sets the URL of the cloud web vault app based on the region parameter. + * + * @param {Region} region - The region of the cloud web vault app. + */ + setCloudWebVaultUrl: (region: Region) => void; getSendUrl: () => string; getIconsUrl: () => string; getApiUrl: () => string; diff --git a/libs/common/src/platform/models/data/server-config.data.spec.ts b/libs/common/src/platform/models/data/server-config.data.spec.ts index 30dc46cf1b..b94092662a 100644 --- a/libs/common/src/platform/models/data/server-config.data.spec.ts +++ b/libs/common/src/platform/models/data/server-config.data.spec.ts @@ -1,3 +1,5 @@ +import { Region } from "../../abstractions/environment.service"; + import { EnvironmentServerConfigData, ServerConfigData, @@ -15,6 +17,7 @@ describe("ServerConfigData", () => { url: "https://test.com", }, environment: { + cloudRegion: Region.EU, vault: "https://vault.com", api: "https://api.com", identity: "https://identity.com", diff --git a/libs/common/src/platform/models/data/server-config.data.ts b/libs/common/src/platform/models/data/server-config.data.ts index 574fa8c63a..a4819f7567 100644 --- a/libs/common/src/platform/models/data/server-config.data.ts +++ b/libs/common/src/platform/models/data/server-config.data.ts @@ -1,5 +1,6 @@ import { Jsonify } from "type-fest"; +import { Region } from "../../abstractions/environment.service"; import { ServerConfigResponse, ThirdPartyServerConfigResponse, @@ -50,6 +51,7 @@ export class ThirdPartyServerConfigData { } export class EnvironmentServerConfigData { + cloudRegion: Region; vault: string; api: string; identity: string; @@ -57,6 +59,7 @@ export class EnvironmentServerConfigData { sso: string; constructor(response: Partial) { + this.cloudRegion = response.cloudRegion; this.vault = response.vault; this.api = response.api; this.identity = response.identity; diff --git a/libs/common/src/platform/models/response/server-config.response.ts b/libs/common/src/platform/models/response/server-config.response.ts index c40d68293b..f611acf6f4 100644 --- a/libs/common/src/platform/models/response/server-config.response.ts +++ b/libs/common/src/platform/models/response/server-config.response.ts @@ -1,4 +1,5 @@ import { BaseResponse } from "../../../models/response/base.response"; +import { Region } from "../../abstractions/environment.service"; export class ServerConfigResponse extends BaseResponse { version: string; @@ -23,6 +24,7 @@ export class ServerConfigResponse extends BaseResponse { } export class EnvironmentServerConfigResponse extends BaseResponse { + cloudRegion: Region; vault: string; api: string; identity: string; @@ -36,6 +38,7 @@ export class EnvironmentServerConfigResponse extends BaseResponse { return; } + this.cloudRegion = this.getResponseProperty("CloudRegion"); this.vault = this.getResponseProperty("Vault"); this.api = this.getResponseProperty("Api"); this.identity = this.getResponseProperty("Identity"); diff --git a/libs/common/src/platform/services/config/config.service.ts b/libs/common/src/platform/services/config/config.service.ts index d1258c47a2..e03107d3b4 100644 --- a/libs/common/src/platform/services/config/config.service.ts +++ b/libs/common/src/platform/services/config/config.service.ts @@ -44,6 +44,7 @@ export class ConfigService implements ConfigServiceAbstraction { return serverConfig; } await this.stateService.setServerConfig(data); + this.environmentService.setCloudWebVaultUrl(data.environment?.cloudRegion); } } catch { return null; diff --git a/libs/common/src/platform/services/environment.service.ts b/libs/common/src/platform/services/environment.service.ts index 071335dada..188c633a03 100644 --- a/libs/common/src/platform/services/environment.service.ts +++ b/libs/common/src/platform/services/environment.service.ts @@ -23,6 +23,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { protected eventsUrl: string; private keyConnectorUrl: string; private scimUrl: string = null; + private cloudWebVaultUrl: string; readonly usUrls: Urls = { base: null, @@ -86,6 +87,26 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { return "https://vault.bitwarden.com"; } + getCloudWebVaultUrl() { + if (this.cloudWebVaultUrl != null) { + return this.cloudWebVaultUrl; + } + + return this.usUrls.webVault; + } + + setCloudWebVaultUrl(region: Region) { + switch (region) { + case Region.EU: + this.cloudWebVaultUrl = this.euUrls.webVault; + break; + case Region.US: + default: + this.cloudWebVaultUrl = this.usUrls.webVault; + break; + } + } + getSendUrl() { return this.getWebVaultUrl() === "https://vault.bitwarden.com" ? "https://send.bitwarden.com/#" @@ -239,6 +260,7 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { return { base: this.baseUrl, webVault: this.webVaultUrl, + cloudWebVault: this.cloudWebVaultUrl, api: this.apiUrl, identity: this.identityUrl, icons: this.iconsUrl,