mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 22:44:11 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
@@ -3234,9 +3234,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"loggingInOn": {
|
||||
"message": "Logging in on"
|
||||
},
|
||||
"opensInANewWindow": {
|
||||
"message": "Opens in a new window"
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
availableVaultTimeoutActions: VaultTimeoutAction[] = [];
|
||||
vaultTimeoutOptions: VaultTimeoutOption[];
|
||||
vaultTimeoutPolicyCallout: Observable<{
|
||||
timeout: { hours: number; minutes: number };
|
||||
timeout: { hours: string; minutes: string };
|
||||
action: VaultTimeoutAction;
|
||||
}>;
|
||||
supportsBiometric: boolean;
|
||||
@@ -105,8 +105,8 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
let timeout;
|
||||
if (policy.data?.minutes) {
|
||||
timeout = {
|
||||
hours: Math.floor(policy.data?.minutes / 60),
|
||||
minutes: policy.data?.minutes % 60,
|
||||
hours: Math.floor(policy.data?.minutes / 60).toString(),
|
||||
minutes: (policy.data?.minutes % 60).toString(),
|
||||
};
|
||||
}
|
||||
return { timeout: timeout, action: policy.data?.action };
|
||||
|
||||
@@ -629,6 +629,9 @@ describe("OverlayBackground", () => {
|
||||
|
||||
it("skips updating the inline menu list if the user has the inline menu set to open on button click", async () => {
|
||||
inlineMenuVisibilityMock$.next(AutofillOverlayVisibility.OnButtonClick);
|
||||
jest
|
||||
.spyOn(overlayBackground as any, "checkIsInlineMenuListVisible")
|
||||
.mockReturnValue(false);
|
||||
tabsSendMessageSpy.mockImplementation((_tab, message, _options) => {
|
||||
if (message.command === "checkFocusedFieldHasValue") {
|
||||
return Promise.resolve(true);
|
||||
|
||||
@@ -1009,7 +1009,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
this.logService.error(error),
|
||||
);
|
||||
|
||||
if ((await this.getInlineMenuVisibility()) === AutofillOverlayVisibility.OnButtonClick) {
|
||||
if (
|
||||
!this.checkIsInlineMenuListVisible() &&
|
||||
(await this.getInlineMenuVisibility()) === AutofillOverlayVisibility.OnButtonClick
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2579,7 +2582,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
* @param sender
|
||||
*/
|
||||
private resetFocusedFieldSubFrameOffsets(sender: chrome.runtime.MessageSender) {
|
||||
if (this.focusedFieldData.frameId > 0 && this.subFrameOffsetsForTab[sender.tab.id]) {
|
||||
if (this.focusedFieldData?.frameId > 0 && this.subFrameOffsetsForTab[sender.tab.id]) {
|
||||
this.subFrameOffsetsForTab[sender.tab.id].set(this.focusedFieldData.frameId, null);
|
||||
}
|
||||
}
|
||||
@@ -2592,6 +2595,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
*/
|
||||
private async triggerSubFrameFocusInRebuild(sender: chrome.runtime.MessageSender) {
|
||||
this.cancelInlineMenuFadeInAndPositionUpdate();
|
||||
this.resetFocusedFieldSubFrameOffsets(sender);
|
||||
this.rebuildSubFrameOffsets$.next(sender);
|
||||
this.repositionInlineMenu$.next(sender);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.10.2",
|
||||
"version": "2024.10.3",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
|
||||
@@ -2804,9 +2804,6 @@
|
||||
"message": "EU",
|
||||
"description": "European Union"
|
||||
},
|
||||
"loggingInOn": {
|
||||
"message": "Logging in on"
|
||||
},
|
||||
"selfHostedServer": {
|
||||
"message": "self-hosted"
|
||||
},
|
||||
|
||||
4
apps/desktop/src/package-lock.json
generated
4
apps/desktop/src/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.10.2",
|
||||
"version": "2024.10.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.10.2",
|
||||
"version": "2024.10.3",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@bitwarden/desktop-napi": "file:../desktop_native/napi",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@bitwarden/desktop",
|
||||
"productName": "Bitwarden",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.10.2",
|
||||
"version": "2024.10.3",
|
||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||
"homepage": "https://bitwarden.com",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -1583,38 +1583,6 @@
|
||||
"specialCharacters": {
|
||||
"message": "Special characters (!@#$%^&*)"
|
||||
},
|
||||
"uppercaseDescription": {
|
||||
"message": "Include uppercase characters",
|
||||
"description": "Tooltip for the password generator uppercase character checkbox"
|
||||
},
|
||||
"uppercaseLabel": {
|
||||
"message": "A-Z",
|
||||
"description": "Label for the password generator uppercase character checkbox"
|
||||
},
|
||||
"lowercaseDescription": {
|
||||
"message": "Include lowercase characters",
|
||||
"description": "Full description for the password generator lowercase character checkbox"
|
||||
},
|
||||
"lowercaseLabel": {
|
||||
"message": "a-z",
|
||||
"description": "Label for the password generator lowercase character checkbox"
|
||||
},
|
||||
"numbersDescription": {
|
||||
"message": "Include numbers",
|
||||
"description": "Full description for the password generator numbers checkbox"
|
||||
},
|
||||
"numbersLabel": {
|
||||
"message": "0-9",
|
||||
"description": "Label for the password generator numbers checkbox"
|
||||
},
|
||||
"specialCharactersDescription": {
|
||||
"message": "Include special characters",
|
||||
"description": "Full description for the password generator special characters checkbox"
|
||||
},
|
||||
"specialCharactersLabel": {
|
||||
"message": "!@#$%^&*",
|
||||
"description": "Label for the password generator special characters checkbox"
|
||||
},
|
||||
"numWords": {
|
||||
"message": "Number of words"
|
||||
},
|
||||
@@ -9529,10 +9497,6 @@
|
||||
"message": "!@#$%^&*",
|
||||
"description": "Label for the password generator special characters checkbox"
|
||||
},
|
||||
"avoidAmbiguous": {
|
||||
"message": "Avoid ambiguous characters",
|
||||
"description": "Label for the avoid ambiguous characters checkbox."
|
||||
},
|
||||
"addAttachment": {
|
||||
"message": "Add attachment"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
} as data"
|
||||
>
|
||||
<div class="environment-selector-btn">
|
||||
{{ "loggingInOn" | i18n }}:
|
||||
{{ "accessing" | i18n }}:
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(null)"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
|
||||
@@ -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;
|
||||
@@ -45,6 +45,24 @@ const LOGGED_OUT_INFO: AccountInfo = {
|
||||
name: undefined,
|
||||
};
|
||||
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or throws if the account or UserId are null.
|
||||
*/
|
||||
export const getUserId = map<{ id: UserId | undefined }, UserId>((account) => {
|
||||
if (account?.id == null) {
|
||||
throw new Error("Null account or account ID");
|
||||
}
|
||||
|
||||
return account.id;
|
||||
});
|
||||
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or returns undefined if the account or UserId are null.
|
||||
*/
|
||||
export const getOptionalUserId = map<{ id: UserId | undefined }, UserId | undefined>(
|
||||
(account) => account?.id ?? undefined,
|
||||
);
|
||||
|
||||
export class AccountServiceImplementation implements InternalAccountService {
|
||||
private accountsState: GlobalState<Record<UserId, AccountInfo>>;
|
||||
private activeAccountIdState: GlobalState<UserId | undefined>;
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -234,7 +234,7 @@
|
||||
},
|
||||
"apps/desktop": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.10.2",
|
||||
"version": "2024.10.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user