diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 4592e295b8..b38a984dd9 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1971,10 +1971,28 @@ "organizationIsDisabled": { "message": "Organization is disabled." }, - "disabledOrganizationFilterError" : { + "disabledOrganizationFilterError": { "message" : "Items in disabled Organizations cannot be accessed. Contact your Organization owner for assistance." }, "cardBrandMir": { "message": "Mir" + }, + "loggingInTo": { + "message": "Logging in to $DOMAIN$", + "placeholders": { + "domain": { + "content": "$1", + "example": "example.com" + } + } + }, + "settingsEdited": { + "message": "Settings have been edited" + }, + "environmentEditedClick": { + "message": "Click here" + }, + "environmentEditedReset": { + "message": "to reset to pre-configured settings" } } diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 10bf24abe4..101b2e564b 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -6,7 +6,6 @@ import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/abs import { CollectionService as CollectionServiceAbstraction } from "@bitwarden/common/abstractions/collection.service"; import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service"; -import { EnvironmentService as EnvironmentServiceAbstraction } from "@bitwarden/common/abstractions/environment.service"; import { EventService as EventServiceAbstraction } from "@bitwarden/common/abstractions/event.service"; import { ExportService as ExportServiceAbstraction } from "@bitwarden/common/abstractions/export.service"; import { FileUploadService as FileUploadServiceAbstraction } from "@bitwarden/common/abstractions/fileUpload.service"; @@ -50,7 +49,6 @@ import { CollectionService } from "@bitwarden/common/services/collection.service import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service"; import { ContainerService } from "@bitwarden/common/services/container.service"; import { EncryptService } from "@bitwarden/common/services/encrypt.service"; -import { EnvironmentService } from "@bitwarden/common/services/environment.service"; import { EventService } from "@bitwarden/common/services/event.service"; import { ExportService } from "@bitwarden/common/services/export.service"; import { FileUploadService } from "@bitwarden/common/services/fileUpload.service"; @@ -84,6 +82,7 @@ import { PopupUtilsService } from "../popup/services/popup-utils.service"; import { AutofillService as AutofillServiceAbstraction } from "../services/abstractions/autofill.service"; import { StateService as StateServiceAbstraction } from "../services/abstractions/state.service"; import AutofillService from "../services/autofill.service"; +import { BrowserEnvironmentService } from "../services/browser-environment.service"; import { BrowserCryptoService } from "../services/browserCrypto.service"; import BrowserLocalStorageService from "../services/browserLocalStorage.service"; import BrowserMessagingService from "../services/browserMessaging.service"; @@ -119,7 +118,7 @@ export default class MainBackground { tokenService: TokenServiceAbstraction; appIdService: AppIdServiceAbstraction; apiService: ApiServiceAbstraction; - environmentService: EnvironmentServiceAbstraction; + environmentService: BrowserEnvironmentService; settingsService: SettingsServiceAbstraction; cipherService: CipherServiceAbstraction; folderService: InternalFolderServiceAbstraction; @@ -253,7 +252,7 @@ export default class MainBackground { ); this.tokenService = new TokenService(this.stateService); this.appIdService = new AppIdService(this.storageService); - this.environmentService = new EnvironmentService(this.stateService); + this.environmentService = new BrowserEnvironmentService(this.stateService, this.logService); this.apiService = new ApiService( this.tokenService, this.platformUtilsService, diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts index e7e06e5c41..bb84fb4f0e 100644 --- a/apps/browser/src/background/runtime.background.ts +++ b/apps/browser/src/background/runtime.background.ts @@ -1,4 +1,3 @@ -import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; @@ -6,6 +5,8 @@ import { NotificationsService } from "@bitwarden/common/abstractions/notificatio import { SystemService } from "@bitwarden/common/abstractions/system.service"; import { Utils } from "@bitwarden/common/misc/utils"; +import { BrowserEnvironmentService } from "src/services/browser-environment.service"; + import { BrowserApi } from "../browser/browserApi"; import { AutofillService } from "../services/abstractions/autofill.service"; import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service"; @@ -26,7 +27,7 @@ export default class RuntimeBackground { private i18nService: I18nService, private notificationsService: NotificationsService, private systemService: SystemService, - private environmentService: EnvironmentService, + private environmentService: BrowserEnvironmentService, private messagingService: MessagingService, private logService: LogService ) { @@ -227,6 +228,10 @@ export default class RuntimeBackground { if (this.onInstalledReason != null) { if (this.onInstalledReason === "install") { BrowserApi.createNewTab("https://bitwarden.com/browser-start/"); + + if (await this.environmentService.hasManagedEnvironment()) { + await this.environmentService.setUrlsToManagedEnvironment(); + } } this.onInstalledReason = null; diff --git a/apps/browser/src/managed_schema.json b/apps/browser/src/managed_schema.json new file mode 100644 index 0000000000..45469d2a90 --- /dev/null +++ b/apps/browser/src/managed_schema.json @@ -0,0 +1,20 @@ +{ + "type": "object", + "properties": { + "environment": { + "type": "object", + "properties": { + "base": { + "type": "string", + "description": "Base url, typically only this value needs to be set" + }, + "webVault": { "type": "string" }, + "api": { "type": "string" }, + "identity": { "type": "string" }, + "icons": { "type": "string" }, + "notifications": { "type": "string" }, + "events": { "type": "string" } + } + } + } +} diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index 546bd8501d..5bad5737fc 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -119,5 +119,8 @@ "default_title": "Bitwarden", "default_panel": "popup/index.html?uilocation=sidebar", "default_icon": "images/icon19.png" + }, + "storage": { + "managed_schema": "managed_schema.json" } } diff --git a/apps/browser/src/popup/accounts/environment.component.html b/apps/browser/src/popup/accounts/environment.component.html index a23de6ff56..3b998d1703 100644 --- a/apps/browser/src/popup/accounts/environment.component.html +++ b/apps/browser/src/popup/accounts/environment.component.html @@ -14,6 +14,17 @@
+ + + {{ "environmentEditedClick" | i18n }} + + {{ "environmentEditedReset" | i18n }} + +

