[PM-8115] Desktop, Extension UI Refresh: Self-hosted Setup Dialog (#11597)

* Reimplement RegistrationSelfHostedEnvConfigDialogComponent

* Update EnvironmentSelectorComponent text based on feature flag.

* Initialize RegistrationSelfHostedEnvConfigDialog with existing values if self hosted

* Cleanup debug

* Add comment

* Remove changes to home and login components

* Remove changes to desktop login component

* Remove changes to browser home component

* Simplify accessing string.

* Add environment selector service.

* Cleanup unused imports in environment-selector

* Launch new env selector dialog from desktop

* Fix lint errors

* Address PR feedback: move dialog component, remove EnvironmentSelectorService, remove unused translation string

* Remove changes to AnonLayout

* PM-8115 - Export Re-usable component from Libs/auth for clean import elsewhere in clients.

* Remove unused accessingString variable

* Add success toast

---------

Co-authored-by: Jared Snider <jsnider@bitwarden.com>
This commit is contained in:
Alec Rippberger 2024-10-28 16:12:57 -05:00 committed by GitHub
parent 95e8e0c9bf
commit 9da80a6cba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 67 additions and 21 deletions

View File

@ -3234,9 +3234,6 @@
}
}
},
"loggingInOn": {
"message": "Logging in on"
},
"opensInANewWindow": {
"message": "Opens in a new window"
},

View File

@ -2804,9 +2804,6 @@
"message": "EU",
"description": "European Union"
},
"loggingInOn": {
"message": "Logging in on"
},
"selfHostedServer": {
"message": "self-hosted"
},

View File

@ -4,7 +4,7 @@
} as data"
>
<div class="environment-selector-btn">
{{ "loggingInOn" | i18n }}:
{{ "accessing" | i18n }}:
<button
type="button"
(click)="toggle(null)"

View File

@ -1,14 +1,19 @@
import { animate, state, style, transition, trigger } from "@angular/animations";
import { ConnectedPosition } from "@angular/cdk/overlay";
import { Component, EventEmitter, Output, Input, OnInit, OnDestroy } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router";
import { ActivatedRoute } from "@angular/router";
import { Observable, map, Subject, takeUntil } from "rxjs";
import { SelfHostedEnvConfigDialogComponent } from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import {
EnvironmentService,
Region,
RegionConfig,
} from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { DialogService, ToastService } from "@bitwarden/components";
export const ExtensionDefaultOverlayPosition: ConnectedPosition[] = [
{
@ -56,7 +61,7 @@ export interface EnvironmentSelectorRouteData {
],
})
export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
@Output() onOpenSelfHostedSettings = new EventEmitter();
@Output() onOpenSelfHostedSettings = new EventEmitter<void>();
@Input() overlayPosition: ConnectedPosition[] = [
{
originX: "start",
@ -79,8 +84,11 @@ export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
constructor(
protected environmentService: EnvironmentService,
protected router: Router,
private route: ActivatedRoute,
private dialogService: DialogService,
private configService: ConfigService,
private toastService: ToastService,
private i18nService: I18nService,
) {}
ngOnInit() {
@ -102,8 +110,25 @@ export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
return;
}
/**
* Opens the self-hosted settings dialog.
*
* If the `UnauthenticatedExtensionUIRefresh` feature flag is enabled,
* the self-hosted settings dialog is opened directly. Otherwise, the
* `onOpenSelfHostedSettings` event is emitted.
*/
if (option === Region.SelfHosted) {
this.onOpenSelfHostedSettings.emit();
if (await this.configService.getFeatureFlag(FeatureFlag.UnauthenticatedExtensionUIRefresh)) {
if (await SelfHostedEnvConfigDialogComponent.open(this.dialogService)) {
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("environmentSaved"),
});
}
} else {
this.onOpenSelfHostedSettings.emit();
}
return;
}

View File

@ -55,3 +55,6 @@ export * from "./lock/lock-component.service";
// vault timeout
export * from "./vault-timeout-input/vault-timeout-input.component";
// self hosted environment configuration dialog
export * from "./self-hosted-env-config-dialog/self-hosted-env-config-dialog.component";

View File

@ -15,7 +15,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { DialogService, FormFieldModule, SelectModule, ToastService } from "@bitwarden/components";
import { RegistrationSelfHostedEnvConfigDialogComponent } from "./registration-self-hosted-env-config-dialog.component";
import { SelfHostedEnvConfigDialogComponent } from "../../self-hosted-env-config-dialog/self-hosted-env-config-dialog.component";
/**
* Component for selecting the environment to register with in the email verification registration flow.
@ -125,9 +125,7 @@ export class RegistrationEnvSelectorComponent implements OnInit, OnDestroy {
}
if (selectedRegion === Region.SelfHosted) {
return from(
RegistrationSelfHostedEnvConfigDialogComponent.open(this.dialogService),
).pipe(
return from(SelfHostedEnvConfigDialogComponent.open(this.dialogService)).pipe(
tap((result: boolean | undefined) =>
this.handleSelfHostedEnvConfigDialogResult(result, prevSelectedRegion),
),

View File

@ -10,7 +10,7 @@ import {
ValidationErrors,
ValidatorFn,
} from "@angular/forms";
import { Subject, firstValueFrom } from "rxjs";
import { Subject, firstValueFrom, take, filter, takeUntil } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import {
@ -54,8 +54,8 @@ function selfHostedEnvSettingsFormValidator(): ValidatorFn {
*/
@Component({
standalone: true,
selector: "auth-registration-self-hosted-env-config-dialog",
templateUrl: "registration-self-hosted-env-config-dialog.component.html",
selector: "self-hosted-env-config-dialog",
templateUrl: "self-hosted-env-config-dialog.component.html",
imports: [
CommonModule,
JslibModule,
@ -68,14 +68,14 @@ function selfHostedEnvSettingsFormValidator(): ValidatorFn {
AsyncActionsModule,
],
})
export class RegistrationSelfHostedEnvConfigDialogComponent implements OnInit, OnDestroy {
export class SelfHostedEnvConfigDialogComponent implements OnInit, OnDestroy {
/**
* Opens the dialog.
* @param dialogService - Dialog service.
* @returns Promise that resolves to true if the dialog was closed with a successful result, false otherwise.
*/
static async open(dialogService: DialogService): Promise<boolean> {
const dialogRef = dialogService.open<boolean>(RegistrationSelfHostedEnvConfigDialogComponent, {
const dialogRef = dialogService.open<boolean>(SelfHostedEnvConfigDialogComponent, {
disableClose: false,
});
@ -131,7 +131,33 @@ export class RegistrationSelfHostedEnvConfigDialogComponent implements OnInit, O
private environmentService: EnvironmentService,
) {}
ngOnInit() {}
ngOnInit() {
/**
* Populate the form with the current self-hosted environment settings.
*/
this.environmentService.environment$
.pipe(
take(1),
filter((env) => {
const region = env.getRegion();
return region === Region.SelfHosted;
}),
takeUntil(this.destroy$),
)
.subscribe({
next: (env) => {
const urls = env.getUrls();
this.formGroup.patchValue({
baseUrl: urls.base || "",
webVaultUrl: urls.webVault || "",
apiUrl: urls.api || "",
identityUrl: urls.identity || "",
iconsUrl: urls.icons || "",
notificationsUrl: urls.notifications || "",
});
},
});
}
submit = async () => {
this.showErrorSummary = false;