From 83cc7d33f2efed0e3647d40cd8662f8f00ae10fe Mon Sep 17 00:00:00 2001 From: Thomas Avery Date: Tue, 27 Jan 2026 16:10:09 -0600 Subject: [PATCH] Remove legacy components --- .../app/settings/preferences.component.html | 90 ------ .../src/app/settings/preferences.component.ts | 239 -------------- libs/key-management-ui/src/index.ts | 1 - ...ession-timeout-input-legacy.component.html | 47 --- .../session-timeout-input-legacy.component.ts | 296 ------------------ 5 files changed, 673 deletions(-) delete mode 100644 apps/web/src/app/settings/preferences.component.html delete mode 100644 apps/web/src/app/settings/preferences.component.ts delete mode 100644 libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.html delete mode 100644 libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.ts diff --git a/apps/web/src/app/settings/preferences.component.html b/apps/web/src/app/settings/preferences.component.html deleted file mode 100644 index cdcb8973602..00000000000 --- a/apps/web/src/app/settings/preferences.component.html +++ /dev/null @@ -1,90 +0,0 @@ - - - -

{{ "preferencesDesc" | i18n }}

-
- - - {{ - "vaultTimeoutPolicyWithActionInEffect" - | i18n: policy.timeout.hours : policy.timeout.minutes : (policy.action | i18n) - }} - - - {{ "vaultTimeoutPolicyInEffect" | i18n: policy.timeout.hours : policy.timeout.minutes }} - - - {{ "vaultTimeoutActionPolicyInEffect" | i18n: (policy.action | i18n) }} - - - - - - - {{ "vaultTimeoutAction" | i18n }} - - {{ "lock" | i18n }} - {{ "vaultTimeoutActionLockDesc" | i18n }} - - - {{ "logOut" | i18n }} - {{ "vaultTimeoutActionLogOutDesc" | i18n }} - - - - - - {{ "language" | i18n }} - - - - - - - - {{ "languageDesc" | i18n }} - -
- - - - {{ "showIconsChangePasswordUrls" | i18n }} - - -
- -
-
- - {{ "theme" | i18n }} - - - - {{ "themeDesc" | i18n }} - - -
-
diff --git a/apps/web/src/app/settings/preferences.component.ts b/apps/web/src/app/settings/preferences.component.ts deleted file mode 100644 index 03540232e02..00000000000 --- a/apps/web/src/app/settings/preferences.component.ts +++ /dev/null @@ -1,239 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { Component, OnDestroy, OnInit } from "@angular/core"; -import { FormBuilder } from "@angular/forms"; -import { - concatMap, - filter, - firstValueFrom, - map, - Observable, - Subject, - switchMap, - takeUntil, - tap, -} from "rxjs"; - -import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; -import { PolicyType } from "@bitwarden/common/admin-console/enums"; -import { getFirstPolicy } from "@bitwarden/common/admin-console/services/policy/default-policy.service"; -import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; -import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; -import { - VaultTimeout, - VaultTimeoutAction, - VaultTimeoutOption, - VaultTimeoutSettingsService, - VaultTimeoutStringType, -} from "@bitwarden/common/key-management/vault-timeout"; -import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums"; -import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; -import { DialogService } from "@bitwarden/components"; -import { SessionTimeoutInputLegacyComponent } from "@bitwarden/key-management-ui"; -import { PermitCipherDetailsPopoverComponent } from "@bitwarden/vault"; - -import { HeaderModule } from "../layouts/header/header.module"; -import { SharedModule } from "../shared"; - -/** - * @deprecated Use {@link AppearanceComponent} and {@link SessionTimeoutComponent} instead. - * - * TODO Cleanup once feature flag enabled: https://bitwarden.atlassian.net/browse/PM-27297 - */ -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection -@Component({ - selector: "app-preferences", - templateUrl: "preferences.component.html", - imports: [ - SharedModule, - HeaderModule, - PermitCipherDetailsPopoverComponent, - SessionTimeoutInputLegacyComponent, - ], -}) -export class PreferencesComponent implements OnInit, OnDestroy { - // For use in template - protected readonly VaultTimeoutAction = VaultTimeoutAction; - - protected availableVaultTimeoutActions$: Observable; - - vaultTimeoutPolicyCallout: Observable<{ - timeout: { hours: number; minutes: number }; - action: VaultTimeoutAction; - }>; - vaultTimeoutOptions: VaultTimeoutOption[]; - localeOptions: any[]; - themeOptions: any[]; - - private startingLocale: string; - private destroy$ = new Subject(); - - form = this.formBuilder.group({ - vaultTimeout: [null as VaultTimeout | null], - vaultTimeoutAction: [VaultTimeoutAction.Lock], - enableFavicons: true, - theme: [ThemeTypes.Light as Theme], - locale: [null as string | null], - }); - - constructor( - private formBuilder: FormBuilder, - private policyService: PolicyService, - private i18nService: I18nService, - private vaultTimeoutSettingsService: VaultTimeoutSettingsService, - private platformUtilsService: PlatformUtilsService, - private themeStateService: ThemeStateService, - private domainSettingsService: DomainSettingsService, - private dialogService: DialogService, - private accountService: AccountService, - ) { - this.vaultTimeoutOptions = [ - { name: i18nService.t("oneMinute"), value: 1 }, - { name: i18nService.t("fiveMinutes"), value: 5 }, - { name: i18nService.t("fifteenMinutes"), value: 15 }, - { name: i18nService.t("thirtyMinutes"), value: 30 }, - { name: i18nService.t("oneHour"), value: 60 }, - { name: i18nService.t("fourHours"), value: 240 }, - { name: i18nService.t("onRefresh"), value: VaultTimeoutStringType.OnRestart }, - ]; - if (this.platformUtilsService.isDev()) { - this.vaultTimeoutOptions.push({ - name: i18nService.t("never"), - value: VaultTimeoutStringType.Never, - }); - } - - const localeOptions: any[] = []; - i18nService.supportedTranslationLocales.forEach((locale) => { - let name = locale; - if (i18nService.localeNames.has(locale)) { - name += " - " + i18nService.localeNames.get(locale); - } - localeOptions.push({ name: name, value: locale }); - }); - localeOptions.sort(Utils.getSortFunction(i18nService, "name")); - localeOptions.splice(0, 0, { name: i18nService.t("default"), value: null }); - this.localeOptions = localeOptions; - this.themeOptions = [ - { name: i18nService.t("themeLight"), value: ThemeTypes.Light }, - { name: i18nService.t("themeDark"), value: ThemeTypes.Dark }, - { name: i18nService.t("themeSystem"), value: ThemeTypes.System }, - ]; - } - - async ngOnInit() { - this.availableVaultTimeoutActions$ = - this.vaultTimeoutSettingsService.availableVaultTimeoutActions$(); - - this.vaultTimeoutPolicyCallout = this.accountService.activeAccount$.pipe( - getUserId, - switchMap((userId) => - this.policyService.policiesByType$(PolicyType.MaximumVaultTimeout, userId), - ), - getFirstPolicy, - filter((policy) => policy != null), - map((policy) => { - let timeout; - if (policy.data?.minutes) { - timeout = { - hours: Math.floor(policy.data?.minutes / 60), - minutes: policy.data?.minutes % 60, - }; - } - return { timeout: timeout, action: policy.data?.action }; - }), - tap((policy) => { - if (policy.action) { - this.form.controls.vaultTimeoutAction.disable({ emitEvent: false }); - } else { - this.form.controls.vaultTimeoutAction.enable({ emitEvent: false }); - } - }), - ); - - this.form.controls.vaultTimeoutAction.valueChanges - .pipe( - concatMap(async (action) => { - if (action === VaultTimeoutAction.LogOut) { - const confirmed = await this.dialogService.openSimpleDialog({ - title: { key: "vaultTimeoutLogOutConfirmationTitle" }, - content: { key: "vaultTimeoutLogOutConfirmation" }, - type: "warning", - }); - - if (!confirmed) { - this.form.controls.vaultTimeoutAction.patchValue(VaultTimeoutAction.Lock, { - emitEvent: false, - }); - return; - } - } - }), - takeUntil(this.destroy$), - ) - .subscribe(); - - const activeAcct = await firstValueFrom(this.accountService.activeAccount$); - - const initialFormValues = { - vaultTimeout: await firstValueFrom( - this.vaultTimeoutSettingsService.getVaultTimeoutByUserId$(activeAcct.id), - ), - vaultTimeoutAction: await firstValueFrom( - this.vaultTimeoutSettingsService.getVaultTimeoutActionByUserId$(activeAcct.id), - ), - enableFavicons: await firstValueFrom(this.domainSettingsService.showFavicons$), - theme: await firstValueFrom(this.themeStateService.selectedTheme$), - locale: (await firstValueFrom(this.i18nService.userSetLocale$)) ?? null, - }; - this.startingLocale = initialFormValues.locale; - this.form.setValue(initialFormValues, { emitEvent: false }); - } - - submit = async () => { - if (!this.form.controls.vaultTimeout.valid) { - this.platformUtilsService.showToast( - "error", - null, - this.i18nService.t("vaultTimeoutRangeError"), - ); - return; - } - - // must get raw value b/c the vault timeout action is disabled when a policy is applied - // which removes the timeout action property and value from the normal form.value. - const values = this.form.getRawValue(); - - const activeAcct = await firstValueFrom(this.accountService.activeAccount$); - - await this.vaultTimeoutSettingsService.setVaultTimeoutOptions( - activeAcct.id, - values.vaultTimeout, - values.vaultTimeoutAction, - ); - - // Save other preferences (theme, locale, favicons) - await this.domainSettingsService.setShowFavicons(values.enableFavicons); - await this.themeStateService.setSelectedTheme(values.theme); - await this.i18nService.setLocale(values.locale); - if (values.locale !== this.startingLocale) { - window.location.reload(); - } else { - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("preferencesUpdated"), - ); - } - }; - - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); - } -} diff --git a/libs/key-management-ui/src/index.ts b/libs/key-management-ui/src/index.ts index 7b9d5a629ac..19df93c9e49 100644 --- a/libs/key-management-ui/src/index.ts +++ b/libs/key-management-ui/src/index.ts @@ -14,4 +14,3 @@ export { ConfirmKeyConnectorDomainComponent } from "./key-connector/confirm-key- export { SessionTimeoutSettingsComponent } from "./session-timeout/components/session-timeout-settings.component"; export { SessionTimeoutSettingsComponentService } from "./session-timeout/services/session-timeout-settings-component.service"; export { SessionTimeoutInputComponent } from "./session-timeout/components/session-timeout-input.component"; -export { SessionTimeoutInputLegacyComponent } from "./session-timeout/components/session-timeout-input-legacy.component"; diff --git a/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.html b/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.html deleted file mode 100644 index 4f1b27a8127..00000000000 --- a/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.html +++ /dev/null @@ -1,47 +0,0 @@ -
- - {{ "vaultTimeout1" | i18n }} - - - - -
- - - {{ "hours" | i18n }} - - - - {{ "minutes" | i18n }} - -
- - {{ "vaultTimeoutPolicyInEffect1" | i18n: vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes }} - - - {{ "vaultCustomTimeoutMinimum" | i18n }} - - - - {{ - "vaultTimeoutPolicyMaximumError" | i18n: vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes - }} - -
diff --git a/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.ts b/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.ts deleted file mode 100644 index 22a53f6a53e..00000000000 --- a/libs/key-management-ui/src/session-timeout/components/session-timeout-input-legacy.component.ts +++ /dev/null @@ -1,296 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { CommonModule } from "@angular/common"; -import { Component, Input, OnChanges, OnDestroy, OnInit } from "@angular/core"; -import { - AbstractControl, - ControlValueAccessor, - FormBuilder, - FormControl, - FormGroup, - NG_VALIDATORS, - NG_VALUE_ACCESSOR, - ReactiveFormsModule, - ValidationErrors, - Validator, -} from "@angular/forms"; -import { filter, map, Observable, Subject, switchMap, takeUntil } from "rxjs"; - -import { JslibModule } from "@bitwarden/angular/jslib.module"; -import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; -import { PolicyType } from "@bitwarden/common/admin-console/enums"; -import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; -import { getFirstPolicy } from "@bitwarden/common/admin-console/services/policy/default-policy.service"; -import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; -import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { - VaultTimeout, - VaultTimeoutAction, - VaultTimeoutOption, - VaultTimeoutSettingsService, -} from "@bitwarden/common/key-management/vault-timeout"; -import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { FormFieldModule, SelectModule } from "@bitwarden/components"; - -type VaultTimeoutForm = FormGroup<{ - vaultTimeout: FormControl; - custom: FormGroup<{ - hours: FormControl; - minutes: FormControl; - }>; -}>; - -type VaultTimeoutFormValue = VaultTimeoutForm["value"]; - -/** - * @deprecated Use {@link SessionTimeoutInputComponent} instead. - * - * TODO Cleanup once feature flag enabled: https://bitwarden.atlassian.net/browse/PM-27297 - */ -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection -@Component({ - selector: "bit-session-timeout-input-legacy", - templateUrl: "session-timeout-input-legacy.component.html", - imports: [CommonModule, JslibModule, ReactiveFormsModule, FormFieldModule, SelectModule], - providers: [ - { - provide: NG_VALUE_ACCESSOR, - multi: true, - useExisting: SessionTimeoutInputLegacyComponent, - }, - { - provide: NG_VALIDATORS, - multi: true, - useExisting: SessionTimeoutInputLegacyComponent, - }, - ], -}) -export class SessionTimeoutInputLegacyComponent - implements ControlValueAccessor, Validator, OnInit, OnDestroy, OnChanges -{ - static CUSTOM_VALUE = -100; - static MIN_CUSTOM_MINUTES = 0; - form: VaultTimeoutForm = this.formBuilder.group({ - vaultTimeout: [null], - custom: this.formBuilder.group({ - hours: [null], - minutes: [null], - }), - }); - - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() vaultTimeoutOptions: VaultTimeoutOption[]; - - vaultTimeoutPolicy: Policy; - vaultTimeoutPolicyHours: number; - vaultTimeoutPolicyMinutes: number; - - protected readonly VaultTimeoutAction = VaultTimeoutAction; - - protected canLockVault$: Observable; - private onChange: (vaultTimeout: VaultTimeout) => void; - private validatorChange: () => void; - private destroy$ = new Subject(); - - constructor( - private formBuilder: FormBuilder, - private policyService: PolicyService, - private vaultTimeoutSettingsService: VaultTimeoutSettingsService, - private i18nService: I18nService, - private accountService: AccountService, - ) {} - - get showCustom() { - return this.form.get("vaultTimeout").value === SessionTimeoutInputLegacyComponent.CUSTOM_VALUE; - } - - get exceedsMinimumTimeout(): boolean { - return ( - !this.showCustom || - this.customTimeInMinutes() > SessionTimeoutInputLegacyComponent.MIN_CUSTOM_MINUTES - ); - } - - get exceedsMaximumTimeout(): boolean { - return ( - this.showCustom && - this.customTimeInMinutes() > - this.vaultTimeoutPolicyMinutes + 60 * this.vaultTimeoutPolicyHours - ); - } - - get filteredVaultTimeoutOptions(): VaultTimeoutOption[] { - // by policy max value - if (this.vaultTimeoutPolicy == null || this.vaultTimeoutPolicy.data == null) { - return this.vaultTimeoutOptions; - } - - return this.vaultTimeoutOptions.filter((option) => { - if (typeof option.value === "number") { - return option.value <= this.vaultTimeoutPolicy.data.minutes; - } - - return false; - }); - } - - async ngOnInit() { - this.accountService.activeAccount$ - .pipe( - getUserId, - switchMap((userId) => - this.policyService.policiesByType$(PolicyType.MaximumVaultTimeout, userId), - ), - getFirstPolicy, - filter((policy) => policy != null), - takeUntil(this.destroy$), - ) - .subscribe((policy) => { - this.vaultTimeoutPolicy = policy; - this.applyVaultTimeoutPolicy(); - }); - this.form.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe((value: VaultTimeoutFormValue) => { - if (this.onChange) { - this.onChange(this.getVaultTimeout(value)); - } - }); - - // Assign the current value to the custom fields - // so that if the user goes from a numeric value to custom - // we can initialize the custom fields with the current value - // ex: user picks 5 min, goes to custom, we want to show 0 hr, 5 min in the custom fields - this.form.controls.vaultTimeout.valueChanges - .pipe( - filter((value) => value !== SessionTimeoutInputLegacyComponent.CUSTOM_VALUE), - takeUntil(this.destroy$), - ) - .subscribe((value) => { - const current = typeof value === "string" ? 0 : Math.max(value, 0); - - // This cannot emit an event b/c it would cause form.valueChanges to fire again - // and we are already handling that above so just silently update - // custom fields when vaultTimeout changes to a non-custom value - this.form.patchValue( - { - custom: { - hours: Math.floor(current / 60), - minutes: current % 60, - }, - }, - { emitEvent: false }, - ); - }); - - this.canLockVault$ = this.vaultTimeoutSettingsService - .availableVaultTimeoutActions$() - .pipe(map((actions) => actions.includes(VaultTimeoutAction.Lock))); - } - - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); - } - - ngOnChanges() { - if ( - !this.vaultTimeoutOptions.find( - (p) => p.value === SessionTimeoutInputLegacyComponent.CUSTOM_VALUE, - ) - ) { - this.vaultTimeoutOptions.push({ - name: this.i18nService.t("custom"), - value: SessionTimeoutInputLegacyComponent.CUSTOM_VALUE, - }); - } - } - - getVaultTimeout(value: VaultTimeoutFormValue) { - if (value.vaultTimeout !== SessionTimeoutInputLegacyComponent.CUSTOM_VALUE) { - return value.vaultTimeout; - } - - return value.custom.hours * 60 + value.custom.minutes; - } - - writeValue(value: number): void { - if (value == null) { - return; - } - - if (this.vaultTimeoutOptions.every((p) => p.value !== value)) { - this.form.setValue({ - vaultTimeout: SessionTimeoutInputLegacyComponent.CUSTOM_VALUE, - custom: { - hours: Math.floor(value / 60), - minutes: value % 60, - }, - }); - return; - } - - this.form.patchValue({ - vaultTimeout: value, - }); - } - - registerOnChange(onChange: any): void { - this.onChange = onChange; - } - - registerOnTouched(onTouched: any): void { - // Empty - } - - setDisabledState?(isDisabled: boolean): void { - // Empty - } - - validate(control: AbstractControl): ValidationErrors { - if (this.vaultTimeoutPolicy && this.vaultTimeoutPolicy?.data?.minutes < control.value) { - return { policyError: true }; - } - - if (!this.exceedsMinimumTimeout) { - return { minTimeoutError: true }; - } - - return null; - } - - registerOnValidatorChange(fn: () => void): void { - this.validatorChange = fn; - } - - private customTimeInMinutes() { - return this.form.value.custom.hours * 60 + this.form.value.custom.minutes; - } - - private applyVaultTimeoutPolicy() { - this.vaultTimeoutPolicyHours = Math.floor(this.vaultTimeoutPolicy.data.minutes / 60); - this.vaultTimeoutPolicyMinutes = this.vaultTimeoutPolicy.data.minutes % 60; - - this.vaultTimeoutOptions = this.vaultTimeoutOptions.filter((vaultTimeoutOption) => { - // Always include the custom option - if (vaultTimeoutOption.value === SessionTimeoutInputLegacyComponent.CUSTOM_VALUE) { - return true; - } - - if (typeof vaultTimeoutOption.value === "number") { - // Include numeric values that are less than or equal to the policy minutes - return vaultTimeoutOption.value <= this.vaultTimeoutPolicy.data.minutes; - } - - // Exclude all string cases when there's a numeric policy defined - return false; - }); - - // Only call validator change if it's been set - if (this.validatorChange) { - this.validatorChange(); - } - } -}