diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index bd62b825e79..493a909f8ac 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -374,12 +374,21 @@ "other": { "message": "Other" }, + "unlockMethods": { + "message": "Unlock options" + }, "unlockMethodNeededToChangeTimeoutActionDesc": { "message": "Set up an unlock method to change your vault timeout action." }, "unlockMethodNeeded": { "message": "Set up an unlock method in Settings" }, + "sessionTimeoutHeader": { + "message": "Session timeout" + }, + "otherOptions": { + "message": "Other options" + }, "rateExtension": { "message": "Rate the extension" }, @@ -3023,6 +3032,9 @@ "adminConsole": { "message": "Admin Console" }, + "accountSecurity": { + "message": "Account security" + }, "errorAssigningTargetCollection": { "message": "Error assigning target collection." }, diff --git a/apps/browser/src/auth/popup/settings/account-security.component.html b/apps/browser/src/auth/popup/settings/account-security.component.html new file mode 100644 index 00000000000..dff9675743f --- /dev/null +++ b/apps/browser/src/auth/popup/settings/account-security.component.html @@ -0,0 +1,140 @@ + +
+ +
+

+ {{ "accountSecurity" | i18n }} +

+
+ +
+
+
+
+

{{ "unlockMethods" | i18n }}

+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+

{{ "sessionTimeoutHeader" | 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) }} + + + + +
+ + +
+ +
+
+
+

{{ "otherOptions" | i18n }}

