1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-11 05:53:42 +00:00
Files
browser/apps/web/src/app/platform/web-environment.service.ts
Justin Baur 804ad79877 Fix extra signalr connection web (#15633)
* Revert "fix(SignalR): Revert "[PM-23062] Fix extra signalr connections""

This reverts commit 97ec9a6339.

* Fix first login on web
2025-08-07 08:48:46 -04:00

123 lines
4.4 KiB
TypeScript

// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Router } from "@angular/router";
import { firstValueFrom, Observable, ReplaySubject } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import {
Environment,
Region,
RegionConfig,
Urls,
} from "@bitwarden/common/platform/abstractions/environment.service";
import {
CloudEnvironment,
DefaultEnvironmentService,
SelfHostedEnvironment,
} from "@bitwarden/common/platform/services/default-environment.service";
import { StateProvider } from "@bitwarden/common/platform/state";
import { UserId } from "@bitwarden/user-core";
export type WebRegionConfig = RegionConfig & {
key: Region | string; // strings are used for custom environments
domain: string;
urls: Urls;
};
/**
* Web specific environment service. Ensures that the urls are set from the window location.
*/
export class WebEnvironmentService extends DefaultEnvironmentService {
private _environmentSubject: ReplaySubject<Environment>;
constructor(
private win: Window,
stateProvider: StateProvider,
accountService: AccountService,
additionalRegionConfigs: WebRegionConfig[] = [],
private router: Router,
private envUrls: Urls,
) {
super(stateProvider, accountService, additionalRegionConfigs);
// The web vault always uses the current location as the base url
envUrls.base ??= this.win.location.origin;
// Find the region
const currentHostname = new URL(this.win.location.href).hostname;
const availableRegions = this.availableRegions();
const region = availableRegions.find((r) => {
// We must use hostname as our QA envs use the same
// domain (bitwarden.pw) but different subdomains (qa and euqa)
const webVaultHostname = new URL(r.urls.webVault).hostname;
return webVaultHostname === currentHostname;
});
let environment: Environment;
if (region) {
environment = new WebCloudEnvironment(region, envUrls);
} else {
environment = new SelfHostedEnvironment(envUrls);
}
// Override the environment observable with a replay subject
const subject = new ReplaySubject<Environment>(1);
subject.next(environment);
this._environmentSubject = subject;
this.environment$ = subject.asObservable();
this.globalEnvironment$ = subject.asObservable();
}
// Web setting env means navigating to a new location
async setEnvironment(region: Region | string, urls?: Urls): Promise<Urls> {
if (region === Region.SelfHosted) {
throw new Error("setEnvironment does not work in web for self-hosted.");
}
// Find the region
const currentHostname = new URL(this.win.location.href).hostname;
const availableRegions = this.availableRegions();
const currentRegionConfig = availableRegions.find((r) => {
// We must use hostname as our QA envs use the same
// domain (bitwarden.pw) but different subdomains (qa and euqa)
const webVaultHostname = new URL(r.urls.webVault).hostname;
return webVaultHostname === currentHostname;
});
if (currentRegionConfig.key === region) {
// They have selected the current region, return the current env urls
// We can't return the region urls because the env base url is modified
// in the constructor to match the current window.location.origin.
const currentEnv = await firstValueFrom(this.environment$);
return currentEnv.getUrls();
}
const chosenRegionConfig = this.availableRegions().find((r) => r.key === region);
if (chosenRegionConfig == null) {
throw new Error("The selected region is not known as an available region.");
}
// Preserve the current in app route + params in the new location
const routeAndParams = `/#${this.router.url}`;
this.win.location.href = chosenRegionConfig.urls.webVault + routeAndParams;
// This return shouldn't matter as we are about to leave the current window
return chosenRegionConfig.urls;
}
getEnvironment$(userId: UserId): Observable<Environment> {
// Web does not support account switching, and even if it did, you'd be required to be the environment of where the application
// is running.
return this._environmentSubject.asObservable();
}
}
export class WebCloudEnvironment extends CloudEnvironment {
constructor(config: RegionConfig, urls: Urls) {
super(config);
// We override the urls to avoid CORS issues
this.urls = urls;
}
}