{{ "selfHostedEnvironment" | i18n }} diff --git a/apps/browser/src/popup/accounts/environment.component.ts b/apps/browser/src/popup/accounts/environment.component.ts index f4004b5c7d..3b58ccfa1d 100644 --- a/apps/browser/src/popup/accounts/environment.component.ts +++ b/apps/browser/src/popup/accounts/environment.component.ts @@ -1,19 +1,22 @@ -import { Component } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { Router } from "@angular/router"; import { EnvironmentComponent as BaseEnvironmentComponent } from "@bitwarden/angular/components/environment.component"; -import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; +import { BrowserEnvironmentService } from "../../services/browser-environment.service"; + @Component({ selector: "app-environment", templateUrl: "environment.component.html", }) -export class EnvironmentComponent extends BaseEnvironmentComponent { +export class EnvironmentComponent extends BaseEnvironmentComponent implements OnInit { + showEditedManagedSettings = false; + constructor( platformUtilsService: PlatformUtilsService, - environmentService: EnvironmentService, + public environmentService: BrowserEnvironmentService, i18nService: I18nService, private router: Router ) { @@ -21,6 +24,22 @@ export class EnvironmentComponent extends BaseEnvironmentComponent { this.showCustom = true; } + async ngOnInit() { + this.showEditedManagedSettings = await this.environmentService.settingsHaveChanged(); + } + + async resetEnvironment() { + const urls = await this.environmentService.getManagedEnvironment(); + + this.baseUrl = urls.base; + this.webVaultUrl = urls.webVault; + this.apiUrl = urls.api; + this.iconsUrl = urls.icons; + this.identityUrl = urls.identity; + this.notificationsUrl = urls.notifications; + this.iconsUrl = urls.icons; + } + saved() { super.saved(); this.router.navigate([""]); diff --git a/apps/browser/src/popup/accounts/login.component.html b/apps/browser/src/popup/accounts/login.component.html index 281df83509..4c18805f45 100644 --- a/apps/browser/src/popup/accounts/login.component.html +++ b/apps/browser/src/popup/accounts/login.component.html @@ -63,6 +63,9 @@

+

+ {{ "loggingInTo" | i18n: selfHostedDomain }} +

diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 925de8721f..7ed102b168 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -56,6 +56,7 @@ import MainBackground from "../../background/main.background"; import { BrowserApi } from "../../browser/browserApi"; import { AutofillService } from "../../services/abstractions/autofill.service"; import { StateService as StateServiceAbstraction } from "../../services/abstractions/state.service"; +import { BrowserEnvironmentService } from "../../services/browser-environment.service"; import { BrowserFileDownloadService } from "../../services/browserFileDownloadService"; import BrowserMessagingService from "../../services/browserMessaging.service"; import BrowserMessagingPrivateModePopupService from "../../services/browserMessagingPrivateModePopup.service"; @@ -172,6 +173,10 @@ function getBgService(service: keyof MainBackground) { useFactory: getBgService("logService"), deps: [], }, + { + provide: BrowserEnvironmentService, + useExisting: EnvironmentService, + }, { provide: EnvironmentService, useFactory: getBgService("environmentService"), diff --git a/apps/browser/src/services/browser-environment.service.ts b/apps/browser/src/services/browser-environment.service.ts new file mode 100644 index 0000000000..0fff387e64 --- /dev/null +++ b/apps/browser/src/services/browser-environment.service.ts @@ -0,0 +1,67 @@ +import { LogService } from "@bitwarden/common/abstractions/log.service"; +import { StateService } from "@bitwarden/common/abstractions/state.service"; +import { EnvironmentService } from "@bitwarden/common/services/environment.service"; + +type GroupPolicyEnvironment = { + base?: string; + webVault?: string; + api?: string; + identity?: string; + icons?: string; + notifications?: string; + events?: string; +}; + +export class BrowserEnvironmentService extends EnvironmentService { + constructor(stateService: StateService, private logService: LogService) { + super(stateService); + } + + async hasManagedEnvironment(): Promise { + try { + return (await this.getManagedEnvironment()) != null; + } catch (e) { + this.logService.error(e); + return false; + } + } + + async settingsHaveChanged() { + const env = await this.getManagedEnvironment(); + + return ( + env.base != this.baseUrl || + env.webVault != this.webVaultUrl || + env.api != this.webVaultUrl || + env.identity != this.identityUrl || + env.icons != this.iconsUrl || + env.notifications != this.notificationsUrl || + env.events != this.eventsUrl + ); + } + + getManagedEnvironment(): Promise { + return new Promise((resolve, reject) => { + chrome.storage.managed.get("environment", (result) => { + if (chrome.runtime.lastError) { + return reject(chrome.runtime.lastError); + } + + resolve(result.environment); + }); + }); + } + + async setUrlsToManagedEnvironment() { + const env = await this.getManagedEnvironment(); + await this.setUrls({ + base: env.base, + webVault: env.webVault, + api: env.api, + identity: env.identity, + icons: env.icons, + notifications: env.notifications, + events: env.events, + }); + } +} diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index cd9ecdd9ea..e4cc10060a 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -85,6 +85,7 @@ const plugins = [ manifestVersion == 3 ? { from: "./src/manifest.v3.json", to: "manifest.json" } : "./src/manifest.json", + { from: "./src/managed_schema.json", to: "managed_schema.json" }, { from: "./src/_locales", to: "_locales" }, { from: "./src/images", to: "images" }, { from: "./src/popup/images", to: "popup/images" }, diff --git a/libs/angular/src/components/login.component.ts b/libs/angular/src/components/login.component.ts index c784a0aa06..259fce5a65 100644 --- a/libs/angular/src/components/login.component.ts +++ b/libs/angular/src/components/login.component.ts @@ -49,6 +49,10 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit super(environmentService, i18nService, platformUtilsService); } + get selfHostedDomain() { + return this.environmentService.hasBaseUrl() ? this.environmentService.getWebVaultUrl() : null; + } + async ngOnInit() { if (this.email == null || this.email === "") { this.email = await this.stateService.getRememberedEmail(); diff --git a/libs/common/src/services/environment.service.ts b/libs/common/src/services/environment.service.ts index c22d7d85e6..271fb87c45 100644 --- a/libs/common/src/services/environment.service.ts +++ b/libs/common/src/services/environment.service.ts @@ -11,13 +11,13 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { private readonly urlsSubject = new Subject(); urls: Observable = this.urlsSubject; - private baseUrl: string; - private webVaultUrl: string; - private apiUrl: string; - private identityUrl: string; - private iconsUrl: string; - private notificationsUrl: string; - private eventsUrl: string; + protected baseUrl: string; + protected webVaultUrl: string; + protected apiUrl: string; + protected identityUrl: string; + protected iconsUrl: string; + protected notificationsUrl: string; + protected eventsUrl: string; private keyConnectorUrl: string; private scimUrl: string = null;