From a7efd2158ebd2032eea0dce8a1f5bc47c43e2165 Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 08:52:54 -0700 Subject: [PATCH 01/35] [PM-18802] - Autofill Settings Nudges and Settings Badge (#14439) * autofill nudge * remove undismiss logic * revert change to popup view cache service * move browser autofill logic to platform. cleanup * fix test * adjustments to autofill nudges * add missing provider * updates to autofill nudges * fix date logic * change autofillBrowserSettingsService isBrowserAutofillSettingOverridden to function * fix up browser autofill overridden settings logic * remove check for privacy in isBrowserAutofillSettingOverridden --- apps/browser/src/_locales/en/messages.json | 18 ++++ .../popup/settings/autofill.component.html | 10 +++ .../popup/settings/autofill.component.ts | 84 +++++++++++-------- .../autofill-browser-settings.service.ts | 31 +++++++ .../src/platform/browser/browser-api.ts | 23 +++++ .../view-cache/popup-view-cache.service.ts | 2 +- .../popup/settings/settings-v2.component.html | 10 ++- .../popup/settings/settings-v2.component.ts | 39 ++++++++- .../spotlight/spotlight.component.html | 5 +- .../spotlight/spotlight.component.ts | 8 +- .../components/spotlight/spotlight.stories.ts | 20 ++--- .../autofill-nudge.service.ts | 47 +++++++++++ .../services/custom-nudges-services/index.ts | 1 + .../src/services/vault-nudges.service.spec.ts | 1 + .../src/services/vault-nudges.service.ts | 3 + 15 files changed, 240 insertions(+), 62 deletions(-) create mode 100644 apps/browser/src/autofill/services/autofill-browser-settings.service.ts create mode 100644 libs/vault/src/services/custom-nudges-services/autofill-nudge.service.ts diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 1df0bf96616..1c3214a6ef7 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1589,6 +1589,24 @@ "autofillSuggestionsSectionTitle": { "message": "Autofill suggestions" }, + "autofillSpotlightTitle": { + "message": "Easily find autofill suggestions" + }, + "autofillSpotlightDesc": { + "message": "Turn off your browser's autofill settings, so they don't conflict with Bitwarden." + }, + "turnOffBrowserAutofill": { + "message": "Turn off $BROWSER$ autofill", + "placeholders": { + "browser": { + "content": "$1", + "example": "Chrome" + } + } + }, + "turnOffAutofill": { + "message": "Turn off autofill" + }, "showInlineMenuLabel": { "message": "Show autofill suggestions on form fields" }, diff --git a/apps/browser/src/autofill/popup/settings/autofill.component.html b/apps/browser/src/autofill/popup/settings/autofill.component.html index 4fd85ddce33..264b04b039b 100644 --- a/apps/browser/src/autofill/popup/settings/autofill.component.html +++ b/apps/browser/src/autofill/popup/settings/autofill.component.html @@ -6,6 +6,16 @@
+
+ +

{{ "autofillSuggestionsSectionTitle" | i18n }}

diff --git a/apps/browser/src/autofill/popup/settings/autofill.component.ts b/apps/browser/src/autofill/popup/settings/autofill.component.ts index c30f150e71d..d63f9a4589d 100644 --- a/apps/browser/src/autofill/popup/settings/autofill.component.ts +++ b/apps/browser/src/autofill/popup/settings/autofill.component.ts @@ -11,9 +11,11 @@ import { FormControl, } from "@angular/forms"; import { RouterModule } from "@angular/router"; -import { firstValueFrom } from "rxjs"; +import { Observable, filter, firstValueFrom, map, switchMap } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { AutofillOverlayVisibility, BrowserClientVendors, @@ -53,7 +55,9 @@ import { SelectModule, TypographyModule, } from "@bitwarden/components"; +import { SpotlightComponent, VaultNudgesService, VaultNudgeType } from "@bitwarden/vault"; +import { AutofillBrowserSettingsService } from "../../../autofill/services/autofill-browser-settings.service"; import { BrowserApi } from "../../../platform/browser/browser-api"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; @@ -81,6 +85,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co SelectModule, TypographyModule, ReactiveFormsModule, + SpotlightComponent, ], }) export class AutofillComponent implements OnInit { @@ -100,6 +105,14 @@ export class AutofillComponent implements OnInit { protected browserClientIsUnknown: boolean; protected autofillOnPageLoadFromPolicy$ = this.autofillSettingsService.activateAutofillOnPageLoadFromPolicy$; + protected showSpotlightNudge$: Observable = this.accountService.activeAccount$.pipe( + filter((account): account is Account => account !== null), + switchMap((account) => + this.vaultNudgesService + .showNudge$(VaultNudgeType.AutofillNudge, account.id) + .pipe(map((nudgeStatus) => !nudgeStatus.hasSpotlightDismissed)), + ), + ); protected autofillOnPageLoadForm = new FormGroup({ autofillOnPageLoad: new FormControl(), @@ -142,6 +155,9 @@ export class AutofillComponent implements OnInit { private configService: ConfigService, private formBuilder: FormBuilder, private destroyRef: DestroyRef, + private vaultNudgesService: VaultNudgesService, + private accountService: AccountService, + private autofillBrowserSettingsService: AutofillBrowserSettingsService, ) { this.autofillOnPageLoadOptions = [ { name: this.i18nService.t("autoFillOnPageLoadYes"), value: true }, @@ -165,7 +181,7 @@ export class AutofillComponent implements OnInit { { name: i18nService.t("never"), value: UriMatchStrategy.Never }, ]; - this.browserClientVendor = this.getBrowserClientVendor(); + this.browserClientVendor = BrowserApi.getBrowserClientVendor(window); this.disablePasswordManagerURI = DisablePasswordManagerUris[this.browserClientVendor]; this.browserShortcutsURI = BrowserShortcutsUris[this.browserClientVendor]; this.browserClientIsUnknown = this.browserClientVendor === BrowserClientVendors.Unknown; @@ -173,7 +189,11 @@ export class AutofillComponent implements OnInit { async ngOnInit() { this.canOverrideBrowserAutofillSetting = !this.browserClientIsUnknown; - this.defaultBrowserAutofillDisabled = await this.browserAutofillSettingCurrentlyOverridden(); + + this.defaultBrowserAutofillDisabled = + await this.autofillBrowserSettingsService.isBrowserAutofillSettingOverridden( + this.browserClientVendor, + ); this.inlineMenuVisibility = await firstValueFrom( this.autofillSettingsService.inlineMenuVisibility$, @@ -308,6 +328,27 @@ export class AutofillComponent implements OnInit { ); } + get spotlightButtonIcon() { + if (this.browserClientVendor === BrowserClientVendors.Unknown) { + return "bwi-external-link"; + } + return null; + } + + get spotlightButtonText() { + if (this.browserClientVendor === BrowserClientVendors.Unknown) { + return this.i18nService.t("turnOffAutofill"); + } + return this.i18nService.t("turnOffBrowserAutofill", this.browserClientVendor); + } + + async dismissSpotlight() { + await this.vaultNudgesService.dismissNudge( + VaultNudgeType.AutofillNudge, + await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)), + ); + } + async updateInlineMenuVisibility() { if (!this.enableInlineMenu) { this.enableInlineMenuOnIconSelect = false; @@ -346,26 +387,6 @@ export class AutofillComponent implements OnInit { } } - private getBrowserClientVendor(): BrowserClientVendor { - if (this.platformUtilsService.isChrome()) { - return BrowserClientVendors.Chrome; - } - - if (this.platformUtilsService.isOpera()) { - return BrowserClientVendors.Opera; - } - - if (this.platformUtilsService.isEdge()) { - return BrowserClientVendors.Edge; - } - - if (this.platformUtilsService.isVivaldi()) { - return BrowserClientVendors.Vivaldi; - } - - return BrowserClientVendors.Unknown; - } - protected async openURI(event: Event, uri: BrowserShortcutsUri | DisablePasswordManagerUri) { event.preventDefault(); @@ -422,7 +443,7 @@ export class AutofillComponent implements OnInit { if ( this.inlineMenuVisibility === AutofillOverlayVisibility.Off || !this.canOverrideBrowserAutofillSetting || - (await this.browserAutofillSettingCurrentlyOverridden()) + this.defaultBrowserAutofillDisabled ) { return; } @@ -460,6 +481,9 @@ export class AutofillComponent implements OnInit { } await BrowserApi.updateDefaultBrowserAutofillSettings(!this.defaultBrowserAutofillDisabled); + this.autofillBrowserSettingsService.setDefaultBrowserAutofillDisabled( + this.defaultBrowserAutofillDisabled, + ); } private handleOverrideDialogAccept = async () => { @@ -467,18 +491,6 @@ export class AutofillComponent implements OnInit { await this.updateDefaultBrowserAutofillDisabled(); }; - async browserAutofillSettingCurrentlyOverridden() { - if (!this.canOverrideBrowserAutofillSetting) { - return false; - } - - if (!(await this.privacyPermissionGranted())) { - return false; - } - - return await BrowserApi.browserAutofillSettingsOverridden(); - } - async privacyPermissionGranted(): Promise { return await BrowserApi.permissionsGranted(["privacy"]); } diff --git a/apps/browser/src/autofill/services/autofill-browser-settings.service.ts b/apps/browser/src/autofill/services/autofill-browser-settings.service.ts new file mode 100644 index 00000000000..ba59a655b77 --- /dev/null +++ b/apps/browser/src/autofill/services/autofill-browser-settings.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from "@angular/core"; +import { BehaviorSubject, Observable } from "rxjs"; + +import { BrowserClientVendors } from "@bitwarden/common/autofill/constants"; +import { BrowserClientVendor } from "@bitwarden/common/autofill/types"; + +import { BrowserApi } from "../../platform/browser/browser-api"; + +/** + * Service class for various Autofill-related browser API operations. + */ +@Injectable({ + providedIn: "root", +}) +export class AutofillBrowserSettingsService { + async isBrowserAutofillSettingOverridden(browserClient: BrowserClientVendor) { + return ( + browserClient !== BrowserClientVendors.Unknown && + (await BrowserApi.browserAutofillSettingsOverridden()) + ); + } + + private _defaultBrowserAutofillDisabled$ = new BehaviorSubject(false); + + defaultBrowserAutofillDisabled$: Observable = + this._defaultBrowserAutofillDisabled$.asObservable(); + + setDefaultBrowserAutofillDisabled(value: boolean) { + this._defaultBrowserAutofillDisabled$.next(value); + } +} diff --git a/apps/browser/src/platform/browser/browser-api.ts b/apps/browser/src/platform/browser/browser-api.ts index 4b4cec7e7da..b27e8ca7c96 100644 --- a/apps/browser/src/platform/browser/browser-api.ts +++ b/apps/browser/src/platform/browser/browser-api.ts @@ -2,6 +2,8 @@ // @ts-strict-ignore import { Observable } from "rxjs"; +import { BrowserClientVendors } from "@bitwarden/common/autofill/constants"; +import { BrowserClientVendor } from "@bitwarden/common/autofill/types"; import { DeviceType } from "@bitwarden/common/enums"; import { isBrowserSafariApi } from "@bitwarden/platform"; @@ -131,6 +133,27 @@ export class BrowserApi { }); } + static getBrowserClientVendor(clientWindow: Window): BrowserClientVendor { + const device = BrowserPlatformUtilsService.getDevice(clientWindow); + + switch (device) { + case DeviceType.ChromeExtension: + case DeviceType.ChromeBrowser: + return BrowserClientVendors.Chrome; + case DeviceType.OperaExtension: + case DeviceType.OperaBrowser: + return BrowserClientVendors.Opera; + case DeviceType.EdgeExtension: + case DeviceType.EdgeBrowser: + return BrowserClientVendors.Edge; + case DeviceType.VivaldiExtension: + case DeviceType.VivaldiBrowser: + return BrowserClientVendors.Vivaldi; + default: + return BrowserClientVendors.Unknown; + } + } + /** * Gets the tab with the given id. * diff --git a/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts b/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts index 6fc3e11493c..ff63b52ab3f 100644 --- a/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts +++ b/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts @@ -82,7 +82,7 @@ export class PopupViewCacheService implements ViewCacheService { initialValue, persistNavigation, } = options; - const cachedValue = this.cache[key] + const cachedValue = this.cache[key]?.value ? deserializer(JSON.parse(this.cache[key].value)) : initialValue; const _signal = signal(cachedValue); diff --git a/apps/browser/src/tools/popup/settings/settings-v2.component.html b/apps/browser/src/tools/popup/settings/settings-v2.component.html index b9f4176b927..22e2d9a28d0 100644 --- a/apps/browser/src/tools/popup/settings/settings-v2.component.html +++ b/apps/browser/src/tools/popup/settings/settings-v2.component.html @@ -17,7 +17,15 @@ - {{ "autofill" | i18n }} +
+

{{ "autofill" | i18n }}

+ 1 +
diff --git a/apps/browser/src/tools/popup/settings/settings-v2.component.ts b/apps/browser/src/tools/popup/settings/settings-v2.component.ts index 9301b8622c5..be05452529a 100644 --- a/apps/browser/src/tools/popup/settings/settings-v2.component.ts +++ b/apps/browser/src/tools/popup/settings/settings-v2.component.ts @@ -1,7 +1,15 @@ import { CommonModule } from "@angular/common"; -import { Component } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { RouterModule } from "@angular/router"; -import { filter, firstValueFrom, Observable, shareReplay, switchMap } from "rxjs"; +import { + combineLatest, + filter, + firstValueFrom, + map, + Observable, + shareReplay, + switchMap, +} from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; @@ -12,6 +20,8 @@ import { BadgeComponent, ItemModule } from "@bitwarden/components"; import { NudgeStatus, VaultNudgesService, VaultNudgeType } from "@bitwarden/vault"; import { CurrentAccountComponent } from "../../../auth/popup/account-switching/current-account.component"; +import { AutofillBrowserSettingsService } from "../../../autofill/services/autofill-browser-settings.service"; +import { BrowserApi } from "../../../platform/browser/browser-api"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component"; @@ -31,8 +41,10 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co BadgeComponent, ], }) -export class SettingsV2Component { +export class SettingsV2Component implements OnInit { VaultNudgeType = VaultNudgeType; + activeUserId: UserId | null = null; + protected isBrowserAutofillSettingOverridden = false; private authenticatedAccount$: Observable = this.accountService.activeAccount$.pipe( filter((account): account is Account => account !== null), @@ -51,6 +63,19 @@ export class SettingsV2Component { ), ); + showAutofillBadge$: Observable = combineLatest([ + this.autofillBrowserSettingsService.defaultBrowserAutofillDisabled$, + this.authenticatedAccount$, + ]).pipe( + switchMap(([defaultBrowserAutofillDisabled, account]) => + this.vaultNudgesService.showNudge$(VaultNudgeType.AutofillNudge, account.id).pipe( + map((nudgeStatus) => { + return !defaultBrowserAutofillDisabled && nudgeStatus.hasBadgeDismissed === false; + }), + ), + ), + ); + protected isNudgeFeatureEnabled$ = this.configService.getFeatureFlag$( FeatureFlag.PM8851_BrowserOnboardingNudge, ); @@ -58,9 +83,17 @@ export class SettingsV2Component { constructor( private readonly vaultNudgesService: VaultNudgesService, private readonly accountService: AccountService, + private readonly autofillBrowserSettingsService: AutofillBrowserSettingsService, private readonly configService: ConfigService, ) {} + async ngOnInit() { + this.isBrowserAutofillSettingOverridden = + await this.autofillBrowserSettingsService.isBrowserAutofillSettingOverridden( + BrowserApi.getBrowserClientVendor(window), + ); + } + async dismissBadge(type: VaultNudgeType) { if (!(await firstValueFrom(this.showVaultBadge$)).hasBadgeDismissed) { const account = await firstValueFrom(this.authenticatedAccount$); diff --git a/libs/vault/src/components/spotlight/spotlight.component.html b/libs/vault/src/components/spotlight/spotlight.component.html index e949ca4d912..0c6a37914d8 100644 --- a/libs/vault/src/components/spotlight/spotlight.component.html +++ b/libs/vault/src/components/spotlight/spotlight.component.html @@ -23,10 +23,9 @@ type="button" buttonType="primary" *ngIf="buttonText" - (click)="handleButtonClick()" + (click)="handleButtonClick($event)" > {{ buttonText }} + - -
diff --git a/libs/vault/src/components/spotlight/spotlight.component.ts b/libs/vault/src/components/spotlight/spotlight.component.ts index e52669cc404..8639fe7947f 100644 --- a/libs/vault/src/components/spotlight/spotlight.component.ts +++ b/libs/vault/src/components/spotlight/spotlight.component.ts @@ -19,11 +19,13 @@ export class SpotlightComponent { @Input() buttonText?: string; // Wheter the component can be dismissed, if true, the component will not show a close button @Input() persistent = false; + // Optional icon to display on the button + @Input() buttonIcon: string | null = null; @Output() onDismiss = new EventEmitter(); - @Output() onButtonClick = new EventEmitter(); + @Output() onButtonClick = new EventEmitter(); - handleButtonClick(): void { - this.onButtonClick.emit(); + handleButtonClick(event: MouseEvent): void { + this.onButtonClick.emit(event); } handleDismiss(): void { diff --git a/libs/vault/src/components/spotlight/spotlight.stories.ts b/libs/vault/src/components/spotlight/spotlight.stories.ts index 9f7757e4528..8e660aacbad 100644 --- a/libs/vault/src/components/spotlight/spotlight.stories.ts +++ b/libs/vault/src/components/spotlight/spotlight.stories.ts @@ -52,9 +52,9 @@ export const Persistent: Story = { }, }; -export const WithCustomButton: Story = { +export const WithButtonIcon: Story = { args: { - buttonText: "Custom Button", + buttonIcon: "bwi bwi-external-link", }, render: (args) => ({ props: args, @@ -62,19 +62,9 @@ export const WithCustomButton: Story = { - - + buttonText="External Link" + buttonIcon="bwi-external-link" + > `, }), }; diff --git a/libs/vault/src/services/custom-nudges-services/autofill-nudge.service.ts b/libs/vault/src/services/custom-nudges-services/autofill-nudge.service.ts new file mode 100644 index 00000000000..b5595e590c9 --- /dev/null +++ b/libs/vault/src/services/custom-nudges-services/autofill-nudge.service.ts @@ -0,0 +1,47 @@ +import { Injectable, inject } from "@angular/core"; +import { Observable, combineLatest, from, map, of } from "rxjs"; +import { catchError } from "rxjs/operators"; + +import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { UserId } from "@bitwarden/common/types/guid"; + +import { DefaultSingleNudgeService } from "../default-single-nudge.service"; +import { NudgeStatus, VaultNudgeType } from "../vault-nudges.service"; + +const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000; + +/** + * Custom Nudge Service to use for the Autofill Nudge in the Vault + */ +@Injectable({ + providedIn: "root", +}) +export class AutofillNudgeService extends DefaultSingleNudgeService { + vaultProfileService = inject(VaultProfileService); + logService = inject(LogService); + + nudgeStatus$(_: VaultNudgeType, userId: UserId): Observable { + const profileDate$ = from(this.vaultProfileService.getProfileCreationDate(userId)).pipe( + catchError(() => { + this.logService.error("Error getting profile creation date"); + // Default to today to ensure we show the nudge + return of(new Date()); + }), + ); + + return combineLatest([ + profileDate$, + this.getNudgeStatus$(VaultNudgeType.AutofillNudge, userId), + of(Date.now() - THIRTY_DAYS_MS), + ]).pipe( + map(([profileCreationDate, status, profileCutoff]) => { + const profileOlderThanCutoff = profileCreationDate.getTime() < profileCutoff; + return { + hasBadgeDismissed: status.hasBadgeDismissed || profileOlderThanCutoff, + hasSpotlightDismissed: status.hasSpotlightDismissed || profileOlderThanCutoff, + }; + }), + ); + } +} diff --git a/libs/vault/src/services/custom-nudges-services/index.ts b/libs/vault/src/services/custom-nudges-services/index.ts index 68427a8dc4d..2e9ade985cc 100644 --- a/libs/vault/src/services/custom-nudges-services/index.ts +++ b/libs/vault/src/services/custom-nudges-services/index.ts @@ -1,3 +1,4 @@ +export * from "./autofill-nudge.service"; export * from "./has-items-nudge.service"; export * from "./download-bitwarden-nudge.service"; export * from "./empty-vault-nudge.service"; diff --git a/libs/vault/src/services/vault-nudges.service.spec.ts b/libs/vault/src/services/vault-nudges.service.spec.ts index a7469410711..89465fc5382 100644 --- a/libs/vault/src/services/vault-nudges.service.spec.ts +++ b/libs/vault/src/services/vault-nudges.service.spec.ts @@ -55,6 +55,7 @@ describe("Vault Nudges Service", () => { useValue: mock(), }, { provide: CipherService, useValue: mock() }, + { provide: LogService, useValue: mock() }, { provide: AccountService, useValue: mock(), diff --git a/libs/vault/src/services/vault-nudges.service.ts b/libs/vault/src/services/vault-nudges.service.ts index 171fe85252f..e04cb609d7f 100644 --- a/libs/vault/src/services/vault-nudges.service.ts +++ b/libs/vault/src/services/vault-nudges.service.ts @@ -9,6 +9,7 @@ import { UserId } from "@bitwarden/common/types/guid"; import { HasItemsNudgeService, EmptyVaultNudgeService, + AutofillNudgeService, DownloadBitwardenNudgeService, NewItemNudgeService, } from "./custom-nudges-services"; @@ -28,6 +29,7 @@ export enum VaultNudgeType { */ EmptyVaultNudge = "empty-vault-nudge", HasVaultItems = "has-vault-items", + AutofillNudge = "autofill-nudge", DownloadBitwarden = "download-bitwarden", newLoginItemStatus = "new-login-item-status", newCardItemStatus = "new-card-item-status", @@ -57,6 +59,7 @@ export class VaultNudgesService { private customNudgeServices: Partial> = { [VaultNudgeType.HasVaultItems]: inject(HasItemsNudgeService), [VaultNudgeType.EmptyVaultNudge]: inject(EmptyVaultNudgeService), + [VaultNudgeType.AutofillNudge]: inject(AutofillNudgeService), [VaultNudgeType.DownloadBitwarden]: inject(DownloadBitwardenNudgeService), [VaultNudgeType.newLoginItemStatus]: this.newItemNudgeService, [VaultNudgeType.newCardItemStatus]: this.newItemNudgeService, From 903b1bf0bade6587d8d4ffa895c0570bac7dd53a Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 08:56:56 -0700 Subject: [PATCH 02/35] re-add missing i18n keys (#14690) --- apps/desktop/src/locales/en/messages.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 681a0e3147c..ea198086f8d 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -3616,6 +3616,27 @@ "biometricsStatusHelptextUnavailableReasonUnknown": { "message": "Biometric unlock is currently unavailable for an unknown reason." }, + "itemDetails": { + "message": "Item details" + }, + "itemName": { + "message": "Item name" + }, + "loginCredentials": { + "message": "Login credentials" + }, + "additionalOptions": { + "message": "Additional options" + }, + "itemHistory": { + "message": "Item history" + }, + "lastEdited": { + "message": "Last edited" + }, + "upload": { + "message": "Upload" + }, "authorize": { "message": "Authorize" }, From 47d41f928956599bd367974cec9d0516d18059d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 18:12:02 +0200 Subject: [PATCH 03/35] [deps]: Update codecov/test-results-action action to v1.1.0 (#14501) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel García --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78a735e4870..f76b349ccd4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,7 +70,7 @@ jobs: uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2 - name: Upload results to codecov.io - uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2 + uses: codecov/test-results-action@f2dba722c67b86c6caa034178c6e4d35335f6706 # v1.1.0 rust: name: Run Rust tests on ${{ matrix.os }} From 89be04a45ef1ec20728148198291bc9ed0baed0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 19:01:50 +0200 Subject: [PATCH 04/35] [deps]: Update dorny/test-reporter action to v2 (#14518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel García --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f76b349ccd4..50f04ebaeb1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,7 +58,7 @@ jobs: run: npm test -- --coverage --maxWorkers=3 - name: Report test results - uses: dorny/test-reporter@31a54ee7ebcacc03a09ea97a7e5465a47b84aea5 # v1.9.1 + uses: dorny/test-reporter@6e6a65b7a0bd2c9197df7d0ae36ac5cee784230c # v2.0.0 if: ${{ github.event.pull_request.head.repo.full_name == github.repository && !cancelled() }} with: name: Test Results From 0d2c890da11b23948d229070c89050f911fe8852 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 13:29:48 -0400 Subject: [PATCH 05/35] [deps] UI Foundation: Update @types/react to v18.3.20 (#14464) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0db144090b9..bdf9c3a9d26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11820,9 +11820,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", - "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", + "version": "18.3.20", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", + "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 7c1873090c1..6fe463ac387 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ }, "react": "18.3.1", "react-dom": "18.3.1", - "@types/react": "18.3.1", + "@types/react": "18.3.20", "replacestream": "4.0.3" }, "lint-staged": { From 624dafa431f9bf783529e11f35cd665f276eb664 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 13:51:15 -0400 Subject: [PATCH 06/35] [deps] UI Foundation: Update angular-cli monorepo to v18.2.19 (#14465) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 718 +++++++++++++++++++++------------------------- package.json | 6 +- 2 files changed, 333 insertions(+), 391 deletions(-) diff --git a/package-lock.json b/package-lock.json index bdf9c3a9d26..1e7e0741cd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,9 +74,9 @@ "zxcvbn": "4.4.2" }, "devDependencies": { - "@angular-devkit/build-angular": "18.2.12", + "@angular-devkit/build-angular": "18.2.19", "@angular-eslint/schematics": "18.4.3", - "@angular/cli": "18.2.12", + "@angular/cli": "18.2.19", "@angular/compiler-cli": "18.2.13", "@babel/core": "7.24.9", "@babel/preset-env": "7.24.8", @@ -84,7 +84,7 @@ "@electron/notarize": "2.5.0", "@electron/rebuild": "3.7.2", "@lit-labs/signals": "0.1.2", - "@ngtools/webpack": "18.2.12", + "@ngtools/webpack": "18.2.19", "@storybook/addon-a11y": "8.6.12", "@storybook/addon-actions": "8.6.12", "@storybook/addon-designs": "8.2.1", @@ -414,29 +414,28 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.12.tgz", - "integrity": "sha512-quVUi7eqTq9OHumQFNl9Y8t2opm8miu4rlYnuF6rbujmmBDvdUvR6trFChueRczl2p5HWqTOr6NPoDGQm8AyNw==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.19.tgz", + "integrity": "sha512-xwY7v+nGE7TXOc4pgY6u57bLzIPSHuecosYr3TiWHAl9iEcKHzkCCFKsLZyunohHmq/i1uA6g3cC6iwp2xNYyg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.12", - "@angular-devkit/build-webpack": "0.1802.12", - "@angular-devkit/core": "18.2.12", - "@angular/build": "18.2.12", - "@babel/core": "7.25.2", - "@babel/generator": "7.25.0", - "@babel/helper-annotate-as-pure": "7.24.7", + "@angular-devkit/architect": "0.1802.19", + "@angular-devkit/build-webpack": "0.1802.19", + "@angular-devkit/core": "18.2.19", + "@angular/build": "18.2.19", + "@babel/core": "7.26.10", + "@babel/generator": "7.26.10", + "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.25.0", - "@babel/plugin-transform-async-to-generator": "7.24.7", - "@babel/plugin-transform-runtime": "7.24.7", - "@babel/preset-env": "7.25.3", - "@babel/runtime": "7.25.0", + "@babel/plugin-transform-async-generator-functions": "7.26.8", + "@babel/plugin-transform-async-to-generator": "7.25.9", + "@babel/plugin-transform-runtime": "7.26.10", + "@babel/preset-env": "7.26.9", + "@babel/runtime": "7.26.10", "@discoveryjs/json-ext": "0.6.1", - "@ngtools/webpack": "18.2.12", - "@vitejs/plugin-basic-ssl": "1.1.0", + "@ngtools/webpack": "18.2.19", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", "babel-loader": "9.1.3", @@ -446,7 +445,7 @@ "css-loader": "7.1.2", "esbuild-wasm": "0.23.0", "fast-glob": "3.3.2", - "http-proxy-middleware": "3.0.3", + "http-proxy-middleware": "3.0.5", "https-proxy-agent": "7.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", @@ -475,7 +474,6 @@ "terser": "5.31.6", "tree-kill": "1.2.2", "tslib": "2.6.3", - "vite": "5.4.6", "watchpack": "2.4.1", "webpack": "5.94.0", "webpack-dev-middleware": "7.4.2", @@ -543,13 +541,13 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/architect": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.12.tgz", - "integrity": "sha512-bepVb2/GtJppYKaeW8yTGE6egmoWZ7zagFDsmBdbF+BYp+HmeoPsclARcdryBPVq68zedyTRdvhWSUTbw1AYuw==", + "version": "0.1802.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.19.tgz", + "integrity": "sha512-M4B1tzxGX1nWCZr9GMM8OO0yBJO2HFSdK8M8P74vEFQfKIeq3y16IQ5zlEveJrkCOFVtmlIy2C9foMCdNyBRMA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "18.2.19", "rxjs": "7.8.1" }, "engines": { @@ -559,9 +557,9 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -587,22 +585,22 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -627,95 +625,110 @@ "semver": "bin/semver.js" } }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/preset-env": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", - "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "node_modules/@angular-devkit/build-angular/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/preset-env": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.0", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.25.0", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.25.0", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", + "core-js-compat": "^3.40.0", "semver": "^6.3.1" }, "engines": { @@ -827,6 +840,20 @@ "webpack": ">=5" } }, + "node_modules/@angular-devkit/build-angular/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@angular-devkit/build-angular/node_modules/browserslist": { "version": "4.24.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", @@ -1345,9 +1372,9 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1416,13 +1443,13 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.12.tgz", - "integrity": "sha512-0Z3fdbZVRnjYWE2/VYyfy+uieY+6YZyEp4ylzklVkc+fmLNsnz4Zw6cK1LzzcBqAwKIyh1IdW20Cg7o8b0sONA==", + "version": "0.1802.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.19.tgz", + "integrity": "sha512-axz1Sasn+c+GJpJexBL+B3Rh1w3wJrQq8k8gkniodjJ594p4ti2qGk7i9Tj8A4cXx5fGY+EpuZvKfI/9Tr7QwA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.12", + "@angular-devkit/architect": "0.1802.19", "rxjs": "7.8.1" }, "engines": { @@ -1436,13 +1463,13 @@ } }, "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/architect": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.12.tgz", - "integrity": "sha512-bepVb2/GtJppYKaeW8yTGE6egmoWZ7zagFDsmBdbF+BYp+HmeoPsclARcdryBPVq68zedyTRdvhWSUTbw1AYuw==", + "version": "0.1802.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.19.tgz", + "integrity": "sha512-M4B1tzxGX1nWCZr9GMM8OO0yBJO2HFSdK8M8P74vEFQfKIeq3y16IQ5zlEveJrkCOFVtmlIy2C9foMCdNyBRMA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "18.2.19", "rxjs": "7.8.1" }, "engines": { @@ -1452,9 +1479,9 @@ } }, "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1581,13 +1608,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.14.tgz", - "integrity": "sha512-mukjZIHHB7gWratq8fZwUq5WZ+1bF4feG/idXr1wgQ+/FqWjs2PP7HDesHVcPymmRulpTyCpB7TNB1O1fgnCpA==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.19.tgz", + "integrity": "sha512-P/0KjkzOf2ZShuShx3cBbjLI7XlcS6B/yCRBo1MQfCC4cZfmzPQoUEOSQeYZgy5pnC24f+dKh/+TWc5uYL/Lvg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.14", + "@angular-devkit/core": "18.2.19", "jsonc-parser": "3.3.1", "magic-string": "0.30.11", "ora": "5.4.1", @@ -1600,9 +1627,9 @@ } }, "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.14.tgz", - "integrity": "sha512-UGIGOjXuOyCW+5S4tINu7e6LOu738CmTw3h7Ui1I8OzdTIYJcYJrei8sgrwDwOYADRal+p0MeMlnykH3TM5XBA==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2034,14 +2061,14 @@ } }, "node_modules/@angular/build": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.12.tgz", - "integrity": "sha512-4Ohz+OSILoL+cCAQ4UTiCT5v6pctu3fXNoNpTEUK46OmxELk9jDITO5rNyNS7TxBn9wY69kjX5VcDf7MenquFQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.19.tgz", + "integrity": "sha512-dTqR+mhcZWtCRyOafvzHNVpYxMQnt8HHHqNM0kyEMzcztXL2L9zDlKr0H9d+AgGGq/v4qwCh+1gFDxsHByZwMQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.12", + "@angular-devkit/architect": "0.1802.19", "@babel/core": "7.25.2", "@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-split-export-declaration": "7.24.7", @@ -2063,7 +2090,7 @@ "rollup": "4.22.4", "sass": "1.77.6", "semver": "7.6.3", - "vite": "5.4.6", + "vite": "~5.4.17", "watchpack": "2.4.1" }, "engines": { @@ -2103,13 +2130,13 @@ } }, "node_modules/@angular/build/node_modules/@angular-devkit/architect": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.12.tgz", - "integrity": "sha512-bepVb2/GtJppYKaeW8yTGE6egmoWZ7zagFDsmBdbF+BYp+HmeoPsclARcdryBPVq68zedyTRdvhWSUTbw1AYuw==", + "version": "0.1802.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.19.tgz", + "integrity": "sha512-M4B1tzxGX1nWCZr9GMM8OO0yBJO2HFSdK8M8P74vEFQfKIeq3y16IQ5zlEveJrkCOFVtmlIy2C9foMCdNyBRMA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "18.2.19", "rxjs": "7.8.1" }, "engines": { @@ -2119,9 +2146,9 @@ } }, "node_modules/@angular/build/node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2325,18 +2352,18 @@ } }, "node_modules/@angular/cli": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.12.tgz", - "integrity": "sha512-xhuZ/b7IhqNw1MgXf+arWf4x+GfUSt/IwbdWU4+CO8A7h0Y46zQywouP/KUK3cMQZfVdHdciTBvlpF3vFacA6Q==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.19.tgz", + "integrity": "sha512-LGVMTc36JQuw8QX8Sclxyei306EQW3KslopXbf7cfqt6D5/fHS+FqqA0O7V8ob/vOGMca+l6hQD27nW5Y3W6pA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.12", - "@angular-devkit/core": "18.2.12", - "@angular-devkit/schematics": "18.2.12", + "@angular-devkit/architect": "0.1802.19", + "@angular-devkit/core": "18.2.19", + "@angular-devkit/schematics": "18.2.19", "@inquirer/prompts": "5.3.8", "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.12", + "@schematics/angular": "18.2.19", "@yarnpkg/lockfile": "1.1.0", "ini": "4.1.3", "jsonc-parser": "3.3.1", @@ -2359,13 +2386,13 @@ } }, "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.12.tgz", - "integrity": "sha512-bepVb2/GtJppYKaeW8yTGE6egmoWZ7zagFDsmBdbF+BYp+HmeoPsclARcdryBPVq68zedyTRdvhWSUTbw1AYuw==", + "version": "0.1802.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.19.tgz", + "integrity": "sha512-M4B1tzxGX1nWCZr9GMM8OO0yBJO2HFSdK8M8P74vEFQfKIeq3y16IQ5zlEveJrkCOFVtmlIy2C9foMCdNyBRMA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "18.2.19", "rxjs": "7.8.1" }, "engines": { @@ -2375,9 +2402,9 @@ } }, "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2402,25 +2429,6 @@ } } }, - "node_modules/@angular/cli/node_modules/@angular-devkit/schematics": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.12.tgz", - "integrity": "sha512-mMea9txHbnCX5lXLHlo0RAgfhFHDio45/jMsREM2PA8UtVf2S8ltXz7ZwUrUyMQRv8vaSfn4ijDstF4hDMnRgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "18.2.12", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.11", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, "node_modules/@angular/cli/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2718,14 +2726,14 @@ "license": "ISC" }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -2786,15 +2794,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.0", + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" @@ -2916,13 +2925,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", + "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-annotate-as-pure": "^7.27.1", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, @@ -2934,13 +2943,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", + "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -3031,9 +3040,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -3116,18 +3125,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -3158,25 +3167,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -3616,16 +3625,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", - "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -3635,15 +3643,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -4281,6 +4289,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", @@ -4298,16 +4323,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", - "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz", + "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, @@ -4318,6 +4343,20 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4598,9 +4637,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", - "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -4610,30 +4649,30 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -4642,13 +4681,13 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -4657,26 +4696,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -5022,23 +5049,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@compodoc/compodoc/node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", @@ -5055,42 +5065,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", - "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.26.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-private-methods": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", @@ -5233,19 +5207,6 @@ "node": ">= 6" } }, - "node_modules/@compodoc/compodoc/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@compodoc/compodoc/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -8353,9 +8314,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.12.tgz", - "integrity": "sha512-FFJAwtWbtpncMOVNuULPBwFJB7GSjiUwO93eGTzRp8O4EPQ8lCQeFbezQm/NP34+T0+GBLGzPSuQT+muob8YKw==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.19.tgz", + "integrity": "sha512-bExj5JrByKPibsqBbn5Pjn8lo91AUOTsyP2hgKpnOnmSr62rhWSiRwXltgz2MCiZRmuUznpt93WiOLixgYfYvQ==", "dev": true, "license": "MIT", "engines": { @@ -9633,14 +9594,14 @@ "license": "MIT" }, "node_modules/@schematics/angular": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.12.tgz", - "integrity": "sha512-sIoeipsisK5eTLW3XuNZYcal83AfslBbgI7LnV+3VrXwpasKPGHwo2ZdwhCd2IXAkuJ02Iyu7MyV0aQRM9i/3g==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.19.tgz", + "integrity": "sha512-s9aynH/fwB/LT94miVfsaL2C4Qd5BLgjMzWFx7iJ8Hyv7FjOBGYO6eGVovjCt2c6/abG+GQAk4EBOCfg3AUtCA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", - "@angular-devkit/schematics": "18.2.12", + "@angular-devkit/core": "18.2.19", + "@angular-devkit/schematics": "18.2.19", "jsonc-parser": "3.3.1" }, "engines": { @@ -9650,9 +9611,9 @@ } }, "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz", + "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9677,25 +9638,6 @@ } } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/schematics": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.12.tgz", - "integrity": "sha512-mMea9txHbnCX5lXLHlo0RAgfhFHDio45/jMsREM2PA8UtVf2S8ltXz7ZwUrUyMQRv8vaSfn4ijDstF4hDMnRgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "18.2.12", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.11", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, "node_modules/@schematics/angular/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -21441,9 +21383,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", - "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", + "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", "dev": true, "license": "MIT", "dependencies": { @@ -24398,15 +24340,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -35658,9 +35600,9 @@ } }, "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 6fe463ac387..81f1c92d5a5 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,9 @@ "libs/**/*" ], "devDependencies": { - "@angular-devkit/build-angular": "18.2.12", + "@angular-devkit/build-angular": "18.2.19", "@angular-eslint/schematics": "18.4.3", - "@angular/cli": "18.2.12", + "@angular/cli": "18.2.19", "@angular/compiler-cli": "18.2.13", "@babel/core": "7.24.9", "@babel/preset-env": "7.24.8", @@ -46,7 +46,7 @@ "@electron/notarize": "2.5.0", "@electron/rebuild": "3.7.2", "@lit-labs/signals": "0.1.2", - "@ngtools/webpack": "18.2.12", + "@ngtools/webpack": "18.2.19", "@storybook/addon-a11y": "8.6.12", "@storybook/addon-actions": "8.6.12", "@storybook/addon-designs": "8.2.1", From e538425e7a5ce635b1fbe88835a4f392d31413ee Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 12:07:14 -0700 Subject: [PATCH 07/35] [PM-21343] - add download bitwarden to list of nudges for settings badge (#14682) * add download bitwarden to list of nudges for settings badge * update tests --- .../src/services/vault-nudges.service.spec.ts | 33 ++++++++++++++----- .../src/services/vault-nudges.service.ts | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libs/vault/src/services/vault-nudges.service.spec.ts b/libs/vault/src/services/vault-nudges.service.spec.ts index 89465fc5382..40c58644309 100644 --- a/libs/vault/src/services/vault-nudges.service.spec.ts +++ b/libs/vault/src/services/vault-nudges.service.spec.ts @@ -12,7 +12,11 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi import { FakeStateProvider, mockAccountServiceWith } from "../../../common/spec"; -import { HasItemsNudgeService, EmptyVaultNudgeService } from "./custom-nudges-services"; +import { + HasItemsNudgeService, + EmptyVaultNudgeService, + DownloadBitwardenNudgeService, +} from "./custom-nudges-services"; import { DefaultSingleNudgeService } from "./default-single-nudge.service"; import { VaultNudgesService, VaultNudgeType } from "./vault-nudges.service"; @@ -25,6 +29,8 @@ describe("Vault Nudges Service", () => { getFeatureFlag: jest.fn().mockReturnValue(true), }; + const vaultNudgeServices = [EmptyVaultNudgeService, DownloadBitwardenNudgeService]; + beforeEach(async () => { fakeStateProvider = new FakeStateProvider(mockAccountServiceWith("user-id" as UserId)); @@ -46,6 +52,10 @@ describe("Vault Nudges Service", () => { provide: HasItemsNudgeService, useValue: mock(), }, + { + provide: DownloadBitwardenNudgeService, + useValue: mock(), + }, { provide: EmptyVaultNudgeService, useValue: mock(), @@ -130,11 +140,14 @@ describe("Vault Nudges Service", () => { describe("HasActiveBadges", () => { it("should return true if a nudgeType with hasBadgeDismissed === false", async () => { - TestBed.overrideProvider(EmptyVaultNudgeService, { - useValue: { - nudgeStatus$: () => of({ hasBadgeDismissed: false, hasSpotlightDismissed: false }), - }, + vaultNudgeServices.forEach((service) => { + TestBed.overrideProvider(service, { + useValue: { + nudgeStatus$: () => of({ hasBadgeDismissed: false, hasSpotlightDismissed: false }), + }, + }); }); + const service = testBed.inject(VaultNudgesService); const result = await firstValueFrom(service.hasActiveBadges$("user-id" as UserId)); @@ -142,10 +155,12 @@ describe("Vault Nudges Service", () => { expect(result).toBe(true); }); it("should return false if all nudgeTypes have hasBadgeDismissed === true", async () => { - TestBed.overrideProvider(EmptyVaultNudgeService, { - useValue: { - nudgeStatus$: () => of({ hasBadgeDismissed: true, hasSpotlightDismissed: true }), - }, + vaultNudgeServices.forEach((service) => { + TestBed.overrideProvider(service, { + useValue: { + nudgeStatus$: () => of({ hasBadgeDismissed: true, hasSpotlightDismissed: false }), + }, + }); }); const service = testBed.inject(VaultNudgesService); diff --git a/libs/vault/src/services/vault-nudges.service.ts b/libs/vault/src/services/vault-nudges.service.ts index e04cb609d7f..be6e978eaa0 100644 --- a/libs/vault/src/services/vault-nudges.service.ts +++ b/libs/vault/src/services/vault-nudges.service.ts @@ -114,7 +114,7 @@ export class VaultNudgesService { */ hasActiveBadges$(userId: UserId): Observable { // Add more nudge types here if they have the settings badge feature - const nudgeTypes = [VaultNudgeType.EmptyVaultNudge]; + const nudgeTypes = [VaultNudgeType.EmptyVaultNudge, VaultNudgeType.DownloadBitwarden]; const nudgeTypesWithBadge$ = nudgeTypes.map((nudge) => { return this.getNudgeService(nudge) From 6b6f9577f4344daa32767824e9d209e640b5f72e Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 12:08:12 -0700 Subject: [PATCH 08/35] multiple fixes for bitwarden component (#14685) --- apps/browser/src/_locales/en/messages.json | 6 ++++ .../download-bitwarden.component.html | 36 +++++++++++++------ .../settings/download-bitwarden.component.ts | 3 +- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 1c3214a6ef7..57a0e78fd1b 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -4551,6 +4551,12 @@ "downloadFromBitwardenNow": { "message": "Download from bitwarden.com now" }, + "getItOnGooglePlay": { + "message": "Get it on Google Play" + }, + "downloadOnTheAppStore": { + "message": "Download on the App Store" + }, "permanentlyDeleteAttachmentConfirmation": { "message": "Are you sure you want to permanently delete this attachment?" }, diff --git a/apps/browser/src/vault/popup/settings/download-bitwarden.component.html b/apps/browser/src/vault/popup/settings/download-bitwarden.component.html index ad063691e76..20896a3c782 100644 --- a/apps/browser/src/vault/popup/settings/download-bitwarden.component.html +++ b/apps/browser/src/vault/popup/settings/download-bitwarden.component.html @@ -2,7 +2,6 @@ -

@@ -20,16 +19,30 @@ /> @@ -41,6 +54,7 @@ {{ "downloadFromBitwardenNow" | i18n }} diff --git a/apps/browser/src/vault/popup/settings/download-bitwarden.component.ts b/apps/browser/src/vault/popup/settings/download-bitwarden.component.ts index b51619b86d1..9f04bb58c34 100644 --- a/apps/browser/src/vault/popup/settings/download-bitwarden.component.ts +++ b/apps/browser/src/vault/popup/settings/download-bitwarden.component.ts @@ -6,7 +6,7 @@ import { firstValueFrom } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; -import { CardComponent, TypographyModule } from "@bitwarden/components"; +import { CardComponent, LinkModule, TypographyModule } from "@bitwarden/components"; import { VaultNudgesService, VaultNudgeType } from "@bitwarden/vault"; import { CurrentAccountComponent } from "../../../auth/popup/account-switching/current-account.component"; @@ -27,6 +27,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co CardComponent, TypographyModule, CurrentAccountComponent, + LinkModule, ], }) export class DownloadBitwardenComponent implements OnInit { From 51e327e20bdd44f83af4991b8246ebfc12ed6718 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Fri, 9 May 2025 21:39:38 +0200 Subject: [PATCH 09/35] Clean up stretchKey (#14520) --- .../services/key-generation.service.spec.ts | 20 +++++++++++++++++++ .../services/key-generation.service.ts | 10 ++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/libs/common/src/platform/services/key-generation.service.spec.ts b/libs/common/src/platform/services/key-generation.service.spec.ts index f75eaeb25be..0a9e997b428 100644 --- a/libs/common/src/platform/services/key-generation.service.spec.ts +++ b/libs/common/src/platform/services/key-generation.service.spec.ts @@ -5,6 +5,7 @@ import { PBKDF2KdfConfig, Argon2KdfConfig } from "@bitwarden/key-management"; import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service"; import { CsprngArray } from "../../types/csprng"; import { EncryptionType } from "../enums"; +import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; import { KeyGenerationService } from "./key-generation.service"; @@ -98,4 +99,23 @@ describe("KeyGenerationService", () => { expect(key.inner().type).toEqual(EncryptionType.AesCbc256_B64); }); }); + + describe("stretchKey", () => { + it("should stretch a key", async () => { + const key = new SymmetricCryptoKey(new Uint8Array(32)); + + cryptoFunctionService.hkdf.mockResolvedValue(new Uint8Array(64)); + + const stretchedKey = await sut.stretchKey(key); + + expect(stretchedKey.inner().type).toEqual(EncryptionType.AesCbc256_HmacSha256_B64); + }); + it("should throw if key is not 32 bytes", async () => { + const key = new SymmetricCryptoKey(new Uint8Array(64)); + + await expect(sut.stretchKey(key)).rejects.toThrow( + "Key passed into stretchKey is not a 256-bit key.", + ); + }); + }); }); diff --git a/libs/common/src/platform/services/key-generation.service.ts b/libs/common/src/platform/services/key-generation.service.ts index 8f9e6856aa0..dcd1f4f95d7 100644 --- a/libs/common/src/platform/services/key-generation.service.ts +++ b/libs/common/src/platform/services/key-generation.service.ts @@ -1,11 +1,11 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { MasterKey, PinKey } from "@bitwarden/common/types/key"; import { KdfConfig, PBKDF2KdfConfig, Argon2KdfConfig, KdfType } from "@bitwarden/key-management"; import { CryptoFunctionService } from "../../key-management/crypto/abstractions/crypto-function.service"; import { CsprngArray } from "../../types/csprng"; import { KeyGenerationService as KeyGenerationServiceAbstraction } from "../abstractions/key-generation.service"; +import { EncryptionType } from "../enums"; import { Utils } from "../misc/utils"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; @@ -79,7 +79,13 @@ export class KeyGenerationService implements KeyGenerationServiceAbstraction { return new SymmetricCryptoKey(key); } - async stretchKey(key: MasterKey | PinKey): Promise { + async stretchKey(key: SymmetricCryptoKey): Promise { + // The key to be stretched is actually usually the output of a KDF, and not actually meant for AesCbc256_B64 encryption, + // but has the same key length. Only 256-bit key materials should be stretched. + if (key.inner().type != EncryptionType.AesCbc256_B64) { + throw new Error("Key passed into stretchKey is not a 256-bit key."); + } + const newKey = new Uint8Array(64); // Master key and pin key are always 32 bytes const encKey = await this.cryptoFunctionService.hkdfExpand( From 83dc4706f3605d9dd7cb7c4aa5e529f858d006cf Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Fri, 9 May 2025 16:21:47 -0400 Subject: [PATCH 10/35] [PM-21279] Cipher for url speedup (#14684) * Use `perUserCache$` for `getAllDecryptedForUrl` * Fix loads before first lock * Filter out null ciphers --- libs/common/src/vault/services/cipher.service.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index a32568c8112..169568d44e9 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -519,8 +519,15 @@ export class CipherService implements CipherServiceAbstraction { includeOtherTypes?: CipherType[], defaultMatch: UriMatchStrategySetting = null, ): Promise { - const ciphers = await this.getAllDecrypted(userId); - return await this.filterCiphersForUrl(ciphers, url, includeOtherTypes, defaultMatch); + return await firstValueFrom( + this.cipherViews$(userId).pipe( + filter((c) => c != null), + switchMap( + async (ciphers) => + await this.filterCiphersForUrl(ciphers, url, includeOtherTypes, defaultMatch), + ), + ), + ); } async filterCiphersForUrl( From 5470d6a6d97c9f0e94b901e41ded66bb5ca49168 Mon Sep 17 00:00:00 2001 From: Miles Blackwood Date: Fri, 9 May 2025 17:30:32 -0400 Subject: [PATCH 11/35] Fix i18n key mis-entry. (#14711) --- apps/browser/src/autofill/notification/bar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/browser/src/autofill/notification/bar.ts b/apps/browser/src/autofill/notification/bar.ts index 4b9ba58d586..3fd6016eb33 100644 --- a/apps/browser/src/autofill/notification/bar.ts +++ b/apps/browser/src/autofill/notification/bar.ts @@ -61,7 +61,7 @@ function getI18n() { loginSaveSuccess: chrome.i18n.getMessage("loginSaveSuccess"), loginSaveConfirmation: chrome.i18n.getMessage("loginSaveConfirmation"), loginUpdateSuccess: chrome.i18n.getMessage("loginUpdateSuccess"), - loginUpdateConfirmation: chrome.i18n.getMessage("loginUpdatedConfirmation"), + loginUpdatedConfirmation: chrome.i18n.getMessage("loginUpdatedConfirmation"), loginUpdateTaskSuccess: chrome.i18n.getMessage("loginUpdateTaskSuccess"), loginUpdateTaskSuccessAdditional: chrome.i18n.getMessage("loginUpdateTaskSuccessAdditional"), nextSecurityTaskAction: chrome.i18n.getMessage("nextSecurityTaskAction"), From 1b756df749a23b33f6f69b9740a8c3ce6a6fb5fb Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Fri, 9 May 2025 20:21:25 -0400 Subject: [PATCH 12/35] [PM-14484] `ApiService` showing html in error message (#14658) * Make ApiService more testable * Add ApiService tests * Switch to only reading text/plain content --- .../browser/src/background/main.background.ts | 1 + .../src/platform/services/node-api.service.ts | 1 + libs/angular/src/services/injection-tokens.ts | 3 + .../src/services/jslib-services.module.ts | 6 + libs/common/src/services/api.service.spec.ts | 203 ++++++++++++++++++ libs/common/src/services/api.service.ts | 27 ++- 6 files changed, 230 insertions(+), 11 deletions(-) create mode 100644 libs/common/src/services/api.service.spec.ts diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index d295fddda52..85a9cd27c57 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -720,6 +720,7 @@ export default class MainBackground { this.logService, (logoutReason: LogoutReason, userId?: UserId) => this.logout(logoutReason, userId), this.vaultTimeoutSettingsService, + { createRequest: (url, request) => new Request(url, request) }, ); this.fileUploadService = new FileUploadService(this.logService, this.apiService); diff --git a/apps/cli/src/platform/services/node-api.service.ts b/apps/cli/src/platform/services/node-api.service.ts index 8c7629fb3d9..d695272364b 100644 --- a/apps/cli/src/platform/services/node-api.service.ts +++ b/apps/cli/src/platform/services/node-api.service.ts @@ -39,6 +39,7 @@ export class NodeApiService extends ApiService { logService, logoutCallback, vaultTimeoutSettingsService, + { createRequest: (url, request) => new Request(url, request) }, customUserAgent, ); } diff --git a/libs/angular/src/services/injection-tokens.ts b/libs/angular/src/services/injection-tokens.ts index a63d862b0d8..d82ff021962 100644 --- a/libs/angular/src/services/injection-tokens.ts +++ b/libs/angular/src/services/injection-tokens.ts @@ -13,6 +13,7 @@ import { import { Theme } from "@bitwarden/common/platform/enums"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; import { Message } from "@bitwarden/common/platform/messaging"; +import { HttpOperations } from "@bitwarden/common/services/api.service"; import { SafeInjectionToken } from "@bitwarden/ui-common"; // Re-export the SafeInjectionToken from ui-common export { SafeInjectionToken } from "@bitwarden/ui-common"; @@ -61,3 +62,5 @@ export const REFRESH_ACCESS_TOKEN_ERROR_CALLBACK = new SafeInjectionToken<() => export const ENV_ADDITIONAL_REGIONS = new SafeInjectionToken( "ENV_ADDITIONAL_REGIONS", ); + +export const HTTP_OPERATIONS = new SafeInjectionToken("HTTP_OPERATIONS"); diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index d82df8574ff..4e7c558a0f0 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -337,6 +337,7 @@ import { CLIENT_TYPE, DEFAULT_VAULT_TIMEOUT, ENV_ADDITIONAL_REGIONS, + HTTP_OPERATIONS, INTRAPROCESS_MESSAGING_SUBJECT, LOCALES_DIRECTORY, LOCKED_CALLBACK, @@ -700,6 +701,10 @@ const safeProviders: SafeProvider[] = [ }, deps: [ToastService, I18nServiceAbstraction], }), + safeProvider({ + provide: HTTP_OPERATIONS, + useValue: { createRequest: (url, request) => new Request(url, request) }, + }), safeProvider({ provide: ApiServiceAbstraction, useClass: ApiService, @@ -712,6 +717,7 @@ const safeProviders: SafeProvider[] = [ LogService, LOGOUT_CALLBACK, VaultTimeoutSettingsService, + HTTP_OPERATIONS, ], }), safeProvider({ diff --git a/libs/common/src/services/api.service.spec.ts b/libs/common/src/services/api.service.spec.ts new file mode 100644 index 00000000000..eca6066b9b7 --- /dev/null +++ b/libs/common/src/services/api.service.spec.ts @@ -0,0 +1,203 @@ +import { mock, MockProxy } from "jest-mock-extended"; +import { of } from "rxjs"; + +import { LogoutReason } from "@bitwarden/auth/common"; + +import { TokenService } from "../auth/abstractions/token.service"; +import { DeviceType } from "../enums"; +import { VaultTimeoutSettingsService } from "../key-management/vault-timeout"; +import { ErrorResponse } from "../models/response/error.response"; +import { AppIdService } from "../platform/abstractions/app-id.service"; +import { Environment, EnvironmentService } from "../platform/abstractions/environment.service"; +import { LogService } from "../platform/abstractions/log.service"; +import { PlatformUtilsService } from "../platform/abstractions/platform-utils.service"; + +import { ApiService, HttpOperations } from "./api.service"; + +describe("ApiService", () => { + let tokenService: MockProxy; + let platformUtilsService: MockProxy; + let environmentService: MockProxy; + let appIdService: MockProxy; + let refreshAccessTokenErrorCallback: jest.Mock; + let logService: MockProxy; + let logoutCallback: jest.Mock, [reason: LogoutReason]>; + let vaultTimeoutSettingsService: MockProxy; + let httpOperations: MockProxy; + + let sut: ApiService; + + beforeEach(() => { + tokenService = mock(); + platformUtilsService = mock(); + platformUtilsService.getDevice.mockReturnValue(DeviceType.ChromeExtension); + + environmentService = mock(); + appIdService = mock(); + refreshAccessTokenErrorCallback = jest.fn(); + logService = mock(); + logoutCallback = jest.fn(); + vaultTimeoutSettingsService = mock(); + httpOperations = mock(); + + sut = new ApiService( + tokenService, + platformUtilsService, + environmentService, + appIdService, + refreshAccessTokenErrorCallback, + logService, + logoutCallback, + vaultTimeoutSettingsService, + httpOperations, + "custom-user-agent", + ); + }); + + describe("send", () => { + it("handles ok GET", async () => { + environmentService.environment$ = of({ + getApiUrl: () => "https://example.com", + } satisfies Partial as Environment); + + httpOperations.createRequest.mockImplementation((url, request) => { + return { + url: url, + cache: request.cache, + credentials: request.credentials, + method: request.method, + mode: request.mode, + signal: request.signal, + headers: new Headers(request.headers), + } satisfies Partial as unknown as Request; + }); + + tokenService.getAccessToken.mockResolvedValue("access_token"); + tokenService.tokenNeedsRefresh.mockResolvedValue(false); + + const nativeFetch = jest.fn, [request: Request]>(); + + nativeFetch.mockImplementation((request) => { + return Promise.resolve({ + ok: true, + status: 200, + json: () => Promise.resolve({ hello: "world" }), + headers: new Headers({ + "content-type": "application/json", + }), + } satisfies Partial as Response); + }); + + sut.nativeFetch = nativeFetch; + + const response = await sut.send("GET", "/something", null, true, true, null, null); + + expect(nativeFetch).toHaveBeenCalledTimes(1); + const request = nativeFetch.mock.calls[0][0]; + // This should get set for users of send + expect(request.cache).toBe("no-store"); + // TODO: Could expect on the credentials parameter + expect(request.headers.get("Device-Type")).toBe("2"); // Chrome Extension + // Custom user agent should get set + expect(request.headers.get("User-Agent")).toBe("custom-user-agent"); + // This should be set when the caller has indicated there is a response + expect(request.headers.get("Accept")).toBe("application/json"); + // If they have indicated that it's authed, then the authorization header should get set. + expect(request.headers.get("Authorization")).toBe("Bearer access_token"); + // The response body + expect(response).toEqual({ hello: "world" }); + }); + }); + + const errorData: { + name: string; + input: Partial; + error: Partial; + }[] = [ + { + name: "json response in camel case", + input: { + json: () => Promise.resolve({ message: "Something bad happened." }), + headers: new Headers({ + "content-type": "application/json", + }), + }, + error: { + message: "Something bad happened.", + }, + }, + { + name: "json response in pascal case", + input: { + json: () => Promise.resolve({ Message: "Something bad happened." }), + headers: new Headers({ + "content-type": "application/json", + }), + }, + error: { + message: "Something bad happened.", + }, + }, + { + name: "json response with charset in content type", + input: { + json: () => Promise.resolve({ message: "Something bad happened." }), + headers: new Headers({ + "content-type": "application/json; charset=utf-8", + }), + }, + error: { + message: "Something bad happened.", + }, + }, + { + name: "text/plain response", + input: { + text: () => Promise.resolve("Something bad happened."), + headers: new Headers({ + "content-type": "text/plain", + }), + }, + error: { + message: "Something bad happened.", + }, + }, + ]; + + it.each(errorData)( + "throws error-like response when not ok response with $name", + async ({ input, error }) => { + environmentService.environment$ = of({ + getApiUrl: () => "https://example.com", + } satisfies Partial as Environment); + + httpOperations.createRequest.mockImplementation((url, request) => { + return { + url: url, + cache: request.cache, + credentials: request.credentials, + method: request.method, + mode: request.mode, + signal: request.signal, + headers: new Headers(request.headers), + } satisfies Partial as unknown as Request; + }); + + const nativeFetch = jest.fn, [request: Request]>(); + + nativeFetch.mockImplementation((request) => { + return Promise.resolve({ + ok: false, + status: 400, + ...input, + } satisfies Partial as Response); + }); + + sut.nativeFetch = nativeFetch; + + await expect( + async () => await sut.send("GET", "/something", null, true, true, null, null), + ).rejects.toMatchObject(error); + }, + ); +}); diff --git a/libs/common/src/services/api.service.ts b/libs/common/src/services/api.service.ts index fb4d08db81c..5c4bcdedb26 100644 --- a/libs/common/src/services/api.service.ts +++ b/libs/common/src/services/api.service.ts @@ -139,6 +139,10 @@ import { AttachmentResponse } from "../vault/models/response/attachment.response import { CipherResponse } from "../vault/models/response/cipher.response"; import { OptionalCipherResponse } from "../vault/models/response/optional-cipher.response"; +export type HttpOperations = { + createRequest: (url: string, request: RequestInit) => Request; +}; + /** * @deprecated The `ApiService` class is deprecated and calls should be extracted into individual * api services. The `send` method is still allowed to be used within api services. For background @@ -166,6 +170,7 @@ export class ApiService implements ApiServiceAbstraction { private logService: LogService, private logoutCallback: (logoutReason: LogoutReason) => Promise, private vaultTimeoutSettingsService: VaultTimeoutSettingsService, + private readonly httpOperations: HttpOperations, private customUserAgent: string = null, ) { this.device = platformUtilsService.getDevice(); @@ -217,7 +222,7 @@ export class ApiService implements ApiServiceAbstraction { const env = await firstValueFrom(this.environmentService.environment$); const response = await this.fetch( - new Request(env.getIdentityUrl() + "/connect/token", { + this.httpOperations.createRequest(env.getIdentityUrl() + "/connect/token", { body: this.qsStringify(identityToken), credentials: await this.getCredentials(), cache: "no-store", @@ -1409,7 +1414,7 @@ export class ApiService implements ApiServiceAbstraction { } const env = await firstValueFrom(this.environmentService.environment$); const response = await this.fetch( - new Request(env.getEventsUrl() + "/collect", { + this.httpOperations.createRequest(env.getEventsUrl() + "/collect", { cache: "no-store", credentials: await this.getCredentials(), method: "POST", @@ -1456,7 +1461,7 @@ export class ApiService implements ApiServiceAbstraction { const authHeader = await this.getActiveBearerToken(); const response = await this.fetch( - new Request(keyConnectorUrl + "/user-keys", { + this.httpOperations.createRequest(keyConnectorUrl + "/user-keys", { cache: "no-store", method: "GET", headers: new Headers({ @@ -1481,7 +1486,7 @@ export class ApiService implements ApiServiceAbstraction { const authHeader = await this.getActiveBearerToken(); const response = await this.fetch( - new Request(keyConnectorUrl + "/user-keys", { + this.httpOperations.createRequest(keyConnectorUrl + "/user-keys", { cache: "no-store", method: "POST", headers: new Headers({ @@ -1501,7 +1506,7 @@ export class ApiService implements ApiServiceAbstraction { async getKeyConnectorAlive(keyConnectorUrl: string) { const response = await this.fetch( - new Request(keyConnectorUrl + "/alive", { + this.httpOperations.createRequest(keyConnectorUrl + "/alive", { cache: "no-store", method: "GET", headers: new Headers({ @@ -1570,7 +1575,7 @@ export class ApiService implements ApiServiceAbstraction { const env = await firstValueFrom(this.environmentService.environment$); const path = `/sso/prevalidate?domainHint=${encodeURIComponent(identifier)}`; const response = await this.fetch( - new Request(env.getIdentityUrl() + path, { + this.httpOperations.createRequest(env.getIdentityUrl() + path, { cache: "no-store", credentials: await this.getCredentials(), headers: headers, @@ -1711,7 +1716,7 @@ export class ApiService implements ApiServiceAbstraction { const env = await firstValueFrom(this.environmentService.environment$); const decodedToken = await this.tokenService.decodeAccessToken(); const response = await this.fetch( - new Request(env.getIdentityUrl() + "/connect/token", { + this.httpOperations.createRequest(env.getIdentityUrl() + "/connect/token", { body: this.qsStringify({ grant_type: "refresh_token", client_id: decodedToken.client_id, @@ -1820,7 +1825,7 @@ export class ApiService implements ApiServiceAbstraction { }; requestInit.headers = requestHeaders; requestInit.body = requestBody; - const response = await this.fetch(new Request(requestUrl, requestInit)); + const response = await this.fetch(this.httpOperations.createRequest(requestUrl, requestInit)); const responseType = response.headers.get("content-type"); const responseIsJson = responseType != null && responseType.indexOf("application/json") !== -1; @@ -1889,7 +1894,7 @@ export class ApiService implements ApiServiceAbstraction { let responseJson: any = null; if (this.isJsonResponse(response)) { responseJson = await response.json(); - } else if (this.isTextResponse(response)) { + } else if (this.isTextPlainResponse(response)) { responseJson = { Message: await response.text() }; } @@ -1945,8 +1950,8 @@ export class ApiService implements ApiServiceAbstraction { return typeHeader != null && typeHeader.indexOf("application/json") > -1; } - private isTextResponse(response: Response): boolean { + private isTextPlainResponse(response: Response): boolean { const typeHeader = response.headers.get("content-type"); - return typeHeader != null && typeHeader.indexOf("text") > -1; + return typeHeader != null && typeHeader.indexOf("text/plain") > -1; } } From 23d4f04b22d52a690de0f6e1ba0918bbcf142c0d Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 17:51:34 -0700 Subject: [PATCH 13/35] set cipher form to partial edit for non edit permission (#14639) --- apps/desktop/src/vault/app/vault/vault-v2.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/desktop/src/vault/app/vault/vault-v2.component.ts b/apps/desktop/src/vault/app/vault/vault-v2.component.ts index 4da2db101ed..66e77580d1c 100644 --- a/apps/desktop/src/vault/app/vault/vault-v2.component.ts +++ b/apps/desktop/src/vault/app/vault/vault-v2.component.ts @@ -514,6 +514,9 @@ export class VaultV2Component implements OnInit, OnDestroy { this.cipherId = cipher.id; this.cipher = cipher; await this.buildFormConfig("edit"); + if (!cipher.edit && this.config) { + this.config.mode = "partial-edit"; + } this.action = "edit"; await this.go().catch(() => {}); } From 2282a74abda260dd21916c3e330409c2a3e181e8 Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Fri, 9 May 2025 18:09:26 -0700 Subject: [PATCH 14/35] [PM-21021] - fix toggled hidden field state for custom fields view (#14595) * fix toggled hidden field state for custom fields view * fix hidden field toggle for cards and login details --- .../card-details-view.component.html | 2 ++ .../card-details-view.component.ts | 19 +++++++++++++++++-- .../custom-fields-v2.component.ts | 10 ++++++++-- .../login-credentials-view.component.html | 1 + .../login-credentials-view.component.ts | 19 +++++++++++++++++-- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/libs/vault/src/cipher-view/card-details/card-details-view.component.html b/libs/vault/src/cipher-view/card-details/card-details-view.component.html index fff771b6465..ff61addd7db 100644 --- a/libs/vault/src/cipher-view/card-details/card-details-view.component.html +++ b/libs/vault/src/cipher-view/card-details/card-details-view.component.html @@ -33,6 +33,7 @@ bitIconButton bitPasswordInputToggle data-testid="toggle-number" + [toggled]="revealCardNumber" (toggledChange)="logCardEvent($event, EventType.Cipher_ClientToggledCardNumberVisible)" > diff --git a/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts b/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts index 27d81f32ee6..d99ac438f27 100644 --- a/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts +++ b/libs/vault/src/cipher-view/login-credentials/login-credentials-view.component.ts @@ -1,7 +1,15 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { CommonModule, DatePipe } from "@angular/common"; -import { Component, EventEmitter, inject, Input, Output } from "@angular/core"; +import { + Component, + EventEmitter, + inject, + Input, + OnChanges, + Output, + SimpleChanges, +} from "@angular/core"; import { Observable, switchMap } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; @@ -51,7 +59,7 @@ type TotpCodeValues = { LinkModule, ], }) -export class LoginCredentialsViewComponent { +export class LoginCredentialsViewComponent implements OnChanges { @Input() cipher: CipherView; @Input() activeUserId: UserId; @Input() hadPendingChangePasswordTask: boolean; @@ -85,6 +93,13 @@ export class LoginCredentialsViewComponent { return `${dateCreated} ${creationDate}`; } + ngOnChanges(changes: SimpleChanges): void { + if (changes["cipher"]) { + this.passwordRevealed = false; + this.showPasswordCount = false; + } + } + async getPremium(organizationId?: string) { await this.premiumUpgradeService.promptForPremium(organizationId); } From 5408a62b7df4631564601fb5fc056e718b6c74f9 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 12 May 2025 11:41:45 +0200 Subject: [PATCH 15/35] [PM-21001] Move KM usage of encrypt service (#14541) * Add new encrypt service functions * Undo changes * Cleanup * Fix build * Fix comments * Move KM usage of encrypt service * Fix build --- .../background/nativeMessaging.background.ts | 5 +-- .../biometric-message-handler.service.spec.ts | 8 ++-- .../biometric-message-handler.service.ts | 4 +- .../crypto/abstractions/encrypt.service.ts | 1 + .../device-trust.service.implementation.ts | 11 +++-- .../services/device-trust.service.spec.ts | 42 ++++++++++--------- .../services/master-password.service.ts | 16 ++----- libs/key-management/src/key.service.spec.ts | 20 +++++---- libs/key-management/src/key.service.ts | 5 +-- ...symmetric-key-regeneration.service.spec.ts | 3 ++ 10 files changed, 59 insertions(+), 56 deletions(-) diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts index d92826765db..7172b98d727 100644 --- a/apps/browser/src/background/nativeMessaging.background.ts +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -357,7 +357,7 @@ export class NativeMessagingBackground { await this.secureCommunication(); } - return await this.encryptService.encrypt( + return await this.encryptService.encryptString( JSON.stringify(message), this.secureChannel!.sharedSecret!, ); @@ -401,10 +401,9 @@ export class NativeMessagingBackground { return; } message = JSON.parse( - await this.encryptService.decryptToUtf8( + await this.encryptService.decryptString( rawMessage as EncString, this.secureChannel.sharedSecret, - "ipc-desktop-ipc-channel-key", ), ); } else { diff --git a/apps/desktop/src/services/biometric-message-handler.service.spec.ts b/apps/desktop/src/services/biometric-message-handler.service.spec.ts index 9ddc3da8ed4..af18828b59d 100644 --- a/apps/desktop/src/services/biometric-message-handler.service.spec.ts +++ b/apps/desktop/src/services/biometric-message-handler.service.spec.ts @@ -347,7 +347,7 @@ describe("BiometricMessageHandlerService", () => { trusted: false, }), ); - encryptService.decryptToUtf8.mockResolvedValue( + encryptService.decryptString.mockResolvedValue( JSON.stringify({ command: "biometricUnlock", messageId: 0, @@ -382,7 +382,7 @@ describe("BiometricMessageHandlerService", () => { ngZone.run.mockReturnValue({ closed: of(true), }); - encryptService.decryptToUtf8.mockResolvedValue( + encryptService.decryptString.mockResolvedValue( JSON.stringify({ command: BiometricsCommands.UnlockWithBiometricsForUser, messageId: 0, @@ -433,7 +433,7 @@ describe("BiometricMessageHandlerService", () => { ngZone.run.mockReturnValue({ closed: of(false), }); - encryptService.decryptToUtf8.mockResolvedValue( + encryptService.decryptString.mockResolvedValue( JSON.stringify({ command: BiometricsCommands.UnlockWithBiometricsForUser, messageId: 0, @@ -480,7 +480,7 @@ describe("BiometricMessageHandlerService", () => { trusted: true, }), ); - encryptService.decryptToUtf8.mockResolvedValue( + encryptService.decryptString.mockResolvedValue( JSON.stringify({ command: BiometricsCommands.UnlockWithBiometricsForUser, messageId: 0, diff --git a/apps/desktop/src/services/biometric-message-handler.service.ts b/apps/desktop/src/services/biometric-message-handler.service.ts index 3851f40505b..42d7b8aae5f 100644 --- a/apps/desktop/src/services/biometric-message-handler.service.ts +++ b/apps/desktop/src/services/biometric-message-handler.service.ts @@ -175,7 +175,7 @@ export class BiometricMessageHandlerService { } const message: LegacyMessage = JSON.parse( - await this.encryptService.decryptToUtf8( + await this.encryptService.decryptString( rawMessage as EncString, SymmetricCryptoKey.fromString(sessionSecret), ), @@ -365,7 +365,7 @@ export class BiometricMessageHandlerService { throw new Error("Session secret is missing"); } - const encrypted = await this.encryptService.encrypt( + const encrypted = await this.encryptService.encryptString( JSON.stringify(message), SymmetricCryptoKey.fromString(sessionSecret), ); diff --git a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts index 7a6c9bcd800..8bd58a21b6e 100644 --- a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts +++ b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts @@ -49,6 +49,7 @@ export abstract class EncryptService { key: SymmetricCryptoKey, decryptTrace?: string, ): Promise; + /** * @deprecated Replaced by BulkEncryptService, remove once the feature is tested and the featureflag PM-4154-multi-worker-encryption-service is removed * @param items The items to decrypt diff --git a/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts b/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts index 06999cab9c3..5e89e0a5cb7 100644 --- a/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts +++ b/libs/common/src/key-management/device-trust/services/device-trust.service.implementation.ts @@ -209,7 +209,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { devices.data .filter((device) => device.isTrusted) .map(async (device) => { - const publicKey = await this.encryptService.decryptToBytes( + const publicKey = await this.encryptService.unwrapEncapsulationKey( new EncString(device.encryptedPublicKey), oldUserKey, ); @@ -220,7 +220,10 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { return null; } - const newEncryptedPublicKey = await this.encryptService.encrypt(publicKey, newUserKey); + const newEncryptedPublicKey = await this.encryptService.wrapEncapsulationKey( + publicKey, + newUserKey, + ); const newEncryptedUserKey = await this.encryptService.encapsulateKeyUnsigned( newUserKey, publicKey, @@ -278,7 +281,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { const currentDeviceKeys = await this.devicesApiService.getDeviceKeys(deviceIdentifier); // Decrypt the existing device public key with the old user key - const decryptedDevicePublicKey = await this.encryptService.decryptToBytes( + const decryptedDevicePublicKey = await this.encryptService.unwrapEncapsulationKey( currentDeviceKeys.encryptedPublicKey, oldUserKey, ); @@ -394,7 +397,7 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction { try { // attempt to decrypt encryptedDevicePrivateKey with device key - const devicePrivateKey = await this.encryptService.decryptToBytes( + const devicePrivateKey = await this.encryptService.unwrapDecapsulationKey( encryptedDevicePrivateKey, deviceKey, ); diff --git a/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts b/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts index 7d4a25c1f08..de9de5d781a 100644 --- a/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts +++ b/libs/common/src/key-management/device-trust/services/device-trust.service.spec.ts @@ -623,9 +623,9 @@ describe("deviceTrustService", () => { }); it("successfully returns the user key when provided keys (including device key) can decrypt it", async () => { - const decryptToBytesSpy = jest - .spyOn(encryptService, "decryptToBytes") - .mockResolvedValue(new Uint8Array(userKeyBytesLength)); + const unwrapDecapsulationKeySpy = jest + .spyOn(encryptService, "unwrapDecapsulationKey") + .mockResolvedValue(new Uint8Array(2048)); const rsaDecryptSpy = jest .spyOn(encryptService, "decapsulateKeyUnsigned") .mockResolvedValue(new SymmetricCryptoKey(new Uint8Array(userKeyBytesLength))); @@ -638,13 +638,13 @@ describe("deviceTrustService", () => { ); expect(result).toEqual(mockUserKey); - expect(decryptToBytesSpy).toHaveBeenCalledTimes(1); + expect(unwrapDecapsulationKeySpy).toHaveBeenCalledTimes(1); expect(rsaDecryptSpy).toHaveBeenCalledTimes(1); }); it("returns null and removes device key when the decryption fails", async () => { - const decryptToBytesSpy = jest - .spyOn(encryptService, "decryptToBytes") + const unwrapDecapsulationKeySpy = jest + .spyOn(encryptService, "unwrapDecapsulationKey") .mockRejectedValue(new Error("Decryption error")); const setDeviceKeySpy = jest.spyOn(deviceTrustService as any, "setDeviceKey"); @@ -656,7 +656,7 @@ describe("deviceTrustService", () => { ); expect(result).toBeNull(); - expect(decryptToBytesSpy).toHaveBeenCalledTimes(1); + expect(unwrapDecapsulationKeySpy).toHaveBeenCalledTimes(1); expect(setDeviceKeySpy).toHaveBeenCalledTimes(1); expect(setDeviceKeySpy).toHaveBeenCalledWith(mockUserId, null); }); @@ -704,8 +704,8 @@ describe("deviceTrustService", () => { DeviceResponse, ), ); - encryptService.decryptToBytes.mockResolvedValue(null); - encryptService.encrypt.mockResolvedValue(new EncString("test_encrypted_data")); + encryptService.decryptBytes.mockResolvedValue(null); + encryptService.encryptString.mockResolvedValue(new EncString("test_encrypted_data")); encryptService.encapsulateKeyUnsigned.mockResolvedValue( new EncString("test_encrypted_data"), ); @@ -752,9 +752,11 @@ describe("deviceTrustService", () => { DeviceResponse, ), ); - encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(64)); - encryptService.encrypt.mockResolvedValue(new EncString("test_encrypted_data")); - encryptService.rsaEncrypt.mockResolvedValue(new EncString("test_encrypted_data")); + encryptService.unwrapEncapsulationKey.mockResolvedValue(new Uint8Array(64)); + encryptService.wrapEncapsulationKey.mockResolvedValue(new EncString("test_encrypted_data")); + encryptService.encapsulateKeyUnsigned.mockResolvedValue( + new EncString("test_encrypted_data"), + ); const protectedDeviceResponse = new ProtectedDeviceResponse({ id: "", @@ -862,13 +864,15 @@ describe("deviceTrustService", () => { }); // Mock the decryption of the public key with the old user key - encryptService.decryptToBytes.mockImplementationOnce((_encValue, privateKeyValue) => { - expect(privateKeyValue.inner().type).toBe(EncryptionType.AesCbc256_HmacSha256_B64); - expect(new Uint8Array(privateKeyValue.toEncoded())[0]).toBe(FakeOldUserKeyMarker); - const data = new Uint8Array(250); - data.fill(FakeDecryptedPublicKeyMarker, 0, 1); - return Promise.resolve(data); - }); + encryptService.unwrapEncapsulationKey.mockImplementationOnce( + (_encValue, privateKeyValue) => { + expect(privateKeyValue.inner().type).toBe(EncryptionType.AesCbc256_HmacSha256_B64); + expect(new Uint8Array(privateKeyValue.toEncoded())[0]).toBe(FakeOldUserKeyMarker); + const data = new Uint8Array(250); + data.fill(FakeDecryptedPublicKeyMarker, 0, 1); + return Promise.resolve(data); + }, + ); // Mock the encryption of the new user key with the decrypted public key encryptService.encapsulateKeyUnsigned.mockImplementationOnce((data, publicKey) => { diff --git a/libs/common/src/key-management/master-password/services/master-password.service.ts b/libs/common/src/key-management/master-password/services/master-password.service.ts index 72b18d8bfba..b9b11d6cbe8 100644 --- a/libs/common/src/key-management/master-password/services/master-password.service.ts +++ b/libs/common/src/key-management/master-password/services/master-password.service.ts @@ -174,21 +174,13 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr throw new Error("No master key found."); } - let decUserKey: Uint8Array; + let decUserKey: SymmetricCryptoKey; if (userKey.encryptionType === EncryptionType.AesCbc256_B64) { - decUserKey = await this.encryptService.decryptToBytes( - userKey, - masterKey, - "Content: User Key; Encrypting Key: Master Key", - ); + decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, masterKey); } else if (userKey.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) { const newKey = await this.keyGenerationService.stretchKey(masterKey); - decUserKey = await this.encryptService.decryptToBytes( - userKey, - newKey, - "Content: User Key; Encrypting Key: Stretched Master Key", - ); + decUserKey = await this.encryptService.unwrapSymmetricKey(userKey, newKey); } else { throw new Error("Unsupported encryption type."); } @@ -198,6 +190,6 @@ export class MasterPasswordService implements InternalMasterPasswordServiceAbstr return null; } - return new SymmetricCryptoKey(decUserKey) as UserKey; + return decUserKey as UserKey; } } diff --git a/libs/key-management/src/key.service.spec.ts b/libs/key-management/src/key.service.spec.ts index 57291462924..25d8aff99fb 100644 --- a/libs/key-management/src/key.service.spec.ts +++ b/libs/key-management/src/key.service.spec.ts @@ -330,7 +330,7 @@ describe("keyService", () => { everHadUserKeyState.nextState(null); // Mock private key decryption - encryptService.decryptToBytes.mockResolvedValue(mockRandomBytes); + encryptService.unwrapDecapsulationKey.mockResolvedValue(mockRandomBytes); }); it("throws if userKey is null", async () => { @@ -352,7 +352,7 @@ describe("keyService", () => { }); it("throws if encPrivateKey cannot be decrypted with the userKey", async () => { - encryptService.decryptToBytes.mockResolvedValue(null); + encryptService.unwrapDecapsulationKey.mockResolvedValue(null); await expect( keyService.setUserKeys(mockUserKey, mockEncPrivateKey, mockUserId), @@ -452,17 +452,16 @@ describe("keyService", () => { // Decryption of the user private key const fakeDecryptedUserPrivateKey = makeStaticByteArray(10, 1); - encryptService.decryptToBytes.mockResolvedValue(fakeDecryptedUserPrivateKey); + encryptService.unwrapDecapsulationKey.mockResolvedValue(fakeDecryptedUserPrivateKey); const fakeUserPublicKey = makeStaticByteArray(10, 2); cryptoFunctionService.rsaExtractPublicKey.mockResolvedValue(fakeUserPublicKey); const userPrivateKey = await firstValueFrom(keyService.userPrivateKey$(mockUserId)); - expect(encryptService.decryptToBytes).toHaveBeenCalledWith( + expect(encryptService.unwrapDecapsulationKey).toHaveBeenCalledWith( fakeEncryptedUserPrivateKey, userKey, - "Content: Encrypted Private Key", ); expect(userPrivateKey).toBe(fakeDecryptedUserPrivateKey); @@ -473,7 +472,7 @@ describe("keyService", () => { const userPrivateKey = await firstValueFrom(keyService.userPrivateKey$(mockUserId)); - expect(encryptService.decryptToBytes).not.toHaveBeenCalled(); + expect(encryptService.unwrapDecapsulationKey).not.toHaveBeenCalled(); expect(userPrivateKey).toBeFalsy(); }); @@ -552,10 +551,12 @@ describe("keyService", () => { providerKeysState.nextState(keys.providerKeys!); } - encryptService.decryptToBytes.mockImplementation((encryptedPrivateKey, userKey) => { - // TOOD: Branch between provider and private key? + encryptService.unwrapDecapsulationKey.mockImplementation((encryptedPrivateKey, userKey) => { return Promise.resolve(fakePrivateKeyDecryption(encryptedPrivateKey, userKey)); }); + encryptService.unwrapSymmetricKey.mockImplementation((encryptedPrivateKey, userKey) => { + return Promise.resolve(new SymmetricCryptoKey(new Uint8Array(64))); + }); encryptService.decapsulateKeyUnsigned.mockImplementation((data, privateKey) => { return Promise.resolve(new SymmetricCryptoKey(fakeOrgKeyDecryption(data, privateKey))); @@ -617,6 +618,7 @@ describe("keyService", () => { }); it("returns decryption keys when some of the org keys are providers", async () => { + encryptService.decryptToBytes.mockResolvedValue(new Uint8Array(64)); const org2Id = "org2Id" as OrganizationId; updateKeys({ userKey: makeSymmetricCryptoKey(64), @@ -647,7 +649,7 @@ describe("keyService", () => { const org2Key = decryptionKeys!.orgKeys![org2Id]; expect(org2Key).not.toBeNull(); - expect(org2Key.keyB64).toContain("provider1Key"); + expect(org2Key.toEncoded()).toHaveLength(64); }); it("returns a stream that pays attention to updates of all data", async () => { diff --git a/libs/key-management/src/key.service.ts b/libs/key-management/src/key.service.ts index 01e7b713e1b..849b9db6a50 100644 --- a/libs/key-management/src/key.service.ts +++ b/libs/key-management/src/key.service.ts @@ -738,7 +738,7 @@ export class DefaultKeyService implements KeyServiceAbstraction { const storePin = await this.shouldStoreKey(KeySuffixOptions.Pin, userId); if (storePin) { // Decrypt userKeyEncryptedPin with user key - const pin = await this.encryptService.decryptToUtf8( + const pin = await this.encryptService.decryptString( (await this.pinService.getUserKeyEncryptedPin(userId))!, key, ); @@ -945,10 +945,9 @@ export class DefaultKeyService implements KeyServiceAbstraction { return null; } - return (await this.encryptService.decryptToBytes( + return (await this.encryptService.unwrapDecapsulationKey( new EncString(encryptedPrivateKey), key, - "Content: Encrypted Private Key", )) as UserPrivateKey; } diff --git a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts index 8e2ce8ab6b9..35cef914588 100644 --- a/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts +++ b/libs/key-management/src/user-asymmetric-key-regeneration/services/default-user-asymmetric-key-regeneration.service.spec.ts @@ -58,6 +58,9 @@ function setupUserKeyValidation( cipher.notes = mockEnc("EncryptedString"); cipher.key = mockEnc("EncKey"); cipherService.getAll.mockResolvedValue([cipher]); + encryptService.unwrapSymmetricKey.mockResolvedValue( + new SymmetricCryptoKey(makeStaticByteArray(64)), + ); encryptService.decryptToBytes.mockResolvedValue(makeStaticByteArray(64)); encryptService.decryptString.mockResolvedValue("mockDecryptedString"); (window as any).bitwardenContainerService = new ContainerService(keyService, encryptService); From fcaf5e63c5e8a54dc3c65d0cb16c9c6f26379bfe Mon Sep 17 00:00:00 2001 From: Matt Andreko Date: Mon, 12 May 2025 07:56:50 -0400 Subject: [PATCH 16/35] Duo URL redirect enhancements (#14640) * Provide additional scrutiny on Duo redirect filtering * Address review feedback from Jared * Add documentation to redirectToDuoFrameless method --- apps/web/src/connectors/duo-redirect.spec.ts | 46 ++++++++++++++++++-- apps/web/src/connectors/duo-redirect.ts | 39 ++++++++++++----- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/apps/web/src/connectors/duo-redirect.spec.ts b/apps/web/src/connectors/duo-redirect.spec.ts index c0498861ba0..85953a5dd00 100644 --- a/apps/web/src/connectors/duo-redirect.spec.ts +++ b/apps/web/src/connectors/duo-redirect.spec.ts @@ -10,13 +10,13 @@ describe("duo-redirect", () => { }); it("should redirect to a valid Duo URL", () => { - const validUrl = "https://api-123.duosecurity.com/auth"; + const validUrl = "https://api-123.duosecurity.com/oauth/v1/authorize"; redirectToDuoFrameless(validUrl); expect(window.location.href).toBe(validUrl); }); it("should redirect to a valid Duo Federal URL", () => { - const validUrl = "https://api-123.duofederal.com/auth"; + const validUrl = "https://api-123.duofederal.com/oauth/v1/authorize"; redirectToDuoFrameless(validUrl); expect(window.location.href).toBe(validUrl); }); @@ -27,15 +27,55 @@ describe("duo-redirect", () => { }); it("should throw an error for an malicious URL with valid redirect embedded", () => { - const invalidUrl = "https://malicious-site.com\\@api-123.duosecurity.com/auth"; + const invalidUrl = "https://malicious-site.com\\@api-123.duosecurity.com/oauth/v1/authorize"; expect(() => redirectToDuoFrameless(invalidUrl)).toThrow("Invalid redirect URL"); }); + it("should throw an error for a URL with a malicious subdomain", () => { + const maliciousSubdomainUrl = + "https://api-a86d5bde.duosecurity.com.evil.com/oauth/v1/authorize"; + expect(() => redirectToDuoFrameless(maliciousSubdomainUrl)).toThrow("Invalid redirect URL"); + }); + + it("should throw an error for a URL using HTTP protocol", () => { + const maliciousSubdomainUrl = "http://api-a86d5bde.duosecurity.com/oauth/v1/authorize"; + expect(() => redirectToDuoFrameless(maliciousSubdomainUrl)).toThrow( + "Invalid redirect URL: invalid protocol", + ); + }); + + it("should throw an error for a URL with javascript code", () => { + const maliciousSubdomainUrl = "javascript://https://api-a86d5bde.duosecurity.com%0Aalert(1)"; + expect(() => redirectToDuoFrameless(maliciousSubdomainUrl)).toThrow( + "Invalid redirect URL: invalid protocol", + ); + }); + it("should throw an error for a non-HTTPS URL", () => { const nonHttpsUrl = "http://api-123.duosecurity.com/auth"; expect(() => redirectToDuoFrameless(nonHttpsUrl)).toThrow("Invalid redirect URL"); }); + it("should throw an error for a URL with invalid port specified", () => { + const urlWithPort = "https://api-123.duyosecurity.com:8080/auth"; + expect(() => redirectToDuoFrameless(urlWithPort)).toThrow( + "Invalid redirect URL: port not allowed", + ); + }); + + it("should redirect to a valid Duo Federal URL with valid port", () => { + const validUrl = "https://api-123.duofederal.com:443/oauth/v1/authorize"; + redirectToDuoFrameless(validUrl); + expect(window.location.href).toBe(validUrl); + }); + + it("should throw an error for a URL with an invalid pathname", () => { + const urlWithPort = "https://api-123.duyosecurity.com/../evil/path/here/"; + expect(() => redirectToDuoFrameless(urlWithPort)).toThrow( + "Invalid redirect URL: invalid pathname", + ); + }); + it("should throw an error for a URL with an invalid hostname", () => { const invalidHostnameUrl = "https://api-123.invalid.com"; expect(() => redirectToDuoFrameless(invalidHostnameUrl)).toThrow("Invalid redirect URL"); diff --git a/apps/web/src/connectors/duo-redirect.ts b/apps/web/src/connectors/duo-redirect.ts index d1841247962..5389b31f6af 100644 --- a/apps/web/src/connectors/duo-redirect.ts +++ b/apps/web/src/connectors/duo-redirect.ts @@ -57,29 +57,46 @@ window.addEventListener("load", async () => { * @param redirectUrl the duo auth url */ export function redirectToDuoFrameless(redirectUrl: string) { - // Regex to match a valid duo redirect URL + // Validation for Duo redirect URL to prevent open redirect or XSS vulnerabilities + // Only used for Duo 2FA redirects in the extension /** * This regex checks for the following: - * The string must start with "https://api-" - * Followed by a subdomain that can contain letters, numbers + * The hostname must start with a subdomain that begins with "api-" followed by a + * string that can contain letters or numbers of indeterminate length * Followed by either "duosecurity.com" or "duofederal.com" * This ensures that the redirect does not contain any malicious content * and is a valid Duo URL. * */ - const duoRedirectUrlRegex = /^https:\/\/api-[a-zA-Z0-9]+\.(duosecurity|duofederal)\.com/; - // Check if the redirect URL matches the regex - if (!duoRedirectUrlRegex.test(redirectUrl)) { - throw new Error("Invalid redirect URL"); - } - // At this point we know the URL to be valid, but we need to check for embedded credentials + const duoRedirectUrlRegex = /^api-[a-zA-Z0-9]+\.(duosecurity|duofederal)\.com$/; const validateUrl = new URL(redirectUrl); - // URLs should not contain + // Check that no embedded credentials are present if (validateUrl.username || validateUrl.password) { throw new Error("Invalid redirect URL: embedded credentials not allowed"); } - window.location.href = decodeURIComponent(redirectUrl); + // Check that the protocol is HTTPS + if (validateUrl.protocol !== "https:") { + throw new Error("Invalid redirect URL: invalid protocol"); + } + + // Check that the port is not specified + if (validateUrl.port && validateUrl.port !== "443") { + throw new Error("Invalid redirect URL: port not allowed"); + } + + if (validateUrl.pathname !== "/oauth/v1/authorize") { + throw new Error("Invalid redirect URL: invalid pathname"); + } + + // Check if the redirect hostname matches the regex + // Only check the hostname part of the URL to avoid over-zealous Regex expressions from matching + // and causing an Open Redirect vulnerability. Always use hostname instead of host, because host includes port if specified. + if (!duoRedirectUrlRegex.test(validateUrl.hostname)) { + throw new Error("Invalid redirect URL"); + } + + window.location.href = redirectUrl; } /** From 4d15f2d43cbd79ac29b35c8e8e3244ecb59ad8e4 Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Mon, 12 May 2025 09:00:01 -0400 Subject: [PATCH 17/35] [PM-16057] use Roboto as primary font (#14553) * swap to using roboto variable font --- .../content/components/constants/styles.ts | 6 +++--- .../notification/confirmation/message.ts | 2 +- .../components/notification/header-message.ts | 2 +- .../src/autofill/shared/styles/variables.scss | 2 +- apps/browser/src/popup/images/loading.svg | 2 +- apps/browser/src/popup/scss/variables.scss | 2 +- .../src/app/components/avatar.component.ts | 2 +- apps/desktop/src/images/loading.svg | 2 +- apps/desktop/src/scss/variables.scss | 2 +- .../src/app/billing/services/stripe.service.ts | 2 +- apps/web/src/images/loading-white.svg | 2 +- apps/web/src/images/loading.svg | 2 +- apps/web/src/scss/variables.scss | 2 +- libs/angular/src/scss/webfonts.css | 6 +++--- libs/angular/src/scss/webfonts/dm-sans.woff2 | Bin 88504 -> 0 bytes libs/angular/src/scss/webfonts/roboto.woff2 | Bin 0 -> 209484 bytes libs/components/src/avatar/avatar.component.ts | 2 +- libs/components/src/variables.scss | 2 +- 18 files changed, 20 insertions(+), 20 deletions(-) delete mode 100644 libs/angular/src/scss/webfonts/dm-sans.woff2 create mode 100644 libs/angular/src/scss/webfonts/roboto.woff2 diff --git a/apps/browser/src/autofill/content/components/constants/styles.ts b/apps/browser/src/autofill/content/components/constants/styles.ts index f7c9ffd4d92..08c8671ce14 100644 --- a/apps/browser/src/autofill/content/components/constants/styles.ts +++ b/apps/browser/src/autofill/content/components/constants/styles.ts @@ -144,17 +144,17 @@ export const border = { export const typography = { body1: ` line-height: 24px; - font-family: "DM Sans", sans-serif; + font-family: Roboto, sans-serif; font-size: 16px; `, body2: ` line-height: 20px; - font-family: "DM Sans", sans-serif; + font-family: Roboto, sans-serif; font-size: 14px; `, helperMedium: ` line-height: 16px; - font-family: "DM Sans", sans-serif; + font-family: Roboto, sans-serif; font-size: 12px; `, }; diff --git a/apps/browser/src/autofill/content/components/notification/confirmation/message.ts b/apps/browser/src/autofill/content/components/notification/confirmation/message.ts index 521fdf45291..527119aed15 100644 --- a/apps/browser/src/autofill/content/components/notification/confirmation/message.ts +++ b/apps/browser/src/autofill/content/components/notification/confirmation/message.ts @@ -72,7 +72,7 @@ const baseTextStyles = css` text-align: left; text-overflow: ellipsis; line-height: 24px; - font-family: "DM Sans", sans-serif; + font-family: Roboto, sans-serif; font-size: 16px; `; diff --git a/apps/browser/src/autofill/content/components/notification/header-message.ts b/apps/browser/src/autofill/content/components/notification/header-message.ts index ccfa58b8970..47fe8cd2828 100644 --- a/apps/browser/src/autofill/content/components/notification/header-message.ts +++ b/apps/browser/src/autofill/content/components/notification/header-message.ts @@ -19,7 +19,7 @@ const notificationHeaderMessageStyles = (theme: Theme) => css` line-height: 28px; white-space: nowrap; color: ${themes[theme].text.main}; - font-family: "DM Sans", sans-serif; + font-family: Roboto, sans-serif; font-size: 18px; font-weight: 600; `; diff --git a/apps/browser/src/autofill/shared/styles/variables.scss b/apps/browser/src/autofill/shared/styles/variables.scss index ae6a060798a..1e804ed8fd2 100644 --- a/apps/browser/src/autofill/shared/styles/variables.scss +++ b/apps/browser/src/autofill/shared/styles/variables.scss @@ -1,6 +1,6 @@ $dark-icon-themes: "theme_dark"; -$font-family-sans-serif: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-source-code-pro: "Source Code Pro", monospace; $font-size-base: 14px; diff --git a/apps/browser/src/popup/images/loading.svg b/apps/browser/src/popup/images/loading.svg index 3f2033303db..5f4102a5921 100644 --- a/apps/browser/src/popup/images/loading.svg +++ b/apps/browser/src/popup/images/loading.svg @@ -1,5 +1,5 @@  - Loading... diff --git a/apps/browser/src/popup/scss/variables.scss b/apps/browser/src/popup/scss/variables.scss index b78f06f2f3f..aea69e26436 100644 --- a/apps/browser/src/popup/scss/variables.scss +++ b/apps/browser/src/popup/scss/variables.scss @@ -1,6 +1,6 @@ $dark-icon-themes: "theme_dark"; -$font-family-sans-serif: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; $font-size-base: 16px; $font-size-large: 18px; diff --git a/apps/desktop/src/app/components/avatar.component.ts b/apps/desktop/src/app/components/avatar.component.ts index 87db2e4b6af..d2660763667 100644 --- a/apps/desktop/src/app/components/avatar.component.ts +++ b/apps/desktop/src/app/components/avatar.component.ts @@ -113,7 +113,7 @@ export class AvatarComponent implements OnChanges, OnInit { textTag.setAttribute("fill", Utils.pickTextColorBasedOnBgColor(color, 135, true)); textTag.setAttribute( "font-family", - '"DM Sans","Helvetica Neue",Helvetica,Arial,' + + 'Roboto,"Helvetica Neue",Helvetica,Arial,' + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"', ); textTag.textContent = character; diff --git a/apps/desktop/src/images/loading.svg b/apps/desktop/src/images/loading.svg index 3f2033303db..5f4102a5921 100644 --- a/apps/desktop/src/images/loading.svg +++ b/apps/desktop/src/images/loading.svg @@ -1,5 +1,5 @@  - Loading... diff --git a/apps/desktop/src/scss/variables.scss b/apps/desktop/src/scss/variables.scss index b8978e284e5..b094be63f8c 100644 --- a/apps/desktop/src/scss/variables.scss +++ b/apps/desktop/src/scss/variables.scss @@ -1,6 +1,6 @@ $dark-icon-themes: "theme_dark"; -$font-family-sans-serif: "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-sans-serif: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif; $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; $font-size-base: 14px; $font-size-large: 18px; diff --git a/apps/web/src/app/billing/services/stripe.service.ts b/apps/web/src/app/billing/services/stripe.service.ts index 5c35923c1f4..360187ecd1e 100644 --- a/apps/web/src/app/billing/services/stripe.service.ts +++ b/apps/web/src/app/billing/services/stripe.service.ts @@ -148,7 +148,7 @@ export class StripeService { base: { color: null, fontFamily: - '"DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, ' + + 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif, ' + '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', fontSize: "16px", fontSmoothing: "antialiased", diff --git a/apps/web/src/images/loading-white.svg b/apps/web/src/images/loading-white.svg index 2bebff7daba..ef5970da42e 100644 --- a/apps/web/src/images/loading-white.svg +++ b/apps/web/src/images/loading-white.svg @@ -1,5 +1,5 @@  - Loading... diff --git a/apps/web/src/images/loading.svg b/apps/web/src/images/loading.svg index 3f2033303db..5f4102a5921 100644 --- a/apps/web/src/images/loading.svg +++ b/apps/web/src/images/loading.svg @@ -1,5 +1,5 @@  - Loading... diff --git a/apps/web/src/scss/variables.scss b/apps/web/src/scss/variables.scss index 4b023e12746..66773999c54 100644 --- a/apps/web/src/scss/variables.scss +++ b/apps/web/src/scss/variables.scss @@ -21,7 +21,7 @@ $body-bg: $white; $body-color: #333333; $font-family-sans-serif: - "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; $h1-font-size: 1.7rem; diff --git a/libs/angular/src/scss/webfonts.css b/libs/angular/src/scss/webfonts.css index 04b072e1bf1..cd35271bf80 100644 --- a/libs/angular/src/scss/webfonts.css +++ b/libs/angular/src/scss/webfonts.css @@ -1,8 +1,8 @@ @font-face { - font-family: "DM Sans"; + font-family: Roboto; src: - url("webfonts/dm-sans.woff2") format("woff2 supports variations"), - url("webfonts/dm-sans.woff2") format("woff2-variations"); + url("webfonts/roboto.woff2") format("woff2 supports variations"), + url("webfonts/roboto.woff2") format("woff2-variations"); font-display: swap; font-weight: 100 900; } diff --git a/libs/angular/src/scss/webfonts/dm-sans.woff2 b/libs/angular/src/scss/webfonts/dm-sans.woff2 deleted file mode 100644 index 2375279dbf5a47d05c9b3364961a1f2d768b78cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88504 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�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�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 B`$zx) diff --git a/libs/angular/src/scss/webfonts/roboto.woff2 b/libs/angular/src/scss/webfonts/roboto.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..af8d2343d9c7d72c6fcbf7ffe127d0cc9f3e696c GIT binary patch literal 209484 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
${message || buttonText ? html` - ${itemName} - - ${message || nothing} - ${buttonText - ? html` - handleButtonKeyDown(e, () => handleClick(e))} - aria-label=${buttonAria} - tabindex="0" - role="button" - > - ${buttonText} - - ` - : nothing} - +
+ ${itemName} + + ${message || nothing} + ${buttonText + ? html` + + handleButtonKeyDown(e, () => handleClick(e))} + aria-label=${buttonAria} + tabindex="0" + role="button" + > + ${buttonText} + + ` + : nothing} + +
` : nothing} ${messageDetails @@ -61,12 +64,17 @@ export function NotificationConfirmationMessage({ const containerStyles = css` display: flex; - flex-wrap: wrap; - align-items: center; + flex-direction: column; gap: ${spacing[1]}; width: 100%; `; +const singleLineWrapperStyles = css` + display: inline; + white-space: normal; + word-break: break-word; +`; + const baseTextStyles = css` overflow-x: hidden; text-align: left; @@ -81,6 +89,9 @@ const notificationConfirmationMessageStyles = (theme: Theme) => css` color: ${themes[theme].text.main}; font-weight: 400; + white-space: normal; + word-break: break-word; + display: inline; `; const itemNameStyles = (theme: Theme) => css` @@ -90,6 +101,10 @@ const itemNameStyles = (theme: Theme) => css` font-weight: 400; white-space: nowrap; max-width: 300px; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + vertical-align: bottom; `; const notificationConfirmationButtonTextStyles = (theme: Theme) => css` diff --git a/apps/browser/src/autofill/notification/bar.ts b/apps/browser/src/autofill/notification/bar.ts index 3fd6016eb33..52cbdcd47d3 100644 --- a/apps/browser/src/autofill/notification/bar.ts +++ b/apps/browser/src/autofill/notification/bar.ts @@ -59,9 +59,7 @@ function getI18n() { collection: chrome.i18n.getMessage("collection"), folder: chrome.i18n.getMessage("folder"), loginSaveSuccess: chrome.i18n.getMessage("loginSaveSuccess"), - loginSaveConfirmation: chrome.i18n.getMessage("loginSaveConfirmation"), loginUpdateSuccess: chrome.i18n.getMessage("loginUpdateSuccess"), - loginUpdatedConfirmation: chrome.i18n.getMessage("loginUpdatedConfirmation"), loginUpdateTaskSuccess: chrome.i18n.getMessage("loginUpdateTaskSuccess"), loginUpdateTaskSuccessAdditional: chrome.i18n.getMessage("loginUpdateTaskSuccessAdditional"), nextSecurityTaskAction: chrome.i18n.getMessage("nextSecurityTaskAction"), @@ -74,6 +72,10 @@ function getI18n() { notificationUpdate: chrome.i18n.getMessage("notificationChangeSave"), notificationEdit: chrome.i18n.getMessage("edit"), notificationEditTooltip: chrome.i18n.getMessage("notificationEditTooltip"), + notificationLoginSaveConfirmation: chrome.i18n.getMessage("notificationLoginSaveConfirmation"), + notificationLoginUpdatedConfirmation: chrome.i18n.getMessage( + "notificationLoginUpdatedConfirmation", + ), notificationUnlock: chrome.i18n.getMessage("notificationUnlock"), notificationUnlockDesc: chrome.i18n.getMessage("notificationUnlockDesc"), notificationViewAria: chrome.i18n.getMessage("notificationViewAria"), From 02cbc37ac56eccefacfb1d35a6a4c7e8f59c0cea Mon Sep 17 00:00:00 2001 From: Daniel Riera Date: Mon, 12 May 2025 17:23:06 -0400 Subject: [PATCH 34/35] PM-20397 Misc notification bar UI tweaks (#14558) * PM-20637 * turncate save button --- .../content/components/notification/container.ts | 2 +- .../content/components/notification/footer.ts | 15 +++++++++------ .../content/components/rows/button-row.ts | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/browser/src/autofill/content/components/notification/container.ts b/apps/browser/src/autofill/content/components/notification/container.ts index c7c7ae16cde..1a78854f5dc 100644 --- a/apps/browser/src/autofill/content/components/notification/container.ts +++ b/apps/browser/src/autofill/content/components/notification/container.ts @@ -94,7 +94,7 @@ const notificationContainerStyles = (theme: Theme) => css` } [class*="${notificationBodyClassPrefix}-"] { - margin: ${spacing["3"]} 0 ${spacing["1.5"]} ${spacing["3"]}; + margin: ${spacing["3"]} 0 0 ${spacing["3"]}; padding-right: ${spacing["3"]}; } `; diff --git a/apps/browser/src/autofill/content/components/notification/footer.ts b/apps/browser/src/autofill/content/components/notification/footer.ts index 73fe9084595..03d0d475e85 100644 --- a/apps/browser/src/autofill/content/components/notification/footer.ts +++ b/apps/browser/src/autofill/content/components/notification/footer.ts @@ -8,7 +8,7 @@ import { NotificationTypes, } from "../../../notification/abstractions/notification-bar"; import { OrgView, FolderView, I18n, CollectionView } from "../common-types"; -import { spacing, themes } from "../constants/styles"; +import { spacing } from "../constants/styles"; import { NotificationButtonRow } from "./button-row"; @@ -37,7 +37,7 @@ export function NotificationFooter({ const primaryButtonText = i18n.saveAction; return html` -
+
${!isChangeNotification ? NotificationButtonRow({ collections, @@ -56,13 +56,16 @@ export function NotificationFooter({ `; } -const notificationFooterStyles = ({ theme }: { theme: Theme }) => css` +const notificationFooterStyles = ({ + isChangeNotification, +}: { + isChangeNotification: boolean; +}) => css` display: flex; - background-color: ${themes[theme].background.alt}; - padding: 0 ${spacing[3]} ${spacing[3]} ${spacing[3]}; + padding: ${spacing[2]} ${spacing[4]} ${isChangeNotification ? spacing[1] : spacing[4]} + ${spacing[4]}; :last-child { border-radius: 0 0 ${spacing["4"]} ${spacing["4"]}; - padding-bottom: ${spacing[4]}; } `; diff --git a/apps/browser/src/autofill/content/components/rows/button-row.ts b/apps/browser/src/autofill/content/components/rows/button-row.ts index 3527d050b81..7e81d846cb7 100644 --- a/apps/browser/src/autofill/content/components/rows/button-row.ts +++ b/apps/browser/src/autofill/content/components/rows/button-row.ts @@ -62,7 +62,7 @@ const buttonRowStyles = css` > button { max-width: min-content; - flex: 1 1 50%; + flex: 1 1 25%; } > div { From 7a51161d50da1b1b4e2428de943a8a83991bde82 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 13 May 2025 12:43:26 +0200 Subject: [PATCH 35/35] Move selectable avatar to auth (#14704) --- .../settings/account}/selectable-avatar.component.ts | 0 apps/web/src/app/shared/loose-components.module.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename apps/web/src/app/{components => auth/settings/account}/selectable-avatar.component.ts (100%) diff --git a/apps/web/src/app/components/selectable-avatar.component.ts b/apps/web/src/app/auth/settings/account/selectable-avatar.component.ts similarity index 100% rename from apps/web/src/app/components/selectable-avatar.component.ts rename to apps/web/src/app/auth/settings/account/selectable-avatar.component.ts diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts index 30d1dd1af75..ab6c6cc5d72 100644 --- a/apps/web/src/app/shared/loose-components.module.ts +++ b/apps/web/src/app/shared/loose-components.module.ts @@ -22,6 +22,7 @@ import { DangerZoneComponent } from "../auth/settings/account/danger-zone.compon import { DeauthorizeSessionsComponent } from "../auth/settings/account/deauthorize-sessions.component"; import { DeleteAccountDialogComponent } from "../auth/settings/account/delete-account-dialog.component"; import { ProfileComponent } from "../auth/settings/account/profile.component"; +import { SelectableAvatarComponent } from "../auth/settings/account/selectable-avatar.component"; import { EmergencyAccessConfirmComponent } from "../auth/settings/emergency-access/confirm/emergency-access-confirm.component"; import { EmergencyAccessAddEditComponent } from "../auth/settings/emergency-access/emergency-access-add-edit.component"; import { EmergencyAccessComponent } from "../auth/settings/emergency-access/emergency-access.component"; @@ -39,7 +40,6 @@ import { VerifyRecoverDeleteComponent } from "../auth/verify-recover-delete.comp import { SponsoredFamiliesComponent } from "../billing/settings/sponsored-families.component"; import { SponsoringOrgRowComponent } from "../billing/settings/sponsoring-org-row.component"; import { DynamicAvatarComponent } from "../components/dynamic-avatar.component"; -import { SelectableAvatarComponent } from "../components/selectable-avatar.component"; import { ExposedPasswordsReportComponent as OrgExposedPasswordsReportComponent } from "../dirt/reports/pages/organizations/exposed-passwords-report.component"; import { InactiveTwoFactorReportComponent as OrgInactiveTwoFactorReportComponent } from "../dirt/reports/pages/organizations/inactive-two-factor-report.component"; import { ReusedPasswordsReportComponent as OrgReusedPasswordsReportComponent } from "../dirt/reports/pages/organizations/reused-passwords-report.component";

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Ð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 Z%W3>CI$@P~5SgeBd{mD4Gdn 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%0DZzBc#{kuHQ3xWI`Ear!Re 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 E0Ln!2jQ{`u literal 0 HcmV?d00001 diff --git a/libs/components/src/avatar/avatar.component.ts b/libs/components/src/avatar/avatar.component.ts index 0e3dbd6f1b9..554f55636fc 100644 --- a/libs/components/src/avatar/avatar.component.ts +++ b/libs/components/src/avatar/avatar.component.ts @@ -123,7 +123,7 @@ export class AvatarComponent implements OnChanges { textTag.setAttribute("fill", Utils.pickTextColorBasedOnBgColor(color, 135, true)); textTag.setAttribute( "font-family", - '"DM Sans","Helvetica Neue",Helvetica,Arial,' + + 'Roboto,"Helvetica Neue",Helvetica,Arial,' + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"', ); // Warning do not use innerHTML here, characters are user provided diff --git a/libs/components/src/variables.scss b/libs/components/src/variables.scss index bc9cded4981..e3651f9c37d 100644 --- a/libs/components/src/variables.scss +++ b/libs/components/src/variables.scss @@ -21,7 +21,7 @@ $body-bg: $white; $body-color: #333333; $font-family-sans-serif: - "DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; $h1-font-size: 1.7rem; From 87b875c48b2a9c5d463397a4bdefe42412399a42 Mon Sep 17 00:00:00 2001 From: Patrick-Pimentel-Bitwarden Date: Mon, 12 May 2025 09:29:11 -0400 Subject: [PATCH 18/35] docs(update-auth-approving-clients): [PM-17111] Add Browser to List of Approving Clients - Updated comments. (#14707) --- .../services/platform-utils/browser-platform-utils.service.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/browser/src/platform/services/platform-utils/browser-platform-utils.service.ts b/apps/browser/src/platform/services/platform-utils/browser-platform-utils.service.ts index c9200ecc1a4..22708d8e425 100644 --- a/apps/browser/src/platform/services/platform-utils/browser-platform-utils.service.ts +++ b/apps/browser/src/platform/services/platform-utils/browser-platform-utils.service.ts @@ -26,6 +26,10 @@ export abstract class BrowserPlatformUtilsService implements PlatformUtilsServic return this.deviceCache; } + // ORDERING MATTERS HERE + // Ordered from most specific to least specific. We try to discern the greatest detail + // for the type of extension the user is on by checking specific cases first and as we go down + // the list we hope to catch all by the most generic clients they could be on. if (BrowserPlatformUtilsService.isFirefox()) { this.deviceCache = DeviceType.FirefoxExtension; } else if (BrowserPlatformUtilsService.isOpera(globalContext)) { From aca8ab8e40f18108ddbf3a1808c545bc1571b1f7 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 12 May 2025 15:31:03 +0200 Subject: [PATCH 19/35] [PM-21001] Move autofill code to new encrypt service interface (#14548) * Move autofill code to new encrypt service interface * Fix test runner --- .../src/native-message.service.ts | 8 ++------ .../src/services/duckduckgo-message-handler.service.ts | 5 ++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/apps/desktop/native-messaging-test-runner/src/native-message.service.ts b/apps/desktop/native-messaging-test-runner/src/native-message.service.ts index c01d581afe8..c2356f93e28 100644 --- a/apps/desktop/native-messaging-test-runner/src/native-message.service.ts +++ b/apps/desktop/native-messaging-test-runner/src/native-message.service.ts @@ -220,7 +220,7 @@ export default class NativeMessageService { const sharedKey = await this.getSharedKeyForKey(key); - return this.encryptService.encrypt(commandDataString, sharedKey); + return this.encryptService.encryptString(commandDataString, sharedKey); } private async decryptResponsePayload( @@ -228,11 +228,7 @@ export default class NativeMessageService { key: string, ): Promise { const sharedKey = await this.getSharedKeyForKey(key); - const decrypted = await this.encryptService.decryptToUtf8( - payload, - sharedKey, - "native-messaging-session", - ); + const decrypted = await this.encryptService.decryptString(payload, sharedKey); return JSON.parse(decrypted); } diff --git a/apps/desktop/src/services/duckduckgo-message-handler.service.ts b/apps/desktop/src/services/duckduckgo-message-handler.service.ts index e82444be993..6fb91231be1 100644 --- a/apps/desktop/src/services/duckduckgo-message-handler.service.ts +++ b/apps/desktop/src/services/duckduckgo-message-handler.service.ts @@ -168,7 +168,7 @@ export class DuckDuckGoMessageHandlerService { payload: DecryptedCommandData, key: SymmetricCryptoKey, ): Promise { - return await this.encryptService.encrypt(JSON.stringify(payload), key); + return await this.encryptService.encryptString(JSON.stringify(payload), key); } private async decryptPayload(message: EncryptedMessage): Promise { @@ -188,10 +188,9 @@ export class DuckDuckGoMessageHandlerService { } try { - let decryptedResult = await this.encryptService.decryptToUtf8( + let decryptedResult = await this.encryptService.decryptString( message.encryptedCommand as EncString, this.duckduckgoSharedSecret, - "ddg-shared-key", ); decryptedResult = this.trimNullCharsFromMessage(decryptedResult); From 57ed1e7285f8a263429140a19ae0e0ff32258dc6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 10:09:40 -0400 Subject: [PATCH 20/35] [deps] Platform: Update @types/node to v22.15.3 (#14723) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../native-messaging-test-runner/package-lock.json | 8 ++++---- apps/desktop/native-messaging-test-runner/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json index d506e109e94..8b39fd9805e 100644 --- a/apps/desktop/native-messaging-test-runner/package-lock.json +++ b/apps/desktop/native-messaging-test-runner/package-lock.json @@ -17,7 +17,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@types/node": "22.14.1", + "@types/node": "22.15.3", "typescript": "5.4.2" } }, @@ -101,9 +101,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" diff --git a/apps/desktop/native-messaging-test-runner/package.json b/apps/desktop/native-messaging-test-runner/package.json index f67ab259d3b..ea6b1b3e7a8 100644 --- a/apps/desktop/native-messaging-test-runner/package.json +++ b/apps/desktop/native-messaging-test-runner/package.json @@ -22,7 +22,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@types/node": "22.14.1", + "@types/node": "22.15.3", "typescript": "5.4.2" }, "_moduleAliases": { diff --git a/package-lock.json b/package-lock.json index 1e7e0741cd8..a15275a695e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -110,7 +110,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.14.1", + "@types/node": "22.15.3", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/papaparse": "5.3.15", @@ -11656,9 +11656,9 @@ } }, "node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 81f1c92d5a5..904ae121cc9 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.14.1", + "@types/node": "22.15.3", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/papaparse": "5.3.15", From 89b9ba21cabbd4ddaf71bba9f267cd646bd4fc9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 07:15:06 -0700 Subject: [PATCH 21/35] [deps] Platform: Update Rust crate arboard to v3.5.0 (#14484) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- apps/desktop/desktop_native/Cargo.lock | 153 ++++++++----------------- apps/desktop/desktop_native/Cargo.toml | 2 +- 2 files changed, 46 insertions(+), 109 deletions(-) diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock index cfd29303510..1b442fbbb8a 100644 --- a/apps/desktop/desktop_native/Cargo.lock +++ b/apps/desktop/desktop_native/Cargo.lock @@ -120,9 +120,9 @@ checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arboard" -version = "3.4.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" +checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70" dependencies = [ "clipboard-win", "log", @@ -130,6 +130,7 @@ dependencies = [ "objc2-app-kit", "objc2-foundation", "parking_lot", + "percent-encoding", "wl-clipboard-rs", "x11rb", ] @@ -465,15 +466,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - [[package]] name = "blocking" version = "1.6.1" @@ -565,12 +557,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cfg_aliases" version = "0.2.1" @@ -867,17 +853,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive-new" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "desktop_core" version = "0.0.0" @@ -1007,6 +982,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1409,7 +1394,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bdbbd5bc8c5749697ccaa352fa45aff8730cf21c68029c0eef1ffed7c3d6ba2" dependencies = [ "cfg-if", - "nix 0.29.0", + "nix", "widestring", "windows 0.57.0", ] @@ -1839,18 +1824,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases 0.1.1", - "libc", -] - [[package]] name = "nix" version = "0.29.0" @@ -1859,7 +1832,7 @@ checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags", "cfg-if", - "cfg_aliases 0.2.1", + "cfg_aliases", "libc", "memoffset", ] @@ -1990,47 +1963,24 @@ dependencies = [ "libc", ] -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - [[package]] name = "objc2" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ - "objc-sys", "objc2-encode", ] [[package]] name = "objc2-app-kit" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags", - "block2", - "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags", - "block2", "objc2", + "objc2-core-graphics", "objc2-foundation", ] @@ -2041,18 +1991,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags", + "dispatch2", + "objc2", ] [[package]] -name = "objc2-core-image" -version = "0.2.2" +name = "objc2-core-graphics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ - "block2", + "bitflags", + "dispatch2", "objc2", - "objc2-foundation", - "objc2-metal", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -2063,14 +2016,13 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags", - "block2", - "libc", "objc2", + "objc2-core-foundation", ] [[package]] @@ -2084,28 +2036,14 @@ dependencies = [ ] [[package]] -name = "objc2-metal" -version = "0.2.2" +name = "objc2-io-surface" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ "bitflags", - "block2", "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", + "objc2-core-foundation", ] [[package]] @@ -3487,9 +3425,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" dependencies = [ "bitflags", "wayland-backend", @@ -3499,9 +3437,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2" dependencies = [ "bitflags", "wayland-backend", @@ -3982,15 +3920,14 @@ dependencies = [ [[package]] name = "wl-clipboard-rs" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" +checksum = "2a083daad7e8a4b8805ad73947ccadabe62afe37ce0e9787a56ff373d34762c7" dependencies = [ - "derive-new", "libc", "log", - "nix 0.28.0", "os_pipe", + "rustix", "tempfile", "thiserror 1.0.69", "tree_magic_mini", @@ -4085,7 +4022,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.29.0", + "nix", "ordered-stream", "rand 0.8.5", "serde", @@ -4115,7 +4052,7 @@ dependencies = [ "futures-core", "futures-lite", "hex", - "nix 0.29.0", + "nix", "ordered-stream", "serde", "serde_repr", diff --git a/apps/desktop/desktop_native/Cargo.toml b/apps/desktop/desktop_native/Cargo.toml index f613744f42a..fafaf02eca3 100644 --- a/apps/desktop/desktop_native/Cargo.toml +++ b/apps/desktop/desktop_native/Cargo.toml @@ -11,7 +11,7 @@ publish = false [workspace.dependencies] aes = "=0.8.4" anyhow = "=1.0.94" -arboard = { version = "=3.4.1", default-features = false } +arboard = { version = "=3.5.0", default-features = false } argon2 = "=0.5.3" base64 = "=0.22.1" bindgen = "0.71.1" From 07725853a287c679964a608f3b23695c54030575 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 12 May 2025 17:00:53 +0200 Subject: [PATCH 22/35] Add tests for masterpasswordservice (#14728) * Add tests for masterpasswordservice * Fix tests --- .../services/master-password.service.spec.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/libs/common/src/key-management/master-password/services/master-password.service.spec.ts b/libs/common/src/key-management/master-password/services/master-password.service.spec.ts index 93439ac8caa..b55e770f865 100644 --- a/libs/common/src/key-management/master-password/services/master-password.service.spec.ts +++ b/libs/common/src/key-management/master-password/services/master-password.service.spec.ts @@ -2,12 +2,16 @@ import { mock, MockProxy } from "jest-mock-extended"; import { of } from "rxjs"; import * as rxjs from "rxjs"; +import { makeSymmetricCryptoKey } from "../../../../spec"; import { ForceSetPasswordReason } from "../../../auth/models/domain/force-set-password-reason"; import { KeyGenerationService } from "../../../platform/abstractions/key-generation.service"; import { LogService } from "../../../platform/abstractions/log.service"; import { StateService } from "../../../platform/abstractions/state.service"; +import { EncString } from "../../../platform/models/domain/enc-string"; +import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; import { StateProvider } from "../../../platform/state"; import { UserId } from "../../../types/guid"; +import { MasterKey } from "../../../types/key"; import { EncryptService } from "../../crypto/abstractions/encrypt.service"; import { MasterPasswordService } from "./master-password.service"; @@ -27,6 +31,14 @@ describe("MasterPasswordService", () => { update: jest.fn().mockResolvedValue(null), }; + const testUserKey: SymmetricCryptoKey = makeSymmetricCryptoKey(64, 1); + const testMasterKey: MasterKey = makeSymmetricCryptoKey(32, 2); + const testStretchedMasterKey: SymmetricCryptoKey = makeSymmetricCryptoKey(64, 3); + const testMasterKeyEncryptedKey = + "0.gbauOANURUHqvhLTDnva1A==|nSW+fPumiuTaDB/s12+JO88uemV6rhwRSR+YR1ZzGr5j6Ei3/h+XEli2Unpz652NlZ9NTuRpHxeOqkYYJtp7J+lPMoclgteXuAzUu9kqlRc="; + const testStretchedMasterKeyEncryptedKey = + "2.gbauOANURUHqvhLTDnva1A==|nSW+fPumiuTaDB/s12+JO88uemV6rhwRSR+YR1ZzGr5j6Ei3/h+XEli2Unpz652NlZ9NTuRpHxeOqkYYJtp7J+lPMoclgteXuAzUu9kqlRc=|DeUFkhIwgkGdZA08bDnDqMMNmZk21D+H5g8IostPKAY="; + beforeEach(() => { stateProvider = mock(); stateService = mock(); @@ -45,6 +57,9 @@ describe("MasterPasswordService", () => { encryptService, logService, ); + + encryptService.unwrapSymmetricKey.mockResolvedValue(makeSymmetricCryptoKey(64, 1)); + keyGenerationService.stretchKey.mockResolvedValue(makeSymmetricCryptoKey(64, 3)); }); describe("setForceSetPasswordReason", () => { @@ -101,4 +116,41 @@ describe("MasterPasswordService", () => { expect(mockUserState.update).toHaveBeenCalled(); }); }); + describe("decryptUserKeyWithMasterKey", () => { + it("decrypts a userkey wrapped in AES256-CBC", async () => { + encryptService.unwrapSymmetricKey.mockResolvedValue(testUserKey); + await sut.decryptUserKeyWithMasterKey( + testMasterKey, + userId, + new EncString(testMasterKeyEncryptedKey), + ); + expect(encryptService.unwrapSymmetricKey).toHaveBeenCalledWith( + new EncString(testMasterKeyEncryptedKey), + testMasterKey, + ); + }); + it("decrypts a userkey wrapped in AES256-CBC-HMAC", async () => { + encryptService.unwrapSymmetricKey.mockResolvedValue(testUserKey); + keyGenerationService.stretchKey.mockResolvedValue(testStretchedMasterKey); + await sut.decryptUserKeyWithMasterKey( + testMasterKey, + userId, + new EncString(testStretchedMasterKeyEncryptedKey), + ); + expect(encryptService.unwrapSymmetricKey).toHaveBeenCalledWith( + new EncString(testStretchedMasterKeyEncryptedKey), + testStretchedMasterKey, + ); + expect(keyGenerationService.stretchKey).toHaveBeenCalledWith(testMasterKey); + }); + it("returns null if failed to decrypt", async () => { + encryptService.unwrapSymmetricKey.mockResolvedValue(null); + const result = await sut.decryptUserKeyWithMasterKey( + testMasterKey, + userId, + new EncString(testStretchedMasterKeyEncryptedKey), + ); + expect(result).toBeNull(); + }); + }); }); From 2487e9b98deb32b10a43bd93cc839d4556223ad4 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Mon, 12 May 2025 11:13:49 -0400 Subject: [PATCH 23/35] [PM-20637] Trigger password reprompt when updating a reprompt cipher via notification (#14575) * reprompt user on cipher update when enabled Co-authored-by: Daniel Riera * update tests * add test --------- Co-authored-by: Daniel Riera --- .../notification.background.spec.ts | 57 ++++++++++++++++++- .../background/notification.background.ts | 42 ++++++++++++-- .../overlay-notifications-content.service.ts | 1 + .../overlay-notifications-content.service.ts | 6 +- .../services/abstractions/autofill.service.ts | 6 +- .../src/autofill/services/autofill.service.ts | 9 ++- .../vault-v2/view-v2/view-v2.component.ts | 27 +++++++-- libs/common/src/autofill/constants/index.ts | 3 +- 8 files changed, 134 insertions(+), 17 deletions(-) diff --git a/apps/browser/src/autofill/background/notification.background.spec.ts b/apps/browser/src/autofill/background/notification.background.spec.ts index 63ae1193737..009efd7ff36 100644 --- a/apps/browser/src/autofill/background/notification.background.spec.ts +++ b/apps/browser/src/autofill/background/notification.background.spec.ts @@ -17,6 +17,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag import { SelfHostedEnvironment } from "@bitwarden/common/platform/services/default-environment.service"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; import { UserId } from "@bitwarden/common/types/guid"; +import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { CipherService } from "@bitwarden/common/vault/services/cipher.service"; @@ -828,6 +829,7 @@ describe("NotificationBackground", () => { id: "testId", name: "testItemName", login: { username: "testUser" }, + reprompt: CipherRepromptType.None, }); getDecryptedCipherByIdSpy.mockResolvedValueOnce(cipherView); @@ -842,6 +844,7 @@ describe("NotificationBackground", () => { message.edit, sender.tab, "testId", + false, ); expect(updateWithServerSpy).toHaveBeenCalled(); expect(tabSendMessageDataSpy).toHaveBeenCalledWith( @@ -855,6 +858,55 @@ describe("NotificationBackground", () => { ); }); + it("prompts the user for master password entry if the notification message type is for ChangePassword and the cipher reprompt is enabled", async () => { + const tab = createChromeTabMock({ id: 1, url: "https://example.com" }); + const sender = mock({ tab }); + const message: NotificationBackgroundExtensionMessage = { + command: "bgSaveCipher", + edit: false, + folder: "folder-id", + }; + const queueMessage = mock({ + type: NotificationQueueMessageType.ChangePassword, + tab, + domain: "example.com", + newPassword: "newPassword", + }); + notificationBackground["notificationQueue"] = [queueMessage]; + const cipherView = mock({ + id: "testId", + name: "testItemName", + login: { username: "testUser" }, + reprompt: CipherRepromptType.Password, + }); + getDecryptedCipherByIdSpy.mockResolvedValueOnce(cipherView); + + sendMockExtensionMessage(message, sender); + await flushPromises(); + + expect(editItemSpy).not.toHaveBeenCalled(); + expect(autofillService.isPasswordRepromptRequired).toHaveBeenCalled(); + expect(createWithServerSpy).not.toHaveBeenCalled(); + expect(updatePasswordSpy).toHaveBeenCalledWith( + cipherView, + queueMessage.newPassword, + message.edit, + sender.tab, + "testId", + false, + ); + expect(updateWithServerSpy).not.toHaveBeenCalled(); + expect(tabSendMessageDataSpy).not.toHaveBeenCalledWith( + sender.tab, + "saveCipherAttemptCompleted", + { + itemName: "testItemName", + cipherId: cipherView.id, + task: undefined, + }, + ); + }); + it("completes password update notification with a security task notice if any are present for the cipher, and dismisses tasks for the updated cipher", async () => { const mockCipherId = "testId"; const mockOrgId = "testOrgId"; @@ -905,6 +957,7 @@ describe("NotificationBackground", () => { id: mockCipherId, organizationId: mockOrgId, name: "Test Item", + reprompt: CipherRepromptType.None, }); getDecryptedCipherByIdSpy.mockResolvedValueOnce(cipherView); @@ -919,6 +972,7 @@ describe("NotificationBackground", () => { message.edit, sender.tab, mockCipherId, + false, ); expect(updateWithServerSpy).toHaveBeenCalled(); expect(tabSendMessageDataSpy).toHaveBeenCalledWith( @@ -1000,6 +1054,7 @@ describe("NotificationBackground", () => { message.edit, sender.tab, "testId", + false, ); expect(editItemSpy).toHaveBeenCalled(); expect(updateWithServerSpy).not.toHaveBeenCalled(); @@ -1170,7 +1225,7 @@ describe("NotificationBackground", () => { newPassword: "newPassword", }); notificationBackground["notificationQueue"] = [queueMessage]; - const cipherView = mock(); + const cipherView = mock({ reprompt: CipherRepromptType.None }); getDecryptedCipherByIdSpy.mockResolvedValueOnce(cipherView); const errorMessage = "fetch error"; updateWithServerSpy.mockImplementation(() => { diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts index 5dd15274677..52920ec67a8 100644 --- a/apps/browser/src/autofill/background/notification.background.ts +++ b/apps/browser/src/autofill/background/notification.background.ts @@ -14,6 +14,7 @@ import { ExtensionCommand, ExtensionCommandType, NOTIFICATION_BAR_LIFESPAN_MS, + UPDATE_PASSWORD, } from "@bitwarden/common/autofill/constants"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { UserNotificationSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/user-notification-settings.service"; @@ -104,6 +105,8 @@ export default class NotificationBackground { this.removeTabFromNotificationQueue(sender.tab), bgReopenUnlockPopout: ({ sender }) => this.openUnlockPopout(sender.tab), bgSaveCipher: ({ message, sender }) => this.handleSaveCipherMessage(message, sender), + bgHandleReprompt: ({ message, sender }: any) => + this.handleCipherUpdateRepromptResponse(message), bgUnlockPopoutOpened: ({ message, sender }) => this.unlockVault(message, sender.tab), checkNotificationQueue: ({ sender }) => this.checkNotificationQueue(sender.tab), collectPageDetailsResponse: ({ message }) => @@ -631,6 +634,17 @@ export default class NotificationBackground { await this.saveOrUpdateCredentials(sender.tab, message.edit, message.folder); } + async handleCipherUpdateRepromptResponse(message: NotificationBackgroundExtensionMessage) { + if (message.success) { + await this.saveOrUpdateCredentials(message.tab, false, undefined, true); + } else { + await BrowserApi.tabSendMessageData(message.tab, "saveCipherAttemptCompleted", { + error: "Password reprompt failed", + }); + return; + } + } + /** * Saves or updates credentials based on the message within the * notification queue that is associated with the specified tab. @@ -639,7 +653,12 @@ export default class NotificationBackground { * @param edit - Identifies if the credentials should be edited or simply added * @param folderId - The folder to add the cipher to */ - private async saveOrUpdateCredentials(tab: chrome.tabs.Tab, edit: boolean, folderId?: string) { + private async saveOrUpdateCredentials( + tab: chrome.tabs.Tab, + edit: boolean, + folderId?: string, + skipReprompt: boolean = false, + ) { for (let i = this.notificationQueue.length - 1; i >= 0; i--) { const queueMessage = this.notificationQueue[i]; if ( @@ -654,18 +673,26 @@ export default class NotificationBackground { continue; } - this.notificationQueue.splice(i, 1); - const activeUserId = await firstValueFrom( this.accountService.activeAccount$.pipe(getOptionalUserId), ); if (queueMessage.type === NotificationQueueMessageType.ChangePassword) { const cipherView = await this.getDecryptedCipherById(queueMessage.cipherId, activeUserId); - await this.updatePassword(cipherView, queueMessage.newPassword, edit, tab, activeUserId); + + await this.updatePassword( + cipherView, + queueMessage.newPassword, + edit, + tab, + activeUserId, + skipReprompt, + ); return; } + this.notificationQueue.splice(i, 1); + // If the vault was locked, check if a cipher needs updating instead of creating a new one if (queueMessage.wasVaultLocked) { const allCiphers = await this.cipherService.getAllDecryptedForUrl( @@ -725,6 +752,7 @@ export default class NotificationBackground { edit: boolean, tab: chrome.tabs.Tab, userId: UserId, + skipReprompt: boolean = false, ) { cipherView.login.password = newPassword; @@ -758,6 +786,12 @@ export default class NotificationBackground { } : undefined; + if (cipherView.reprompt && !skipReprompt) { + await this.autofillService.isPasswordRepromptRequired(cipherView, tab, UPDATE_PASSWORD); + + return; + } + await this.cipherService.updateWithServer(cipher); await BrowserApi.tabSendMessageData(tab, "saveCipherAttemptCompleted", { diff --git a/apps/browser/src/autofill/overlay/notifications/abstractions/overlay-notifications-content.service.ts b/apps/browser/src/autofill/overlay/notifications/abstractions/overlay-notifications-content.service.ts index 82c03cacadf..42d7666e8a7 100644 --- a/apps/browser/src/autofill/overlay/notifications/abstractions/overlay-notifications-content.service.ts +++ b/apps/browser/src/autofill/overlay/notifications/abstractions/overlay-notifications-content.service.ts @@ -15,6 +15,7 @@ export type NotificationsExtensionMessage = { typeData?: NotificationTypeData; height?: number; error?: string; + closedByUser?: boolean; fadeOutNotification?: boolean; }; }; diff --git a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts index 519521feaa9..c21aaa37dd4 100644 --- a/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts +++ b/apps/browser/src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts @@ -106,13 +106,15 @@ export class OverlayNotificationsContentService * @param message - The message containing the data for closing the notification bar. */ private handleCloseNotificationBarMessage(message: NotificationsExtensionMessage) { + const closedByUser = + typeof message.data?.closedByUser === "boolean" ? message.data.closedByUser : true; if (message.data?.fadeOutNotification) { setElementStyles(this.notificationBarIframeElement, { opacity: "0" }, true); - globalThis.setTimeout(() => this.closeNotificationBar(true), 150); + globalThis.setTimeout(() => this.closeNotificationBar(closedByUser), 150); return; } - this.closeNotificationBar(true); + this.closeNotificationBar(closedByUser); } /** diff --git a/apps/browser/src/autofill/services/abstractions/autofill.service.ts b/apps/browser/src/autofill/services/abstractions/autofill.service.ts index 5b1b4b3b8bb..daafd871789 100644 --- a/apps/browser/src/autofill/services/abstractions/autofill.service.ts +++ b/apps/browser/src/autofill/services/abstractions/autofill.service.ts @@ -87,5 +87,9 @@ export abstract class AutofillService { cipherType?: CipherType, ) => Promise; setAutoFillOnPageLoadOrgPolicy: () => Promise; - isPasswordRepromptRequired: (cipher: CipherView, tab: chrome.tabs.Tab) => Promise; + isPasswordRepromptRequired: ( + cipher: CipherView, + tab: chrome.tabs.Tab, + action?: string, + ) => Promise; } diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index da46ceb0864..525010bacc1 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -593,15 +593,20 @@ export default class AutofillService implements AutofillServiceInterface { * * @param cipher - The cipher to autofill * @param tab - The tab to autofill + * @param action - override for default action once reprompt is completed successfully */ - async isPasswordRepromptRequired(cipher: CipherView, tab: chrome.tabs.Tab): Promise { + async isPasswordRepromptRequired( + cipher: CipherView, + tab: chrome.tabs.Tab, + action?: string, + ): Promise { const userHasMasterPasswordAndKeyHash = await this.userVerificationService.hasMasterPasswordAndMasterKeyHash(); if (cipher.reprompt === CipherRepromptType.Password && userHasMasterPasswordAndKeyHash) { if (!this.isDebouncingPasswordRepromptPopout()) { await this.openVaultItemPasswordRepromptPopout(tab, { cipherId: cipher.id, - action: "autofill", + action: action ?? "autofill", }); } diff --git a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.ts b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.ts index 56db47619b0..a834314560b 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.ts @@ -19,6 +19,7 @@ import { COPY_USERNAME_ID, COPY_VERIFICATION_CODE_ID, SHOW_AUTOFILL_BUTTON, + UPDATE_PASSWORD, } from "@bitwarden/common/autofill/constants"; import { EventType } from "@bitwarden/common/enums"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -49,6 +50,7 @@ import { PasswordRepromptService, } from "@bitwarden/vault"; +import { sendExtensionMessage } from "../../../../../autofill/utils/index"; import { BrowserApi } from "../../../../../platform/browser/browser-api"; import BrowserPopupUtils from "../../../../../platform/popup/browser-popup-utils"; import { PopOutComponent } from "../../../../../platform/popup/components/pop-out.component"; @@ -72,7 +74,8 @@ type LoadAction = | typeof SHOW_AUTOFILL_BUTTON | typeof COPY_USERNAME_ID | typeof COPY_PASSWORD_ID - | typeof COPY_VERIFICATION_CODE_ID; + | typeof COPY_VERIFICATION_CODE_ID + | typeof UPDATE_PASSWORD; @Component({ selector: "app-view-v2", @@ -294,7 +297,7 @@ export class ViewV2Component { // Both vaultPopupAutofillService and copyCipherFieldService will perform password re-prompting internally. switch (loadAction) { - case "show-autofill-button": + case SHOW_AUTOFILL_BUTTON: // This action simply shows the cipher view, no need to do anything. if ( this.cipher.reprompt !== CipherRepromptType.None && @@ -303,30 +306,42 @@ export class ViewV2Component { await closeViewVaultItemPopout(`${VaultPopoutType.viewVaultItem}_${this.cipher.id}`); } return; - case "autofill": + case AUTOFILL_ID: actionSuccess = await this.vaultPopupAutofillService.doAutofill(this.cipher, false); break; - case "copy-username": + case COPY_USERNAME_ID: actionSuccess = await this.copyCipherFieldService.copy( this.cipher.login.username, "username", this.cipher, ); break; - case "copy-password": + case COPY_PASSWORD_ID: actionSuccess = await this.copyCipherFieldService.copy( this.cipher.login.password, "password", this.cipher, ); break; - case "copy-totp": + case COPY_VERIFICATION_CODE_ID: actionSuccess = await this.copyCipherFieldService.copy( this.cipher.login.totp, "totp", this.cipher, ); break; + case UPDATE_PASSWORD: { + const repromptSuccess = await this.passwordRepromptService.showPasswordPrompt(); + + await sendExtensionMessage("bgHandleReprompt", { + tab: await chrome.tabs.get(senderTabId), + success: repromptSuccess, + }); + + await closeViewVaultItemPopout(`${VaultPopoutType.viewVaultItem}_${this.cipher.id}`); + + break; + } } if (BrowserPopupUtils.inPopout(window)) { diff --git a/libs/common/src/autofill/constants/index.ts b/libs/common/src/autofill/constants/index.ts index 62ad10e9a90..dc79e27b6aa 100644 --- a/libs/common/src/autofill/constants/index.ts +++ b/libs/common/src/autofill/constants/index.ts @@ -38,7 +38,7 @@ export const ClearClipboardDelay = { FiveMinutes: 300, } as const; -/* Context Menu item Ids */ +/* Ids for context menu items and messaging events */ export const AUTOFILL_CARD_ID = "autofill-card"; export const AUTOFILL_ID = "autofill"; export const SHOW_AUTOFILL_BUTTON = "show-autofill-button"; @@ -54,6 +54,7 @@ export const GENERATE_PASSWORD_ID = "generate-password"; export const NOOP_COMMAND_SUFFIX = "noop"; export const ROOT_ID = "root"; export const SEPARATOR_ID = "separator"; +export const UPDATE_PASSWORD = "update-password"; export const NOTIFICATION_BAR_LIFESPAN_MS = 150000; // 150 seconds From 355bddc6c9d5c110e55fe74c5fcfa86ddd85572c Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Mon, 12 May 2025 11:50:29 -0400 Subject: [PATCH 24/35] [CL-301] Enable Storybook test runner. Run a11y tests also (#14646) * Enable Storybook test runner. Run a11y tests also * no need to return checkA11y function * add back decorator removed in error * add test runner to our ownership * add axe-playwright to our ownership --- .github/renovate.json5 | 2 + .storybook/preview.tsx | 7 + .storybook/test-runner.ts | 50 + package-lock.json | 2149 ++++++++++++++++++++++++++++++++++--- package.json | 4 + tsconfig.eslint.json | 1 + 6 files changed, 2062 insertions(+), 151 deletions(-) create mode 100644 .storybook/test-runner.ts diff --git a/.github/renovate.json5 b/.github/renovate.json5 index c1045739506..e5cd47077fb 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -312,6 +312,7 @@ "@angular/platform-browser", "@angular/platform", "@angular/router", + "axe-playwright", "@compodoc/compodoc", "@ng-select/ng-select", "@storybook/addon-a11y", @@ -320,6 +321,7 @@ "@storybook/addon-essentials", "@storybook/addon-interactions", "@storybook/addon-links", + "@storybook/test-runner", "@storybook/addon-themes", "@storybook/angular", "@storybook/manager-api", diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 6bd28cfe809..19a4fc51dc8 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -26,6 +26,13 @@ const preview: Preview = { wrapperDecorator, ], parameters: { + a11y: { + element: "#storybook-root", + manual: true, + options: { + runOnly: ["section508", "wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"], + }, + }, controls: { matchers: { color: /(background|color)$/i, diff --git a/.storybook/test-runner.ts b/.storybook/test-runner.ts new file mode 100644 index 00000000000..8584a321090 --- /dev/null +++ b/.storybook/test-runner.ts @@ -0,0 +1,50 @@ +import { + // waitForPageReady, + type TestRunnerConfig, +} from "@storybook/test-runner"; +import { injectAxe, checkA11y } from "axe-playwright"; + +const testRunnerConfig: TestRunnerConfig = { + setup() {}, + + async preVisit(page, context) { + return await injectAxe(page); + }, + + async postVisit(page, context) { + await page.waitForSelector("#storybook-root"); + // https://github.com/abhinaba-ghosh/axe-playwright#parameters-on-checka11y-axerun + await checkA11y( + // Playwright page instance. + page, + + // context + "#storybook-root", + + // axeOptions, see https://www.deque.com/axe/core-documentation/api-documentation/#parameters-axerun + { + detailedReport: true, + detailedReportOptions: { + // Includes the full html for invalid nodes + html: true, + }, + verbose: false, + }, + + // skipFailures + false, + + // reporter "v2" is terminal reporter, "html" writes results to file + "v2", + + // axeHtmlReporterOptions + // NOTE: set reporter param (above) to "html" to activate these options + { + outputDir: "reports/a11y", + reportFileName: `${context.id}.html`, + }, + ); + }, +}; + +export default testRunnerConfig; diff --git a/package-lock.json b/package-lock.json index a15275a695e..81c9384fbbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,7 @@ "@storybook/addon-essentials": "8.6.12", "@storybook/addon-interactions": "8.6.12", "@storybook/addon-links": "8.6.12", + "@storybook/test-runner": "0.22.0", "@storybook/addon-themes": "8.6.12", "@storybook/angular": "8.6.12", "@storybook/manager-api": "8.6.12", @@ -123,6 +124,7 @@ "@yao-pkg/pkg": "5.16.1", "angular-eslint": "18.4.3", "autoprefixer": "10.4.21", + "axe-playwright": "2.1.0", "babel-loader": "9.2.1", "base64-loader": "1.0.0", "browserslist": "4.23.2", @@ -3327,7 +3329,6 @@ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -3453,7 +3454,6 @@ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -3580,7 +3580,6 @@ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -4714,8 +4713,7 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@bitwarden/admin-console": { "resolved": "libs/admin-console", @@ -7179,7 +7177,6 @@ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -7197,7 +7194,6 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -7208,7 +7204,6 @@ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -7223,7 +7218,6 @@ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -7238,7 +7232,6 @@ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -7252,7 +7245,6 @@ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -7269,7 +7261,6 @@ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -7283,7 +7274,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7293,8 +7283,7 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", @@ -7312,7 +7301,6 @@ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -7331,7 +7319,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7342,7 +7329,6 @@ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -7391,7 +7377,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -7405,7 +7390,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -7420,8 +7404,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@jest/core/node_modules/slash": { "version": "3.0.0", @@ -7429,11 +7412,23 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -7456,7 +7451,6 @@ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -7502,7 +7496,6 @@ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -7519,7 +7512,6 @@ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -7564,7 +7556,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7577,7 +7568,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7599,7 +7589,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7613,7 +7602,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7637,7 +7625,6 @@ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -7653,7 +7640,6 @@ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -7670,7 +7656,6 @@ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -7687,7 +7672,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7698,7 +7682,6 @@ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -7725,8 +7708,7 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@jest/transform/node_modules/slash": { "version": "3.0.0", @@ -7734,7 +7716,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -10819,6 +10800,43 @@ "storybook": "^8.6.12" } }, + "node_modules/@storybook/test-runner": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@storybook/test-runner/-/test-runner-0.22.0.tgz", + "integrity": "sha512-fKY6MTE/bcvMaulKXy+z0fPmRXJx1REkYMOMcGn8zn6uffyBigGgaVf/sZ+AZfibwvjzg/StWhJ9HvAM8pc14g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5", + "@jest/types": "^29.6.3", + "@storybook/csf": "^0.1.11", + "@swc/core": "^1.5.22", + "@swc/jest": "^0.2.23", + "expect-playwright": "^0.8.0", + "jest": "^29.6.4", + "jest-circus": "^29.6.4", + "jest-environment-node": "^29.6.4", + "jest-junit": "^16.0.0", + "jest-playwright-preset": "^4.0.0", + "jest-runner": "^29.6.4", + "jest-serializer-html": "^7.1.0", + "jest-watch-typeahead": "^2.0.0", + "nyc": "^15.1.0", + "playwright": "^1.14.0" + }, + "bin": { + "test-storybook": "dist/test-storybook.js" + }, + "engines": { + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "storybook": "^0.0.0-0 || ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 || ^9.0.0-0" + } + }, "node_modules/@storybook/theming": { "version": "8.6.12", "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.12.tgz", @@ -10882,6 +10900,250 @@ "storybook": "^8.6.12" } }, + "node_modules/@swc/core": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz", + "integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.21" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.11.24", + "@swc/core-darwin-x64": "1.11.24", + "@swc/core-linux-arm-gnueabihf": "1.11.24", + "@swc/core-linux-arm64-gnu": "1.11.24", + "@swc/core-linux-arm64-musl": "1.11.24", + "@swc/core-linux-x64-gnu": "1.11.24", + "@swc/core-linux-x64-musl": "1.11.24", + "@swc/core-win32-arm64-msvc": "1.11.24", + "@swc/core-win32-ia32-msvc": "1.11.24", + "@swc/core-win32-x64-msvc": "1.11.24" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz", + "integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz", + "integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz", + "integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz", + "integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz", + "integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz", + "integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz", + "integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz", + "integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz", + "integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz", + "integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/jest": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.38.tgz", + "integrity": "sha512-HMoZgXWMqChJwffdDjvplH53g9G2ALQes3HKXDEdliB/b85OQ0CTSbxG8VSeCwiAn7cOaDVEt4mwmZvbHcS52w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.7.0", + "@swc/counter": "^0.1.3", + "jsonc-parser": "^3.2.0" + }, + "engines": { + "npm": ">= 7.0.0" + }, + "peerDependencies": { + "@swc/core": "*" + } + }, + "node_modules/@swc/types": { + "version": "0.1.21", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", + "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -11102,7 +11364,6 @@ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -11117,7 +11378,6 @@ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.0.0" } @@ -11128,7 +11388,6 @@ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -11140,7 +11399,6 @@ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.20.7" } @@ -11336,7 +11594,6 @@ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*" } @@ -11506,6 +11763,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/junit-report-builder": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/junit-report-builder/-/junit-report-builder-3.0.2.tgz", + "integrity": "sha512-R5M+SYhMbwBeQcNXYWNCZkl09vkVfAtcPIaCGdzIkkbeaTrVbGQ7HVgi4s+EmM/M1K4ZuWQH0jGcvMvNePfxYA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/keygrip": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", @@ -11908,6 +12172,16 @@ "license": "MIT", "optional": true }, + "node_modules/@types/wait-on": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/@types/wait-on/-/wait-on-5.3.4.tgz", + "integrity": "sha512-EBsPjFMrFlMbbUFf9D1Fp+PAB2TwmUn7a3YtHyD9RLuTIk1jDd8SxXVAoez2Ciy+8Jsceo2MYEYZzJ/DvorOKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/webpack-env": { "version": "1.18.8", "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.8.tgz", @@ -13845,6 +14119,19 @@ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", "license": "MIT" }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/archiver": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", @@ -13981,6 +14268,13 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true, + "license": "MIT" + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -14356,6 +14650,39 @@ "node": ">=4" } }, + "node_modules/axe-html-reporter": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/axe-html-reporter/-/axe-html-reporter-2.2.11.tgz", + "integrity": "sha512-WlF+xlNVgNVWiM6IdVrsh+N0Cw7qupe5HT9N6Uyi+aN7f6SSi92RDomiP1noW8OWIV85V6x404m5oKMeqRV3tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mustache": "^4.0.1" + }, + "engines": { + "node": ">=8.9.0" + }, + "peerDependencies": { + "axe-core": ">=3" + } + }, + "node_modules/axe-playwright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/axe-playwright/-/axe-playwright-2.1.0.tgz", + "integrity": "sha512-tY48SX56XaAp16oHPyD4DXpybz8Jxdz9P7exTjF/4AV70EGUavk+1fUPWirM0OYBR+YyDx6hUeDvuHVA6fB9YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/junit-report-builder": "^3.0.2", + "axe-core": "^4.10.1", + "axe-html-reporter": "2.2.11", + "junit-report-builder": "^5.1.1", + "picocolors": "^1.1.1" + }, + "peerDependencies": { + "playwright": ">1.0.0" + } + }, "node_modules/axios": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", @@ -14383,7 +14710,6 @@ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -14406,7 +14732,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14435,7 +14760,6 @@ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -14453,7 +14777,6 @@ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -14471,7 +14794,6 @@ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" } @@ -14482,7 +14804,6 @@ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -14600,7 +14921,6 @@ "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -14628,7 +14948,6 @@ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -15090,7 +15409,6 @@ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "node-int64": "^0.4.0" } @@ -15471,6 +15789,68 @@ "node": ">=8" } }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caching-transform/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/caching-transform/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/caching-transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -15553,7 +15933,6 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -15670,7 +16049,6 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -16037,8 +16415,7 @@ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", @@ -16123,6 +16500,13 @@ "node": ">=4.0.0" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -16751,7 +17135,6 @@ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -16942,6 +17325,20 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/cwd": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", + "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-pkg": "^0.1.2", + "fs-exists-sync": "^0.1.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -17120,7 +17517,6 @@ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -17216,6 +17612,22 @@ "node": ">= 10" } }, + "node_modules/default-require-extensions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -17342,7 +17754,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -17385,6 +17796,100 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/diffable-html": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/diffable-html/-/diffable-html-4.1.0.tgz", + "integrity": "sha512-++kyNek+YBLH8cLXS+iTj/Hiy2s5qkRJEJ8kgu/WHbFrVY2vz9xPFUT+fii2zGF0m1CaojDlQJjkfrCt7YWM1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "htmlparser2": "^3.9.2" + } + }, + "node_modules/diffable-html/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/diffable-html/node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/diffable-html/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/diffable-html/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/diffable-html/node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/diffable-html/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/diffable-html/node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/diffable-html/node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, "node_modules/dir-compare": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", @@ -18057,7 +18562,6 @@ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18382,8 +18886,7 @@ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/es6-shim": { "version": "0.35.8", @@ -19185,7 +19688,6 @@ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -19200,6 +19702,19 @@ "node": ">=6" } }, + "node_modules/expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-homedir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expect": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", @@ -19217,6 +19732,24 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/expect-playwright": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/expect-playwright/-/expect-playwright-0.8.0.tgz", + "integrity": "sha512-+kn8561vHAY+dt+0gMqqj1oY+g5xWrsuGMk4QGxotT2WS545nVqqjs37z6hrYfIuucwqthzwJfCJUEYqixyljg==", + "dev": true, + "license": "MIT" + }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/exponential-backoff": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", @@ -19596,7 +20129,6 @@ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "bser": "2.1.1" } @@ -19771,6 +20303,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-file-up": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", + "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-exists-sync": "^0.1.0", + "resolve-dir": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-pkg": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", + "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-file-up": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-process": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.10.tgz", + "integrity": "sha512-ncYFnWEIwL7PzmrK1yZtaccN8GhethD37RzBHG6iOZoFYB4vSmLLXfeWJjeN5nMvCJMjOtBvBBF8OgxEcikiZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "~4.1.2", + "commander": "^12.1.0", + "loglevel": "^1.9.2" + }, + "bin": { + "find-process": "bin/find-process.js" + } + }, + "node_modules/find-process/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -20305,6 +20889,27 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/front-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", @@ -20349,6 +20954,16 @@ "dev": true, "license": "MIT" }, + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fs-extra": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", @@ -20527,7 +21142,6 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -20678,6 +21292,56 @@ "node": ">=10.0" } }, + "node_modules/global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -20942,6 +21606,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -20964,6 +21655,19 @@ "he": "bin/he" } }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -21084,8 +21788,7 @@ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/html-loader": { "version": "5.1.0", @@ -22170,7 +22873,6 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -22475,6 +23177,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -22540,6 +23249,16 @@ "dev": true, "license": "MIT" }, + "node_modules/is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -22597,6 +23316,19 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-instrument": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", @@ -22614,13 +23346,116 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "dev": true, + "license": "ISC", + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -22636,7 +23471,6 @@ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -22652,7 +23486,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -22663,7 +23496,6 @@ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -22737,7 +23569,6 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -22765,7 +23596,6 @@ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -22781,7 +23611,6 @@ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -22814,7 +23643,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -22828,7 +23656,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -22843,8 +23670,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jest-circus/node_modules/slash": { "version": "3.0.0", @@ -22852,7 +23678,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -22863,7 +23688,6 @@ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -22898,7 +23722,6 @@ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -22945,7 +23768,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -22959,7 +23781,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -22972,7 +23793,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -22994,7 +23814,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -23008,7 +23827,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -23023,8 +23841,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jest-config/node_modules/slash": { "version": "3.0.0", @@ -23032,7 +23849,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -23094,7 +23910,6 @@ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "detect-newline": "^3.0.0" }, @@ -23108,7 +23923,6 @@ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -23126,7 +23940,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -23140,7 +23953,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -23155,8 +23967,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jest-environment-jsdom": { "version": "29.7.0", @@ -23385,7 +24196,6 @@ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -23414,7 +24224,6 @@ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -23467,7 +24276,6 @@ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" @@ -23482,7 +24290,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -23496,7 +24303,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -23511,8 +24317,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jest-matcher-utils": { "version": "29.7.0", @@ -23660,13 +24465,106 @@ "typescript": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, + "node_modules/jest-playwright-preset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jest-playwright-preset/-/jest-playwright-preset-4.0.0.tgz", + "integrity": "sha512-+dGZ1X2KqtwXaabVjTGxy0a3VzYfvYsWaRcuO8vMhyclHSOpGSI1+5cmlqzzCwQ3+fv0EjkTc7I5aV9lo08dYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect-playwright": "^0.8.0", + "jest-process-manager": "^0.4.0", + "nyc": "^15.1.0", + "playwright-core": ">=1.2.0", + "rimraf": "^3.0.2", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "jest": "^29.3.1", + "jest-circus": "^29.3.1", + "jest-environment-node": "^29.3.1", + "jest-runner": "^29.3.1" + } + }, + "node_modules/jest-playwright-preset/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-playwright-preset/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-playwright-preset/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-playwright-preset/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-playwright-preset/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -23743,13 +24641,58 @@ "dev": true, "license": "MIT" }, + "node_modules/jest-process-manager": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/jest-process-manager/-/jest-process-manager-0.4.0.tgz", + "integrity": "sha512-80Y6snDyb0p8GG83pDxGI/kQzwVTkCxc7ep5FPe/F6JYdvRDhwr6RzRmPSP7SEwuLhxo80lBS/NqOdUIbHIfhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/wait-on": "^5.2.0", + "chalk": "^4.1.0", + "cwd": "^0.10.0", + "exit": "^0.1.2", + "find-process": "^1.4.4", + "prompts": "^2.4.1", + "signal-exit": "^3.0.3", + "spawnd": "^5.0.0", + "tree-kill": "^1.2.2", + "wait-on": "^7.0.0" + } + }, + "node_modules/jest-process-manager/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jest-process-manager/node_modules/wait-on": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", + "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.6.1", + "joi": "^17.11.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.1" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jest-regex-util": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -23760,7 +24703,6 @@ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -23782,7 +24724,6 @@ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -23797,7 +24738,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -23808,7 +24748,6 @@ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -23842,7 +24781,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -23853,7 +24791,6 @@ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -23865,7 +24802,6 @@ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -23900,7 +24836,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -23913,7 +24848,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -23935,7 +24869,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -23949,18 +24882,26 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/jest-serializer-html": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer-html/-/jest-serializer-html-7.1.0.tgz", + "integrity": "sha512-xYL2qC7kmoYHJo8MYqJkzrl/Fdlx+fat4U1AqYg+kafqwcKPiMkOcjWHPKhueuNEgr+uemhGc+jqXYiwCyRyLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "diffable-html": "^4.1.0" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -23993,7 +24934,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -24007,7 +24947,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -24022,8 +24961,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jest-util": { "version": "29.7.0", @@ -24062,7 +25000,6 @@ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -24081,7 +25018,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -24095,7 +25031,6 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -24109,7 +25044,6 @@ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -24124,8 +25058,111 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, + "license": "MIT" + }, + "node_modules/jest-watch-typeahead": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-2.2.2.tgz", + "integrity": "sha512-+QgOFW4o5Xlgd6jGS5X37i08tuuXNW8X0CV9WNFi+3n8ExCIP+E1melYhvYLjv5fE6D0yyzk74vsSO8I6GqtvQ==", + "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "ansi-escapes": "^6.0.0", + "chalk": "^5.2.0", + "jest-regex-util": "^29.0.0", + "jest-watcher": "^29.0.0", + "slash": "^5.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0 || ^29.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/char-regex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.2.tgz", + "integrity": "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, "node_modules/jest-watcher": { "version": "29.7.0", @@ -24133,7 +25170,6 @@ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -24154,7 +25190,6 @@ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -24171,7 +25206,6 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -24518,6 +25552,47 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/junit-report-builder": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/junit-report-builder/-/junit-report-builder-5.1.1.tgz", + "integrity": "sha512-ZNOIIGMzqCGcHQEA2Q4rIQQ3Df6gSIfne+X9Rly9Bc2y55KxAZu8iGv+n2pP0bLf0XAOctJZgeloC54hWzCahQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "make-dir": "^3.1.0", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/junit-report-builder/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/junit-report-builder/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", @@ -24897,7 +25972,6 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -25602,6 +26676,13 @@ "license": "MIT", "peer": true }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -26001,7 +27082,6 @@ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "semver": "^7.5.3" }, @@ -26097,7 +27177,6 @@ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "tmpl": "1.0.5" } @@ -27587,6 +28666,16 @@ "readable-stream": "^3.6.0" } }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", @@ -28164,8 +29253,7 @@ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-machine-id": { "version": "1.1.12", @@ -28173,6 +29261,19 @@ "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", "dev": true }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -28844,6 +29945,350 @@ "node": ">=6" } }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc/node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/nyc/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -29113,6 +30558,16 @@ "dev": true, "license": "MIT" }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/os-name": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", @@ -29270,6 +30725,22 @@ "node": ">=6" } }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -29551,6 +31022,16 @@ "node": ">= 0.10" } }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/parse5": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", @@ -30112,6 +31593,53 @@ "node": ">=4" } }, + "node_modules/playwright": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.52.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -30634,6 +32162,19 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/process-on-spawn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", + "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -30808,8 +32349,7 @@ "url": "https://opencollective.com/fast-check" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/qrcode-parser": { "version": "2.1.3", @@ -31308,6 +32848,19 @@ "node": ">= 0.10" } }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "license": "ISC", + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/remark-gfm": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", @@ -31487,6 +33040,13 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -31550,6 +33110,20 @@ "node": ">=8" } }, + "node_modules/resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -32444,6 +34018,13 @@ "node": ">= 0.8" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -32888,6 +34469,164 @@ "node": ">=0.10.0" } }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/spawn-wrap/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/spawn-wrap/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-wrap/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/spawn-wrap/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/spawn-wrap/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/spawnd": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-5.0.0.tgz", + "integrity": "sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "exit": "^0.1.2", + "signal-exit": "^3.0.3", + "tree-kill": "^1.2.2", + "wait-port": "^0.2.9" + } + }, + "node_modules/spawnd/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -33234,7 +34973,6 @@ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -33364,7 +35102,6 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -33927,7 +35664,6 @@ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -33943,7 +35679,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -33956,7 +35691,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -33978,7 +35712,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -34148,8 +35881,7 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -34899,6 +36631,16 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "license": "MIT" }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", @@ -35490,7 +37232,6 @@ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -35505,8 +37246,7 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", @@ -36131,6 +37871,109 @@ "tslib": "^2.1.0" } }, + "node_modules/wait-port": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.14.tgz", + "integrity": "sha512-kIzjWcr6ykl7WFbZd0TMae8xovwqcqbx6FM9l+7agOgUByhzdjfzZBPK2CPufldTOMxbUivss//Sh9MFawmPRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.4.2", + "commander": "^3.0.2", + "debug": "^4.1.1" + }, + "bin": { + "wait-port": "bin/wait-port.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wait-port/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wait-port/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wait-port/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/wait-port/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/wait-port/node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true, + "license": "MIT" + }, + "node_modules/wait-port/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/wait-port/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/wait-port/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/walk-up-path": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", @@ -36144,7 +37987,6 @@ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "makeerror": "1.0.12" } @@ -36883,6 +38725,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, "node_modules/which-typed-array": { "version": "1.1.18", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", @@ -37030,7 +38879,6 @@ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -37044,8 +38892,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/ws": { "version": "8.18.1", diff --git a/package.json b/package.json index 904ae121cc9..8ba1c95df6a 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "storybook": "ng run components:storybook", "build-storybook": "ng run components:build-storybook", "build-storybook:ci": "ng run components:build-storybook --webpack-stats-json", + "test-stories": "test-storybook --url http://localhost:6006", + "test-stories:watch": "test-stories --watch", "postinstall": "patch-package" }, "workspaces": [ @@ -53,6 +55,7 @@ "@storybook/addon-essentials": "8.6.12", "@storybook/addon-interactions": "8.6.12", "@storybook/addon-links": "8.6.12", + "@storybook/test-runner": "0.22.0", "@storybook/addon-themes": "8.6.12", "@storybook/angular": "8.6.12", "@storybook/manager-api": "8.6.12", @@ -85,6 +88,7 @@ "@yao-pkg/pkg": "5.16.1", "angular-eslint": "18.4.3", "autoprefixer": "10.4.21", + "axe-playwright": "2.1.0", "babel-loader": "9.2.1", "base64-loader": "1.0.0", "browserslist": "4.23.2", diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 7ffa34df58c..e8c3f669c0c 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -45,6 +45,7 @@ "files": [ ".storybook/main.ts", ".storybook/manager.js", + ".storybook/test-runner.ts", "apps/browser/src/autofill/content/components/.lit-storybook/main.ts" ], "include": ["apps/**/*", "libs/**/*", "bitwarden_license/**/*", "scripts/**/*"], From a10b9530af5628552583f8afb31cb0d9d6928fd2 Mon Sep 17 00:00:00 2001 From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Date: Mon, 12 May 2025 18:20:56 +0100 Subject: [PATCH 25/35] changes to sponsorship is showing in individual vault (#14627) --- .../app/billing/settings/sponsored-families.component.ts | 8 +++++--- .../admin-console/models/data/organization.data.spec.ts | 1 + .../src/admin-console/models/data/organization.data.ts | 2 ++ .../src/admin-console/models/domain/organization.ts | 2 ++ .../models/response/profile-organization.response.ts | 2 ++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/billing/settings/sponsored-families.component.ts b/apps/web/src/app/billing/settings/sponsored-families.component.ts index cee08bae8cd..7e493168ce2 100644 --- a/apps/web/src/app/billing/settings/sponsored-families.component.ts +++ b/apps/web/src/app/billing/settings/sponsored-families.component.ts @@ -112,13 +112,15 @@ export class SponsoredFamiliesComponent implements OnInit, OnDestroy { }); } }); - this.anyOrgsAvailable$ = this.availableSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0)); this.activeSponsorshipOrgs$ = this.organizationService .organizations$(userId) - .pipe(map((orgs) => orgs.filter((o) => o.familySponsorshipFriendlyName !== null))); - + .pipe( + map((orgs) => + orgs.filter((o) => o.familySponsorshipFriendlyName !== null && !o.isAdminInitiated), + ), + ); this.anyActiveSponsorships$ = this.activeSponsorshipOrgs$.pipe(map((orgs) => orgs.length > 0)); this.loading = false; diff --git a/libs/common/src/admin-console/models/data/organization.data.spec.ts b/libs/common/src/admin-console/models/data/organization.data.spec.ts index fae24133502..7d66e7bc0d5 100644 --- a/libs/common/src/admin-console/models/data/organization.data.spec.ts +++ b/libs/common/src/admin-console/models/data/organization.data.spec.ts @@ -59,6 +59,7 @@ describe("ORGANIZATIONS state", () => { userIsManagedByOrganization: false, useRiskInsights: false, useAdminSponsoredFamilies: false, + isAdminInitiated: false, }, }; const result = sut.deserializer(JSON.parse(JSON.stringify(expectedResult))); diff --git a/libs/common/src/admin-console/models/data/organization.data.ts b/libs/common/src/admin-console/models/data/organization.data.ts index 799d062aefa..e0783957117 100644 --- a/libs/common/src/admin-console/models/data/organization.data.ts +++ b/libs/common/src/admin-console/models/data/organization.data.ts @@ -61,6 +61,7 @@ export class OrganizationData { userIsManagedByOrganization: boolean; useRiskInsights: boolean; useAdminSponsoredFamilies: boolean; + isAdminInitiated: boolean; constructor( response?: ProfileOrganizationResponse, @@ -124,6 +125,7 @@ export class OrganizationData { this.userIsManagedByOrganization = response.userIsManagedByOrganization; this.useRiskInsights = response.useRiskInsights; this.useAdminSponsoredFamilies = response.useAdminSponsoredFamilies; + this.isAdminInitiated = response.isAdminInitiated; this.isMember = options.isMember; this.isProviderUser = options.isProviderUser; diff --git a/libs/common/src/admin-console/models/domain/organization.ts b/libs/common/src/admin-console/models/domain/organization.ts index 2e51c54b0ad..1864d56649b 100644 --- a/libs/common/src/admin-console/models/domain/organization.ts +++ b/libs/common/src/admin-console/models/domain/organization.ts @@ -91,6 +91,7 @@ export class Organization { userIsManagedByOrganization: boolean; useRiskInsights: boolean; useAdminSponsoredFamilies: boolean; + isAdminInitiated: boolean; constructor(obj?: OrganizationData) { if (obj == null) { @@ -150,6 +151,7 @@ export class Organization { this.userIsManagedByOrganization = obj.userIsManagedByOrganization; this.useRiskInsights = obj.useRiskInsights; this.useAdminSponsoredFamilies = obj.useAdminSponsoredFamilies; + this.isAdminInitiated = obj.isAdminInitiated; } get canAccess() { diff --git a/libs/common/src/admin-console/models/response/profile-organization.response.ts b/libs/common/src/admin-console/models/response/profile-organization.response.ts index da97a1034b1..3a86c764eb8 100644 --- a/libs/common/src/admin-console/models/response/profile-organization.response.ts +++ b/libs/common/src/admin-console/models/response/profile-organization.response.ts @@ -56,6 +56,7 @@ export class ProfileOrganizationResponse extends BaseResponse { userIsManagedByOrganization: boolean; useRiskInsights: boolean; useAdminSponsoredFamilies: boolean; + isAdminInitiated: boolean; constructor(response: any) { super(response); @@ -123,5 +124,6 @@ export class ProfileOrganizationResponse extends BaseResponse { this.userIsManagedByOrganization = this.getResponseProperty("UserIsManagedByOrganization"); this.useRiskInsights = this.getResponseProperty("UseRiskInsights"); this.useAdminSponsoredFamilies = this.getResponseProperty("UseAdminSponsoredFamilies"); + this.isAdminInitiated = this.getResponseProperty("IsAdminInitiated"); } } From eed18c929437ab418f35b02b866088a041a83683 Mon Sep 17 00:00:00 2001 From: Todd Martin <106564991+trmartin4@users.noreply.github.com> Date: Mon, 12 May 2025 14:26:52 -0400 Subject: [PATCH 26/35] chore(view-cache): [PM-21154] Move view-cache its own feature package and adjust imports * Moved view-cache services to directory * Fixed DI for browser extension. * Fixed tests. --- .../view-cache/popup-view-cache.service.ts | 2 +- .../src/popup/services/services.module.ts | 2 +- .../vault-popup-list-filters.service.spec.ts | 5 +- .../vault-popup-list-filters.service.ts | 5 +- libs/angular/src/platform/view-cache/index.ts | 1 + .../src/platform/view-cache/internal.ts | 1 + .../noop-view-cache.service.ts | 6 +- .../src/platform/view-cache/view-cache.md | 130 ++++++++++++++++++ .../view-cache.service.ts | 2 + .../src/services/jslib-services.module.ts | 5 +- ...auth-component-email-cache.service.spec.ts | 2 +- ...auth-email-component-cache.service.spec.ts | 2 +- ...ctor-auth-email-component-cache.service.ts | 2 +- ...actor-auth-component-cache.service.spec.ts | 2 +- ...two-factor-auth-component-cache.service.ts | 2 +- ...gin-via-auth-request-cache.service.spec.ts | 2 +- ...lt-login-via-auth-request-cache.service.ts | 2 +- .../src/cipher-form/cipher-form.stories.ts | 2 +- .../components/cipher-form.component.spec.ts | 2 +- .../default-cipher-form-cache.service.spec.ts | 2 +- .../default-cipher-form-cache.service.ts | 2 +- 21 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 libs/angular/src/platform/view-cache/index.ts create mode 100644 libs/angular/src/platform/view-cache/internal.ts rename libs/angular/src/platform/{services => view-cache}/noop-view-cache.service.ts (87%) create mode 100644 libs/angular/src/platform/view-cache/view-cache.md rename libs/angular/src/platform/{abstractions => view-cache}/view-cache.service.ts (98%) diff --git a/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts b/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts index ff63b52ab3f..2a946982990 100644 --- a/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts +++ b/apps/browser/src/platform/popup/view-cache/popup-view-cache.service.ts @@ -19,7 +19,7 @@ import { FormCacheOptions, SignalCacheOptions, ViewCacheService, -} from "@bitwarden/angular/platform/abstractions/view-cache.service"; +} from "@bitwarden/angular/platform/view-cache"; import { MessageSender } from "@bitwarden/common/platform/messaging"; import { GlobalStateProvider } from "@bitwarden/common/platform/state"; diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 00b8ae81cf9..6ede88dfc13 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -5,9 +5,9 @@ import { Router } from "@angular/router"; import { merge, of, Subject } from "rxjs"; import { CollectionService } from "@bitwarden/admin-console/common"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; import { AngularThemingService } from "@bitwarden/angular/platform/services/theming/angular-theming.service"; import { SafeProvider, safeProvider } from "@bitwarden/angular/platform/utils/safe-provider"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { CLIENT_TYPE, DEFAULT_VAULT_TIMEOUT, diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts index 9498d953808..621ec795157 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts @@ -4,6 +4,7 @@ import { FormBuilder } from "@angular/forms"; import { BehaviorSubject, skipWhile } from "rxjs"; import { CollectionService, CollectionView } from "@bitwarden/admin-console/common"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; @@ -20,8 +21,6 @@ import { CipherType } from "@bitwarden/common/vault/enums"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; -import { PopupViewCacheService } from "../../../platform/popup/view-cache/popup-view-cache.service"; - import { CachedFilterState, MY_VAULT_ID, @@ -123,7 +122,7 @@ describe("VaultPopupListFiltersService", () => { useValue: accountService, }, { - provide: PopupViewCacheService, + provide: ViewCacheService, useValue: viewCacheService, }, ], diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts index c726678c973..db4cfeefe9f 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts @@ -15,6 +15,7 @@ import { } from "rxjs"; import { CollectionService, CollectionView } from "@bitwarden/admin-console/common"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { DynamicTreeNode } from "@bitwarden/angular/vault/vault-filter/models/dynamic-tree-node.model"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; @@ -40,8 +41,6 @@ import { FolderView } from "@bitwarden/common/vault/models/view/folder.view"; import { ServiceUtils } from "@bitwarden/common/vault/service-utils"; import { ChipSelectOption } from "@bitwarden/components"; -import { PopupViewCacheService } from "../../../platform/popup/view-cache/popup-view-cache.service"; - const FILTER_VISIBILITY_KEY = new KeyDefinition(VAULT_SETTINGS_DISK, "filterVisibility", { deserializer: (obj) => obj, }); @@ -178,7 +177,7 @@ export class VaultPopupListFiltersService { private policyService: PolicyService, private stateProvider: StateProvider, private accountService: AccountService, - private viewCacheService: PopupViewCacheService, + private viewCacheService: ViewCacheService, ) { this.filterForm.controls.organization.valueChanges .pipe(takeUntilDestroyed()) diff --git a/libs/angular/src/platform/view-cache/index.ts b/libs/angular/src/platform/view-cache/index.ts new file mode 100644 index 00000000000..79deef6aa5b --- /dev/null +++ b/libs/angular/src/platform/view-cache/index.ts @@ -0,0 +1 @@ +export { ViewCacheService, FormCacheOptions, SignalCacheOptions } from "./view-cache.service"; diff --git a/libs/angular/src/platform/view-cache/internal.ts b/libs/angular/src/platform/view-cache/internal.ts new file mode 100644 index 00000000000..6e0992eecbf --- /dev/null +++ b/libs/angular/src/platform/view-cache/internal.ts @@ -0,0 +1 @@ +export { NoopViewCacheService } from "./noop-view-cache.service"; diff --git a/libs/angular/src/platform/services/noop-view-cache.service.ts b/libs/angular/src/platform/view-cache/noop-view-cache.service.ts similarity index 87% rename from libs/angular/src/platform/services/noop-view-cache.service.ts rename to libs/angular/src/platform/view-cache/noop-view-cache.service.ts index 9953e80b3b0..f83a0fc0b04 100644 --- a/libs/angular/src/platform/services/noop-view-cache.service.ts +++ b/libs/angular/src/platform/view-cache/noop-view-cache.service.ts @@ -1,11 +1,7 @@ import { Injectable, signal, WritableSignal } from "@angular/core"; import type { FormGroup } from "@angular/forms"; -import { - FormCacheOptions, - SignalCacheOptions, - ViewCacheService, -} from "../abstractions/view-cache.service"; +import { FormCacheOptions, SignalCacheOptions, ViewCacheService } from "./view-cache.service"; /** * The functionality of the {@link ViewCacheService} is only needed in the browser extension popup, diff --git a/libs/angular/src/platform/view-cache/view-cache.md b/libs/angular/src/platform/view-cache/view-cache.md new file mode 100644 index 00000000000..c1f80da5800 --- /dev/null +++ b/libs/angular/src/platform/view-cache/view-cache.md @@ -0,0 +1,130 @@ +# Extension Persistence + +By default, when the browser extension popup closes, the user's current view and any data entered +without saving is lost. This introduces friction in several workflows within our client, such as: + +- Performing actions that require email OTP entry, since the user must navigate from the popup to + get to their email inbox +- Entering information to create a new vault item from a browser tab +- And many more + +Previously, we have recommended that users "pop out" the extension into its own window to persist +the extension context, but this introduces additional user actions and may leave the extension open +(and unlocked) for longer than a user intends. + +In order to provide a better user experience, we have introduced two levels of persistence to the +Bitwarden extension client: + +- We persist the route history, allowing us to re-open the last route when the popup re-opens, and +- We offer a service for teams to use to persist component-specific form data or state to survive a + popup close/re-open cycle + +## Persistence lifetime + +Since we are persisting data, it is important that the lifetime of that data be well-understood and +well-constrained. The cache of route history and form data is cleared when any of the following +events occur: + +- The account is locked +- The account is logged out +- Account switching is used to switch the active account +- The extension popup has been closed for 2 minutes + +In addition, cached form data is cleared when a browser extension navigation event occurs (e.g. +switching between tabs in the extension). + +## Types of persistence + +### Route history persistence + +Route history is persisted on the extension automatically, with no specific implementation required +on any component. + +The persistence layer ensures that the popup will open at the same route as was active when it +closed, provided that none of the lifetime expiration events have occurred. + +:::tip Excluding a route + +If a particular route should be excluded from the history and not persisted, add +`doNotSaveUrl: true` to the `data` property on the route. + +::: + +### View data persistence + +Route persistence ensures that the user will land back on the route that they were on when the popup +closed, but it does not persist any state or form data that the user may have modified. In order to +persist that data, the component is responsible for registering that data with the +[`ViewCacheService`](./view-cache.service.ts). +This is done prescriptively to ensure that only necessary data is cached and that it is done with +intention by the component. + +The `ViewCacheService` provides an interface for caching both individual state and `FormGroup`s. + +#### Caching individual data elements + +For individual pieces of state, use the `signal()` method on the `ViewCacheService` to create a +writeable [signal](https://angular.dev/guide/signals) wrapper around the desired state. + +```typescript +const mySignal = this.viewCacheService.signal({ + key: "my-state-key" + initialValue: null +}); +``` + +If a cached value exists, the returned signal will contain the cached data. + +Setting the value should be done through the signal's `set()` method: + +```typescript +const mySignal = this.viewCacheService.signal({ + key: "my-state-key" + initialValue: null +}); +mySignal.set("value") +``` + +:::note Equality comparison + +By default, signals use `Object.is` to determine equality, and `set()` will only trigger updates if +the updated value is not equal to the current signal state. See documentation +[here](https://angular.dev/guide/signals#signal-equality-functions). + +::: + +Putting this together, the most common implementation pattern would be: + +1. **Register the signal** using `ViewCacheService.signal()` on initialization of the component or + service responsible for the state being persisted. +2. **Restore state from the signal:** If cached data exists, the signal will contain that data. The + component or service should use this data to re-create the state from prior to the popup closing. +3. **Set new state** in the cache when it changes. Ensure that any updates to the data are persisted + to the cache with `set()`, so that the cache reflects the latest state. + +#### Caching form data + +For persisting form data, the `ViewCacheService` supplies a `formGroup()` method, which manages the +persistence of any entered form data to the cache and the initialization of the form from the cached +data. You can supply the `FormGroup` in the `control` parameter of the method, and the +`ViewCacheService` will: + +- Initialize the form the a cached value, if it exists +- Save form value to cache when it changes +- Mark the form dirty if the restored value is not `undefined`. + +```typescript +this.loginDetailsForm = this.viewCacheService.formGroup({ + key: "my-form", + control: this.formBuilder.group({ + username: [""], + email: [""], + }), +}); +``` + +## What about other clients? + +The `ViewCacheService` is designed to be injected into shared, client-agnostic components. A +`NoopViewCacheService` is provided and injected for non-extension clients, preserving a single +interface for your components. diff --git a/libs/angular/src/platform/abstractions/view-cache.service.ts b/libs/angular/src/platform/view-cache/view-cache.service.ts similarity index 98% rename from libs/angular/src/platform/abstractions/view-cache.service.ts rename to libs/angular/src/platform/view-cache/view-cache.service.ts index c5ae6c77d1f..498a29aa242 100644 --- a/libs/angular/src/platform/abstractions/view-cache.service.ts +++ b/libs/angular/src/platform/view-cache/view-cache.service.ts @@ -42,6 +42,8 @@ export type FormCacheOptions = BaseCacheOptions< /** * Cache for temporary component state * + * [Read more](./view-cache.md) + * * #### Implementations * - browser extension popup: used to persist UI between popup open and close * - all other clients: noop diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 4e7c558a0f0..470115ae3f0 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -325,13 +325,14 @@ import { import { DeviceTrustToastService as DeviceTrustToastServiceAbstraction } from "../auth/services/device-trust-toast.service.abstraction"; import { DeviceTrustToastService } from "../auth/services/device-trust-toast.service.implementation"; import { FormValidationErrorsService as FormValidationErrorsServiceAbstraction } from "../platform/abstractions/form-validation-errors.service"; -import { ViewCacheService } from "../platform/abstractions/view-cache.service"; import { FormValidationErrorsService } from "../platform/services/form-validation-errors.service"; import { LoggingErrorHandler } from "../platform/services/logging-error-handler"; -import { NoopViewCacheService } from "../platform/services/noop-view-cache.service"; import { AngularThemingService } from "../platform/services/theming/angular-theming.service"; import { AbstractThemingService } from "../platform/services/theming/theming.service.abstraction"; import { safeProvider, SafeProvider } from "../platform/utils/safe-provider"; +import { ViewCacheService } from "../platform/view-cache"; +// eslint-disable-next-line no-restricted-imports -- Needed for DI +import { NoopViewCacheService } from "../platform/view-cache/internal"; import { CLIENT_TYPE, diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts index f3b904a4ea6..d2d86710b72 100644 --- a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-component-email-cache.service.spec.ts @@ -2,7 +2,7 @@ import { TestBed } from "@angular/core/testing"; import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject } from "rxjs"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts index 1613c0e4af8..36d99ee56ac 100644 --- a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.spec.ts @@ -2,7 +2,7 @@ import { TestBed } from "@angular/core/testing"; import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject } from "rxjs"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts index e32b6cd1385..d274b8003d7 100644 --- a/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts +++ b/libs/auth/src/angular/two-factor-auth/child-components/two-factor-auth-email/two-factor-auth-email-component-cache.service.ts @@ -1,7 +1,7 @@ import { inject, Injectable, WritableSignal } from "@angular/core"; import { Jsonify } from "type-fest"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.spec.ts b/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.spec.ts index 0993954fde1..5b5d486556b 100644 --- a/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.spec.ts +++ b/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.spec.ts @@ -2,7 +2,7 @@ import { TestBed } from "@angular/core/testing"; import { mock, MockProxy } from "jest-mock-extended"; import { BehaviorSubject } from "rxjs"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.ts b/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.ts index 61b44aa98dd..2d9fcaa5633 100644 --- a/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.ts +++ b/libs/auth/src/angular/two-factor-auth/two-factor-auth-component-cache.service.ts @@ -1,7 +1,7 @@ import { inject, Injectable, WritableSignal } from "@angular/core"; import { Jsonify } from "type-fest"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts index 89b78500f1f..ab82b98f614 100644 --- a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts @@ -1,7 +1,7 @@ import { signal } from "@angular/core"; import { TestBed } from "@angular/core/testing"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { LoginViaAuthRequestView } from "@bitwarden/common/auth/models/view/login-via-auth-request.view"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; diff --git a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts index 493fea5c14b..8fbdb925e7c 100644 --- a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts +++ b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts @@ -1,6 +1,6 @@ import { inject, Injectable, WritableSignal } from "@angular/core"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { LoginViaAuthRequestView } from "@bitwarden/common/auth/models/view/login-via-auth-request.view"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; diff --git a/libs/vault/src/cipher-form/cipher-form.stories.ts b/libs/vault/src/cipher-form/cipher-form.stories.ts index 9943f07292d..7090502ef14 100644 --- a/libs/vault/src/cipher-form/cipher-form.stories.ts +++ b/libs/vault/src/cipher-form/cipher-form.stories.ts @@ -13,7 +13,7 @@ import { import { BehaviorSubject } from "rxjs"; import { CollectionView } from "@bitwarden/admin-console/common"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { AuditService } from "@bitwarden/common/abstractions/audit.service"; import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; diff --git a/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts b/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts index 4c61ad5d2d5..da687f33ef9 100644 --- a/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts +++ b/libs/vault/src/cipher-form/components/cipher-form.component.spec.ts @@ -3,7 +3,7 @@ import { ComponentFixture, TestBed } from "@angular/core/testing"; import { ReactiveFormsModule } from "@angular/forms"; import { mock } from "jest-mock-extended"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { Cipher } from "@bitwarden/common/vault/models/domain/cipher"; diff --git a/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.spec.ts b/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.spec.ts index 6236e2d3dac..0dec46e1b20 100644 --- a/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.spec.ts +++ b/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.spec.ts @@ -1,7 +1,7 @@ import { signal } from "@angular/core"; import { TestBed } from "@angular/core/testing"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; diff --git a/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.ts b/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.ts index 268b2db306b..b4a8138e025 100644 --- a/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.ts +++ b/libs/vault/src/cipher-form/services/default-cipher-form-cache.service.ts @@ -1,6 +1,6 @@ import { inject, Injectable } from "@angular/core"; -import { ViewCacheService } from "@bitwarden/angular/platform/abstractions/view-cache.service"; +import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; From a8fb456329ab1d5eaa32684e43dffc6a8585b829 Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Mon, 12 May 2025 14:38:08 -0400 Subject: [PATCH 27/35] Uif/remove a11y manual flag (#14744) * remove comment left in error * remove runOnly options and manual flag --- .storybook/preview.tsx | 4 ---- .storybook/test-runner.ts | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 19a4fc51dc8..a948fce0428 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -28,10 +28,6 @@ const preview: Preview = { parameters: { a11y: { element: "#storybook-root", - manual: true, - options: { - runOnly: ["section508", "wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"], - }, }, controls: { matchers: { diff --git a/.storybook/test-runner.ts b/.storybook/test-runner.ts index 8584a321090..208adf96214 100644 --- a/.storybook/test-runner.ts +++ b/.storybook/test-runner.ts @@ -1,7 +1,4 @@ -import { - // waitForPageReady, - type TestRunnerConfig, -} from "@storybook/test-runner"; +import { type TestRunnerConfig } from "@storybook/test-runner"; import { injectAxe, checkA11y } from "axe-playwright"; const testRunnerConfig: TestRunnerConfig = { From 90d8e822ff09d6c4013cc346972712e902c0f797 Mon Sep 17 00:00:00 2001 From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Date: Mon, 12 May 2025 14:08:48 -0500 Subject: [PATCH 28/35] chore: remove vault-bulk-management-action flag for the third time, refs PM-13112 (#14747) --- libs/common/src/enums/feature-flag.enum.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index 08de8ada25a..aa9a9ab5d6e 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -55,7 +55,6 @@ export enum FeatureFlag { /* Vault */ PM8851_BrowserOnboardingNudge = "pm-8851-browser-onboarding-nudge", PM9111ExtensionPersistAddEditForm = "pm-9111-extension-persist-add-edit-form", - VaultBulkManagementAction = "vault-bulk-management-action", SecurityTasks = "security-tasks", CipherKeyEncryption = "cipher-key-encryption", PM18520_UpdateDesktopCipherForm = "pm-18520-desktop-cipher-forms", @@ -107,7 +106,6 @@ export const DefaultFeatureFlagValue = { /* Vault */ [FeatureFlag.PM8851_BrowserOnboardingNudge]: FALSE, [FeatureFlag.PM9111ExtensionPersistAddEditForm]: FALSE, - [FeatureFlag.VaultBulkManagementAction]: FALSE, [FeatureFlag.SecurityTasks]: FALSE, [FeatureFlag.CipherKeyEncryption]: FALSE, [FeatureFlag.PM18520_UpdateDesktopCipherForm]: FALSE, From ce8e123c447c8bdbbbc8a6bb0eb1381e837e4fbe Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Mon, 12 May 2025 12:17:15 -0700 Subject: [PATCH 29/35] [PM-21480] - check for privacy granted in isBrowserAutofillSettingOverridden (#14748) * check for privacy granted in isBrowserAutofillSettingOverridden * check for privacy granted in browserAutofillSettingsOverridden --- apps/browser/src/platform/browser/browser-api.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/browser/src/platform/browser/browser-api.ts b/apps/browser/src/platform/browser/browser-api.ts index b27e8ca7c96..4ef72fa0077 100644 --- a/apps/browser/src/platform/browser/browser-api.ts +++ b/apps/browser/src/platform/browser/browser-api.ts @@ -664,6 +664,10 @@ export class BrowserApi { * Identifies if the browser autofill settings are overridden by the extension. */ static async browserAutofillSettingsOverridden(): Promise { + if (!(await BrowserApi.permissionsGranted(["privacy"]))) { + return false; + } + const checkOverrideStatus = (details: chrome.types.ChromeSettingGetResult) => details.levelOfControl === "controlled_by_this_extension" && !details.value; From b8074a6f730c0179b71f2ccde0b06920d46d57ea Mon Sep 17 00:00:00 2001 From: Todd Martin <106564991+trmartin4@users.noreply.github.com> Date: Mon, 12 May 2025 15:18:02 -0400 Subject: [PATCH 30/35] chore(feature-flag): Remove pm-9112-device-approval-persistence (#14718) --- .../login-via-auth-request.component.ts | 34 +++++------ ...gin-via-auth-request-cache.service.spec.ts | 61 ++++--------------- ...lt-login-via-auth-request-cache.service.ts | 27 -------- libs/common/src/enums/feature-flag.enum.ts | 2 - 4 files changed, 27 insertions(+), 97 deletions(-) diff --git a/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts index ab5b0c09b32..4c95a1eca3e 100644 --- a/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts +++ b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts @@ -23,12 +23,10 @@ import { AuthRequest } from "@bitwarden/common/auth/models/request/auth.request" import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response"; import { LoginViaAuthRequestView } from "@bitwarden/common/auth/models/view/login-via-auth-request.view"; import { ClientType, HttpStatusCode } from "@bitwarden/common/enums"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service"; import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -101,7 +99,6 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { private validationService: ValidationService, private loginSuccessHandlerService: LoginSuccessHandlerService, private loginViaAuthRequestCacheService: LoginViaAuthRequestCacheService, - private configService: ConfigService, ) { this.clientType = this.platformUtilsService.getClientType(); @@ -132,7 +129,6 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { async ngOnInit(): Promise { // Get the authStatus early because we use it in both flows this.authStatus = await firstValueFrom(this.authService.activeAccountStatus$); - await this.loginViaAuthRequestCacheService.init(); const userHasAuthenticatedViaSSO = this.authStatus === AuthenticationStatus.Locked; @@ -410,24 +406,22 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { const authRequestResponse: AuthRequestResponse = await this.authRequestApiService.postAuthRequest(authRequest); - if (await this.configService.getFeatureFlag(FeatureFlag.PM9112_DeviceApprovalPersistence)) { - if (!this.authRequestKeyPair.privateKey) { - this.logService.error("No private key when trying to cache the login view."); - return; - } - - if (!this.accessCode) { - this.logService.error("No access code when trying to cache the login view."); - return; - } - - this.loginViaAuthRequestCacheService.cacheLoginView( - authRequestResponse.id, - this.authRequestKeyPair.privateKey, - this.accessCode, - ); + if (!this.authRequestKeyPair.privateKey) { + this.logService.error("No private key when trying to cache the login view."); + return; } + if (!this.accessCode) { + this.logService.error("No access code when trying to cache the login view."); + return; + } + + this.loginViaAuthRequestCacheService.cacheLoginView( + authRequestResponse.id, + this.authRequestKeyPair.privateKey, + this.accessCode, + ); + if (authRequestResponse.id) { await this.anonymousHubService.createHubConnection(authRequestResponse.id); } diff --git a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts index ab82b98f614..67ac605e611 100644 --- a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.spec.ts @@ -3,7 +3,6 @@ import { TestBed } from "@angular/core/testing"; import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { LoginViaAuthRequestView } from "@bitwarden/common/auth/models/view/login-via-auth-request.view"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { LoginViaAuthRequestCacheService } from "./default-login-via-auth-request-cache.service"; @@ -14,74 +13,40 @@ describe("LoginViaAuthRequestCache", () => { const cacheSignal = signal(null); const getCacheSignal = jest.fn().mockReturnValue(cacheSignal); - const getFeatureFlag = jest.fn().mockResolvedValue(false); const cacheSetMock = jest.spyOn(cacheSignal, "set"); beforeEach(() => { getCacheSignal.mockClear(); - getFeatureFlag.mockClear(); cacheSetMock.mockClear(); testBed = TestBed.configureTestingModule({ providers: [ { provide: ViewCacheService, useValue: { signal: getCacheSignal } }, - { provide: ConfigService, useValue: { getFeatureFlag } }, LoginViaAuthRequestCacheService, ], }); }); - describe("feature enabled", () => { - beforeEach(() => { - getFeatureFlag.mockResolvedValue(true); - }); + it("`getCachedLoginViaAuthRequestView` returns the cached data", async () => { + cacheSignal.set({ ...buildMockState() }); + service = testBed.inject(LoginViaAuthRequestCacheService); - it("`getCachedLoginViaAuthRequestView` returns the cached data", async () => { - cacheSignal.set({ ...buildMockState() }); - service = testBed.inject(LoginViaAuthRequestCacheService); - await service.init(); - - expect(service.getCachedLoginViaAuthRequestView()).toEqual({ - ...buildMockState(), - }); - }); - - it("updates the signal value", async () => { - service = testBed.inject(LoginViaAuthRequestCacheService); - await service.init(); - - const parameters = buildAuthenticMockAuthView(); - - service.cacheLoginView(parameters.id, parameters.privateKey, parameters.accessCode); - - expect(cacheSignal.set).toHaveBeenCalledWith({ - id: parameters.id, - privateKey: Utils.fromBufferToB64(parameters.privateKey), - accessCode: parameters.accessCode, - }); + expect(service.getCachedLoginViaAuthRequestView()).toEqual({ + ...buildMockState(), }); }); - describe("feature disabled", () => { - beforeEach(async () => { - cacheSignal.set({ ...buildMockState() } as LoginViaAuthRequestView); - getFeatureFlag.mockResolvedValue(false); - cacheSetMock.mockClear(); + it("updates the signal value", async () => { + service = testBed.inject(LoginViaAuthRequestCacheService); - service = testBed.inject(LoginViaAuthRequestCacheService); - await service.init(); - }); + const parameters = buildAuthenticMockAuthView(); - it("`getCachedCipherView` returns null", () => { - expect(service.getCachedLoginViaAuthRequestView()).toBeNull(); - }); + service.cacheLoginView(parameters.id, parameters.privateKey, parameters.accessCode); - it("does not update the signal value", () => { - const params = buildAuthenticMockAuthView(); - - service.cacheLoginView(params.id, params.privateKey, params.accessCode); - - expect(cacheSignal.set).not.toHaveBeenCalled(); + expect(cacheSignal.set).toHaveBeenCalledWith({ + id: parameters.id, + privateKey: Utils.fromBufferToB64(parameters.privateKey), + accessCode: parameters.accessCode, }); }); diff --git a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts index 8fbdb925e7c..80dbafd3159 100644 --- a/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts +++ b/libs/auth/src/common/services/auth-request/default-login-via-auth-request-cache.service.ts @@ -2,8 +2,6 @@ import { inject, Injectable, WritableSignal } from "@angular/core"; import { ViewCacheService } from "@bitwarden/angular/platform/view-cache"; import { LoginViaAuthRequestView } from "@bitwarden/common/auth/models/view/login-via-auth-request.view"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; const LOGIN_VIA_AUTH_CACHE_KEY = "login-via-auth-request-form-cache"; @@ -17,10 +15,6 @@ const LOGIN_VIA_AUTH_CACHE_KEY = "login-via-auth-request-form-cache"; @Injectable() export class LoginViaAuthRequestCacheService { private viewCacheService: ViewCacheService = inject(ViewCacheService); - private configService: ConfigService = inject(ConfigService); - - /** True when the `PM9112_DeviceApproval` flag is enabled */ - private featureEnabled: boolean = false; private defaultLoginViaAuthRequestCache: WritableSignal = this.viewCacheService.signal({ @@ -31,23 +25,10 @@ export class LoginViaAuthRequestCacheService { constructor() {} - /** - * Must be called once before interacting with the cached data, otherwise methods will be noop. - */ - async init() { - this.featureEnabled = await this.configService.getFeatureFlag( - FeatureFlag.PM9112_DeviceApprovalPersistence, - ); - } - /** * Update the cache with the new LoginView. */ cacheLoginView(id: string, privateKey: Uint8Array, accessCode: string): void { - if (!this.featureEnabled) { - return; - } - // When the keys get stored they should be converted to a B64 string to ensure // data can be properly formed when json-ified. If not done, they are not stored properly and // will not be parsable by the cryptography library after coming out of storage. @@ -59,10 +40,6 @@ export class LoginViaAuthRequestCacheService { } clearCacheLoginView(): void { - if (!this.featureEnabled) { - return; - } - this.defaultLoginViaAuthRequestCache.set(null); } @@ -70,10 +47,6 @@ export class LoginViaAuthRequestCacheService { * Returns the cached LoginViaAuthRequestView when available. */ getCachedLoginViaAuthRequestView(): LoginViaAuthRequestView | null { - if (!this.featureEnabled) { - return null; - } - return this.defaultLoginViaAuthRequestCache(); } } diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index aa9a9ab5d6e..a7679a6248a 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -16,7 +16,6 @@ export enum FeatureFlag { SeparateCustomRolePermissions = "pm-19917-separate-custom-role-permissions", /* Auth */ - PM9112_DeviceApprovalPersistence = "pm-9112-device-approval-persistence", PM9115_TwoFactorExtensionDataPersistence = "pm-9115-two-factor-extension-data-persistence", /* Autofill */ @@ -112,7 +111,6 @@ export const DefaultFeatureFlagValue = { [FeatureFlag.EndUserNotifications]: FALSE, /* Auth */ - [FeatureFlag.PM9112_DeviceApprovalPersistence]: FALSE, [FeatureFlag.PM9115_TwoFactorExtensionDataPersistence]: FALSE, /* Billing */ From 7d01c42e37e07d6642a2fbda5eb27cc12fdf4f85 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 15:42:21 -0400 Subject: [PATCH 31/35] [deps] Vault: Update multer to v1.4.5-lts.2 (#14469) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: SmithThe4th --- apps/cli/package.json | 2 +- package-lock.json | 10 +++++----- package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 79d4786a23c..0a7e66d7818 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -81,7 +81,7 @@ "koa-json": "2.0.2", "lowdb": "1.0.0", "lunr": "2.3.9", - "multer": "1.4.5-lts.1", + "multer": "1.4.5-lts.2", "node-fetch": "2.6.12", "node-forge": "1.3.1", "open": "8.4.2", diff --git a/package-lock.json b/package-lock.json index 81c9384fbbb..44bebc9cbd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,7 +54,7 @@ "lit": "3.2.1", "lowdb": "1.0.0", "lunr": "2.3.9", - "multer": "1.4.5-lts.1", + "multer": "1.4.5-lts.2", "ngx-toastr": "19.0.0", "node-fetch": "2.6.12", "node-forge": "1.3.1", @@ -217,7 +217,7 @@ "koa-json": "2.0.2", "lowdb": "1.0.0", "lunr": "2.3.9", - "multer": "1.4.5-lts.1", + "multer": "1.4.5-lts.2", "node-fetch": "2.6.12", "node-forge": "1.3.1", "open": "8.4.2", @@ -28598,9 +28598,9 @@ } }, "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", diff --git a/package.json b/package.json index 8ba1c95df6a..47cede513ed 100644 --- a/package.json +++ b/package.json @@ -190,7 +190,7 @@ "lit": "3.2.1", "lowdb": "1.0.0", "lunr": "2.3.9", - "multer": "1.4.5-lts.1", + "multer": "1.4.5-lts.2", "ngx-toastr": "19.0.0", "node-fetch": "2.6.12", "node-forge": "1.3.1", From 9af7963609a08a5e00dd209e5614022c0d58350a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 14:58:48 -0500 Subject: [PATCH 32/35] [deps] Vault: Update @koa/multer to v3.1.0 (#14495) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> --- apps/cli/package.json | 2 +- package-lock.json | 68 ++++++++++++++++++++----------------------- package.json | 2 +- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 0a7e66d7818..82faa7d40e6 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -64,7 +64,7 @@ ] }, "dependencies": { - "@koa/multer": "3.0.2", + "@koa/multer": "3.1.0", "@koa/router": "13.1.0", "argon2": "0.41.1", "big-integer": "1.6.52", diff --git a/package-lock.json b/package-lock.json index 44bebc9cbd4..8466a4ba4c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "@bitwarden/sdk-internal": "0.2.0-main.159", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", - "@koa/multer": "3.0.2", + "@koa/multer": "3.1.0", "@koa/router": "13.1.0", "@microsoft/signalr": "8.0.7", "@microsoft/signalr-protocol-msgpack": "8.0.7", @@ -200,7 +200,7 @@ "version": "2025.4.0", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { - "@koa/multer": "3.0.2", + "@koa/multer": "3.1.0", "@koa/router": "13.1.0", "argon2": "0.41.1", "big-integer": "1.6.52", @@ -389,6 +389,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -2745,6 +2746,7 @@ "version": "7.26.8", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2754,6 +2756,7 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -2784,12 +2787,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2799,6 +2804,7 @@ "version": "7.26.10", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", + "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.26.10", @@ -2828,6 +2834,7 @@ "version": "7.26.5", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.26.5", @@ -2844,6 +2851,7 @@ "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, "funding": [ { "type": "opencollective", @@ -2876,6 +2884,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3015,6 +3024,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", @@ -3045,6 +3055,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -3148,6 +3159,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -3172,6 +3184,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.1", @@ -3280,23 +3293,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -3382,6 +3378,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" @@ -4010,6 +4007,7 @@ "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.26.0", @@ -7855,15 +7853,12 @@ } }, "node_modules/@koa/multer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@koa/multer/-/multer-3.0.2.tgz", - "integrity": "sha512-Q6WfPpE06mJWyZD1fzxM6zWywaoo+zocAn2YA9QYz4RsecoASr1h/kSzG0c5seDpFVKCMZM9raEfuM7XfqbRLw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@koa/multer/-/multer-3.1.0.tgz", + "integrity": "sha512-ETf4OLpOew9XE9lyU+5HIqk3TCmdGAw9pUXgxzrlYip+PkxLGoU4meiVTxiW4B6lxdBNijb3DFQ7M2woLcDL1g==", "license": "MIT", - "dependencies": { - "fix-esm": "1.0.1" - }, "engines": { - "node": ">= 8" + "node": ">= 14" }, "peerDependencies": { "multer": "*" @@ -15362,6 +15357,7 @@ "version": "4.23.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -15951,6 +15947,7 @@ "version": "1.0.30001717", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -18482,6 +18479,7 @@ "version": "1.5.151", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz", "integrity": "sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==", + "dev": true, "license": "ISC" }, "node_modules/electron-updater": { @@ -18965,6 +18963,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -20387,17 +20386,6 @@ "micromatch": "^4.0.2" } }, - "node_modules/fix-esm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fix-esm/-/fix-esm-1.0.1.tgz", - "integrity": "sha512-EZtb7wPXZS54GaGxaWxMlhd1DUDCnAg5srlYdu/1ZVeW+7wwR3Tp59nu52dXByFs3MBRq+SByx1wDOJpRvLEXw==", - "license": "WTFPL OR CC0-1.0", - "dependencies": { - "@babel/core": "^7.14.6", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.14.5" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -21084,6 +21072,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -25452,6 +25441,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -27032,6 +27022,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -29278,6 +29269,7 @@ "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, "license": "MIT" }, "node_modules/nopt": { @@ -37088,6 +37080,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -38970,6 +38963,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, "license": "ISC" }, "node_modules/yaml": { diff --git a/package.json b/package.json index 47cede513ed..2993707313f 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@bitwarden/sdk-internal": "0.2.0-main.159", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", - "@koa/multer": "3.0.2", + "@koa/multer": "3.1.0", "@koa/router": "13.1.0", "@microsoft/signalr": "8.0.7", "@microsoft/signalr-protocol-msgpack": "8.0.7", From 63b224f3dd08f692c14e18109fba4463062b5c63 Mon Sep 17 00:00:00 2001 From: Daniel Riera Date: Mon, 12 May 2025 17:03:09 -0400 Subject: [PATCH 33/35] PM-21454 Firefox - "null" text is showing in Add/Update Confirmation notification (#14745) * PM-21454 * Update apps/browser/src/autofill/content/components/lit-stories/mock-data.ts Co-authored-by: Jonathan Prusik * Update apps/browser/src/autofill/content/components/lit-stories/mock-data.ts Co-authored-by: Jonathan Prusik * Update apps/browser/src/autofill/content/components/notification/confirmation/container.ts Co-authored-by: Jonathan Prusik * run lint --------- Co-authored-by: Jonathan Prusik --- apps/browser/src/_locales/en/messages.json | 19 ++---- .../components/lit-stories/mock-data.ts | 4 +- .../notification/confirmation/container.ts | 9 ++- .../notification/confirmation/message.ts | 63 ++++++++++++------- apps/browser/src/autofill/notification/bar.ts | 6 +- 5 files changed, 57 insertions(+), 44 deletions(-) diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 57a0e78fd1b..361093b12ef 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1088,22 +1088,13 @@ } } }, - "loginSaveConfirmation": { - "message": "$ITEMNAME$ saved to Bitwarden.", - "placeholders": { - "itemName": { - "content": "$1" - } - }, + "notificationLoginSaveConfirmation": { + "message": "saved to Bitwarden.", + "description": "Shown to user after item is saved." }, - "loginUpdatedConfirmation": { - "message": "$ITEMNAME$ updated in Bitwarden.", - "placeholders": { - "itemName": { - "content": "$1" - } - }, + "notificationLoginUpdatedConfirmation": { + "message": "updated in Bitwarden.", "description": "Shown to user after item is updated." }, "saveAsNewLoginAction": { diff --git a/apps/browser/src/autofill/content/components/lit-stories/mock-data.ts b/apps/browser/src/autofill/content/components/lit-stories/mock-data.ts index b8e35813c6c..d134db3ca6f 100644 --- a/apps/browser/src/autofill/content/components/lit-stories/mock-data.ts +++ b/apps/browser/src/autofill/content/components/lit-stories/mock-data.ts @@ -107,9 +107,9 @@ export const mockI18n = { collection: "Collection", folder: "Folder", loginSaveSuccess: "Login saved", - loginSaveConfirmation: "$ITEMNAME$ saved to Bitwarden.", + notificationLoginSaveConfirmation: "saved to Bitwarden.", loginUpdateSuccess: "Login updated", - loginUpdatedConfirmation: "$ITEMNAME$ updated in Bitwarden.", + notificationLoginUpdatedConfirmation: "updated in Bitwarden.", loginUpdateTaskSuccess: "Great job! You took the steps to make you and $ORGANIZATION$ more secure.", loginUpdateTaskSuccessAdditional: diff --git a/apps/browser/src/autofill/content/components/notification/confirmation/container.ts b/apps/browser/src/autofill/content/components/notification/confirmation/container.ts index 7ad6b4542ec..d4d66c7a7be 100644 --- a/apps/browser/src/autofill/content/components/notification/confirmation/container.ts +++ b/apps/browser/src/autofill/content/components/notification/confirmation/container.ts @@ -113,9 +113,14 @@ function getConfirmationMessage(i18n: I18n, type?: NotificationType, error?: str if (error) { return i18n.saveFailureDetails; } + + /* @TODO This partial string return and later concatenation with the cipher name is needed + * to handle cipher name overflow cases, but is risky for i18n concerns. Fix concatenation + * with cipher name overflow when a tag replacement solution is available. + */ return type === NotificationTypes.Add - ? i18n.loginSaveConfirmation - : i18n.loginUpdatedConfirmation; + ? i18n.notificationLoginSaveConfirmation + : i18n.notificationLoginUpdatedConfirmation; } function getHeaderMessage(i18n: I18n, type?: NotificationType, error?: string) { diff --git a/apps/browser/src/autofill/content/components/notification/confirmation/message.ts b/apps/browser/src/autofill/content/components/notification/confirmation/message.ts index 527119aed15..2bf8caecfff 100644 --- a/apps/browser/src/autofill/content/components/notification/confirmation/message.ts +++ b/apps/browser/src/autofill/content/components/notification/confirmation/message.ts @@ -28,28 +28,31 @@ export function NotificationConfirmationMessage({