+
+ + + + + +
+
+
diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/auth/popup/settings/account-security.component.ts similarity index 83% rename from apps/browser/src/popup/settings/settings.component.ts rename to apps/browser/src/auth/popup/settings/account-security.component.ts index c7e5b7dc952..88365e7b472 100644 --- a/apps/browser/src/popup/settings/settings.component.ts +++ b/apps/browser/src/auth/popup/settings/account-security.component.ts @@ -1,6 +1,5 @@ import { ChangeDetectorRef, Component, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; -import { Router } from "@angular/router"; import { BehaviorSubject, combineLatest, @@ -23,7 +22,6 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction"; -import { DeviceType } from "@bitwarden/common/enums"; import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; @@ -34,35 +32,20 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv import { BiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service"; import { DialogService } from "@bitwarden/components"; -import { SetPinComponent } from "../../auth/popup/components/set-pin.component"; -import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors"; -import { BrowserApi } from "../../platform/browser/browser-api"; -import { enableAccountSwitching } from "../../platform/flags"; -import BrowserPopupUtils from "../../platform/popup/browser-popup-utils"; +import { BiometricErrors, BiometricErrorTypes } from "../../../models/biometricErrors"; +import { BrowserApi } from "../../../platform/browser/browser-api"; +import { enableAccountSwitching } from "../../../platform/flags"; +import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils"; +import { SetPinComponent } from "../components/set-pin.component"; -import { AboutComponent } from "./about.component"; import { AwaitDesktopDialogComponent } from "./await-desktop-dialog.component"; -const RateUrls = { - [DeviceType.ChromeExtension]: - "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", - [DeviceType.FirefoxExtension]: - "https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews", - [DeviceType.OperaExtension]: - "https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container", - [DeviceType.EdgeExtension]: - "https://microsoftedge.microsoft.com/addons/detail/jbkfoedolllekgbhcbcoahefnbanhhlh", - [DeviceType.VivaldiExtension]: - "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", - [DeviceType.SafariExtension]: "https://apps.apple.com/app/bitwarden/id1352778147", -}; - @Component({ - selector: "app-settings", - templateUrl: "settings.component.html", + selector: "auth-account-security", + templateUrl: "account-security.component.html", }) // eslint-disable-next-line rxjs-angular/prefer-takeuntil -export class SettingsComponent implements OnInit { +export class AccountSecurityComponent implements OnInit { protected readonly VaultTimeoutAction = VaultTimeoutAction; availableVaultTimeoutActions: VaultTimeoutAction[] = []; @@ -95,7 +78,6 @@ export class SettingsComponent implements OnInit { private vaultTimeoutService: VaultTimeoutService, private vaultTimeoutSettingsService: VaultTimeoutSettingsService, public messagingService: MessagingService, - private router: Router, private environmentService: EnvironmentService, private cryptoService: CryptoService, private stateService: StateService, @@ -425,23 +407,6 @@ export class SettingsComponent implements OnInit { ); } - async lock() { - await this.vaultTimeoutService.lock(); - } - - async logOut() { - const confirmed = await this.dialogService.openSimpleDialog({ - title: { key: "logOut" }, - content: { key: "logOutConfirmation" }, - type: "info", - }); - - const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id; - if (confirmed) { - this.messagingService.send("logout", { userId: userId }); - } - } - async changePassword() { const confirmed = await this.dialogService.openSimpleDialog({ title: { key: "continueToWebApp" }, @@ -468,44 +433,6 @@ export class SettingsComponent implements OnInit { } } - async share() { - const confirmed = await this.dialogService.openSimpleDialog({ - title: { key: "learnOrg" }, - content: { key: "learnOrgConfirmation" }, - type: "info", - }); - if (confirmed) { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - BrowserApi.createNewTab("https://bitwarden.com/help/about-organizations/"); - } - } - - async webVault() { - const env = await firstValueFrom(this.environmentService.environment$); - const url = env.getWebVaultUrl(); - await BrowserApi.createNewTab(url); - } - - async import() { - await this.router.navigate(["/import"]); - if (await BrowserApi.isPopupOpen()) { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - BrowserPopupUtils.openCurrentPagePopout(window); - } - } - - export() { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.router.navigate(["/export"]); - } - - about() { - this.dialogService.open(AboutComponent); - } - async fingerprint() { const fingerprint = await this.cryptoService.getFingerprint( await this.stateService.getUserId(), @@ -518,11 +445,21 @@ export class SettingsComponent implements OnInit { return firstValueFrom(dialogRef.closed); } - rate() { - const deviceType = this.platformUtilsService.getDevice(); - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - BrowserApi.createNewTab((RateUrls as any)[deviceType]); + async lock() { + await this.vaultTimeoutService.lock(); + } + + async logOut() { + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "logOut" }, + content: { key: "logOutConfirmation" }, + type: "info", + }); + + const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id; + if (confirmed) { + this.messagingService.send("logout", { userId: userId }); + } } ngOnDestroy() { diff --git a/apps/browser/src/popup/settings/await-desktop-dialog.component.html b/apps/browser/src/auth/popup/settings/await-desktop-dialog.component.html similarity index 100% rename from apps/browser/src/popup/settings/await-desktop-dialog.component.html rename to apps/browser/src/auth/popup/settings/await-desktop-dialog.component.html diff --git a/apps/browser/src/popup/settings/await-desktop-dialog.component.ts b/apps/browser/src/auth/popup/settings/await-desktop-dialog.component.ts similarity index 100% rename from apps/browser/src/popup/settings/await-desktop-dialog.component.ts rename to apps/browser/src/auth/popup/settings/await-desktop-dialog.component.ts diff --git a/apps/browser/src/popup/settings/vault-timeout-input.component.html b/apps/browser/src/auth/popup/settings/vault-timeout-input.component.html similarity index 100% rename from apps/browser/src/popup/settings/vault-timeout-input.component.html rename to apps/browser/src/auth/popup/settings/vault-timeout-input.component.html diff --git a/apps/browser/src/popup/settings/vault-timeout-input.component.ts b/apps/browser/src/auth/popup/settings/vault-timeout-input.component.ts similarity index 100% rename from apps/browser/src/popup/settings/vault-timeout-input.component.ts rename to apps/browser/src/auth/popup/settings/vault-timeout-input.component.ts diff --git a/apps/browser/src/popup/app-routing.animations.ts b/apps/browser/src/popup/app-routing.animations.ts index 13403545fde..e37c640bf92 100644 --- a/apps/browser/src/popup/app-routing.animations.ts +++ b/apps/browser/src/popup/app-routing.animations.ts @@ -174,6 +174,9 @@ export const routerTransition = trigger("routerTransition", [ transition("clone-cipher => attachments, clone-cipher => collections", inSlideLeft), transition("attachments => clone-cipher, collections => clone-cipher", outSlideRight), + transition("tabs => account-security", inSlideLeft), + transition("account-security => tabs", outSlideRight), + transition("tabs => import", inSlideLeft), transition("import => tabs", outSlideRight), diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index 0dcf496457a..059e2e605da 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -21,6 +21,7 @@ import { LoginComponent } from "../auth/popup/login.component"; import { RegisterComponent } from "../auth/popup/register.component"; import { RemovePasswordComponent } from "../auth/popup/remove-password.component"; import { SetPasswordComponent } from "../auth/popup/set-password.component"; +import { AccountSecurityComponent } from "../auth/popup/settings/account-security.component"; import { SsoComponent } from "../auth/popup/sso.component"; import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component"; import { TwoFactorComponent } from "../auth/popup/two-factor.component"; @@ -35,6 +36,7 @@ import { SendGroupingsComponent } from "../tools/popup/send/send-groupings.compo import { SendTypeComponent } from "../tools/popup/send/send-type.component"; import { ExportComponent } from "../tools/popup/settings/export.component"; import { ImportBrowserComponent } from "../tools/popup/settings/import/import-browser.component"; +import { SettingsComponent } from "../tools/popup/settings/settings.component"; import { Fido2Component } from "../vault/popup/components/fido2/fido2.component"; import { AddEditComponent } from "../vault/popup/components/vault/add-edit.component"; import { AttachmentsComponent } from "../vault/popup/components/vault/attachments.component"; @@ -53,7 +55,6 @@ import { ExcludedDomainsComponent } from "./settings/excluded-domains.component" import { FoldersComponent } from "./settings/folders.component"; import { HelpAndFeedbackComponent } from "./settings/help-and-feedback.component"; import { OptionsComponent } from "./settings/options.component"; -import { SettingsComponent } from "./settings/settings.component"; import { SyncComponent } from "./settings/sync.component"; import { TabsV2Component } from "./tabs-v2.component"; import { TabsComponent } from "./tabs.component"; @@ -246,6 +247,12 @@ const routes: Routes = [ canActivate: [AuthGuard], data: { state: "autofill" }, }, + { + path: "account-security", + component: AccountSecurityComponent, + canActivate: [AuthGuard], + data: { state: "account-security" }, + }, { path: "folders", component: FoldersComponent, diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index bed40dfddc9..40cdd297548 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -30,6 +30,8 @@ import { LoginComponent } from "../auth/popup/login.component"; import { RegisterComponent } from "../auth/popup/register.component"; import { RemovePasswordComponent } from "../auth/popup/remove-password.component"; import { SetPasswordComponent } from "../auth/popup/set-password.component"; +import { AccountSecurityComponent } from "../auth/popup/settings/account-security.component"; +import { VaultTimeoutInputComponent } from "../auth/popup/settings/vault-timeout-input.component"; import { SsoComponent } from "../auth/popup/sso.component"; import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component"; import { TwoFactorComponent } from "../auth/popup/two-factor.component"; @@ -49,6 +51,7 @@ import { SendAddEditComponent } from "../tools/popup/send/send-add-edit.componen import { SendGroupingsComponent } from "../tools/popup/send/send-groupings.component"; import { SendTypeComponent } from "../tools/popup/send/send-type.component"; import { ExportComponent } from "../tools/popup/settings/export.component"; +import { SettingsComponent } from "../tools/popup/settings/settings.component"; import { ActionButtonsComponent } from "../vault/popup/components/action-buttons.component"; import { CipherRowComponent } from "../vault/popup/components/cipher-row.component"; import { Fido2CipherRowComponent } from "../vault/popup/components/fido2/fido2-cipher-row.component"; @@ -77,9 +80,7 @@ import { ExcludedDomainsComponent } from "./settings/excluded-domains.component" import { FoldersComponent } from "./settings/folders.component"; import { HelpAndFeedbackComponent } from "./settings/help-and-feedback.component"; import { OptionsComponent } from "./settings/options.component"; -import { SettingsComponent } from "./settings/settings.component"; import { SyncComponent } from "./settings/sync.component"; -import { VaultTimeoutInputComponent } from "./settings/vault-timeout-input.component"; import { TabsV2Component } from "./tabs-v2.component"; import { TabsComponent } from "./tabs.component"; @@ -156,6 +157,7 @@ import "../platform/popup/locales"; SendListComponent, SendTypeComponent, SetPasswordComponent, + AccountSecurityComponent, SettingsComponent, ShareComponent, SsoComponent, diff --git a/apps/browser/src/popup/settings/about.component.html b/apps/browser/src/tools/popup/settings/about/about.component.html similarity index 100% rename from apps/browser/src/popup/settings/about.component.html rename to apps/browser/src/tools/popup/settings/about/about.component.html diff --git a/apps/browser/src/popup/settings/about.component.ts b/apps/browser/src/tools/popup/settings/about/about.component.ts similarity index 100% rename from apps/browser/src/popup/settings/about.component.ts rename to apps/browser/src/tools/popup/settings/about/about.component.ts diff --git a/apps/browser/src/popup/settings/settings.component.html b/apps/browser/src/tools/popup/settings/settings.component.html similarity index 55% rename from apps/browser/src/popup/settings/settings.component.html rename to apps/browser/src/tools/popup/settings/settings.component.html index 98c218b0db0..0b7773019bc 100644 --- a/apps/browser/src/popup/settings/settings.component.html +++ b/apps/browser/src/tools/popup/settings/settings.component.html @@ -7,10 +7,18 @@
-
+

{{ "manage" | i18n }}

+
-
-

{{ "security" | 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) }} - - - - -
- - -
- -
- - -
-
- - -
-
- - -
- - -
-

{{ "account" | i18n }}

@@ -145,35 +67,6 @@
- - -
diff --git a/apps/browser/src/tools/popup/settings/settings.component.ts b/apps/browser/src/tools/popup/settings/settings.component.ts new file mode 100644 index 00000000000..81727c442cd --- /dev/null +++ b/apps/browser/src/tools/popup/settings/settings.component.ts @@ -0,0 +1,101 @@ +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { firstValueFrom, Subject } from "rxjs"; + +import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service"; +import { DeviceType } from "@bitwarden/common/enums"; +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"; +import { DialogService } from "@bitwarden/components"; + +import { BrowserApi } from "../../../platform/browser/browser-api"; +import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils"; + +import { AboutComponent } from "./about/about.component"; + +const RateUrls = { + [DeviceType.ChromeExtension]: + "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", + [DeviceType.FirefoxExtension]: + "https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews", + [DeviceType.OperaExtension]: + "https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container", + [DeviceType.EdgeExtension]: + "https://microsoftedge.microsoft.com/addons/detail/jbkfoedolllekgbhcbcoahefnbanhhlh", + [DeviceType.VivaldiExtension]: + "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", + [DeviceType.SafariExtension]: "https://apps.apple.com/app/bitwarden/id1352778147", +}; + +@Component({ + selector: "tools-settings", + templateUrl: "settings.component.html", +}) +// eslint-disable-next-line rxjs-angular/prefer-takeuntil +export class SettingsComponent implements OnInit { + private destroy$ = new Subject(); + + constructor( + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private vaultTimeoutService: VaultTimeoutService, + public messagingService: MessagingService, + private router: Router, + private environmentService: EnvironmentService, + private dialogService: DialogService, + ) {} + + async ngOnInit() {} + + async share() { + const confirmed = await this.dialogService.openSimpleDialog({ + title: { key: "learnOrg" }, + content: { key: "learnOrgConfirmation" }, + type: "info", + }); + if (confirmed) { + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + BrowserApi.createNewTab("https://bitwarden.com/help/about-organizations/"); + } + } + + async webVault() { + const env = await firstValueFrom(this.environmentService.environment$); + const url = env.getWebVaultUrl(); + await BrowserApi.createNewTab(url); + } + + async import() { + await this.router.navigate(["/import"]); + if (await BrowserApi.isPopupOpen()) { + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + BrowserPopupUtils.openCurrentPagePopout(window); + } + } + + export() { + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.router.navigate(["/export"]); + } + + about() { + this.dialogService.open(AboutComponent); + } + + rate() { + const deviceType = this.platformUtilsService.getDevice(); + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + BrowserApi.createNewTab((RateUrls as any)[deviceType]); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } +}