diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 8c08caec353..f7db6d78f21 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -2504,6 +2504,14 @@ "message": "Send saved", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, + "sendFilePopoutDialogText": { + "message": "Pop out extension?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFilePopoutDialogDesc": { + "message": "To create a file Send, you need to pop out te extension to a new window.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, "sendLinuxChromiumFileWarning": { "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." }, @@ -2513,6 +2521,9 @@ "sendSafariFileWarning": { "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." }, + "popOut": { + "message": "Pop out" + }, "sendFileCalloutHeader": { "message": "Before you start" }, @@ -4485,5 +4496,8 @@ }, "noEditPermissions": { "message": "You don't have permission to edit this item" + }, + "authenticating": { + "message": "Authenticating" } } diff --git a/apps/browser/src/autofill/background/overlay-notifications.background.ts b/apps/browser/src/autofill/background/overlay-notifications.background.ts index e252bdcc4af..ca8f05b77dc 100644 --- a/apps/browser/src/autofill/background/overlay-notifications.background.ts +++ b/apps/browser/src/autofill/background/overlay-notifications.background.ts @@ -6,6 +6,7 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { BrowserApi } from "../../platform/browser/browser-api"; +import { generateDomainMatchPatterns, isInvalidResponseStatusCode } from "../utils"; import { ActiveFormSubmissionRequests, @@ -109,35 +110,11 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg */ private getSenderUrlMatchPatterns(sender: chrome.runtime.MessageSender) { return new Set([ - ...this.generateMatchPatterns(sender.url), - ...this.generateMatchPatterns(sender.tab.url), + ...generateDomainMatchPatterns(sender.url), + ...generateDomainMatchPatterns(sender.tab.url), ]); } - /** - * Generates the origin and subdomain match patterns for the URL. - * - * @param url - The URL of the tab - */ - private generateMatchPatterns(url: string): string[] { - try { - if (!url.startsWith("http")) { - url = `https://${url}`; - } - - const originMatchPattern = `${new URL(url).origin}/*`; - - const parsedUrl = new URL(url); - const splitHost = parsedUrl.hostname.split("."); - const domain = splitHost.slice(-2).join("."); - const subDomainMatchPattern = `${parsedUrl.protocol}//*.${domain}/*`; - - return [originMatchPattern, subDomainMatchPattern]; - } catch { - return []; - } - } - /** * Stores the login form data that was modified by the user in the content script. This data is * used to trigger the add login or change password notification when the form is submitted. @@ -329,7 +306,7 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg private handleOnCompletedRequestEvent = async (details: chrome.webRequest.WebResponseDetails) => { if ( this.requestHostIsInvalid(details) || - this.isInvalidStatusCode(details.statusCode) || + isInvalidResponseStatusCode(details.statusCode) || !this.activeFormSubmissionRequests.has(details.requestId) ) { return; @@ -472,16 +449,6 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg this.setupWebRequestsListeners(); }; - /** - * Determines if the status code of the web response is invalid. An invalid status code is - * any status code that is not in the 200-299 range. - * - * @param statusCode - The status code of the web response - */ - private isInvalidStatusCode = (statusCode: number) => { - return statusCode < 200 || statusCode >= 300; - }; - /** * Determines if the host of the web request is invalid. An invalid host is any host that does not * start with "http" or a tab id that is less than 0. diff --git a/apps/browser/src/autofill/background/overlay.background.spec.ts b/apps/browser/src/autofill/background/overlay.background.spec.ts index 30f19e7260a..b6a04f63d54 100644 --- a/apps/browser/src/autofill/background/overlay.background.spec.ts +++ b/apps/browser/src/autofill/background/overlay.background.spec.ts @@ -61,6 +61,7 @@ import { triggerPortOnDisconnectEvent, triggerPortOnMessageEvent, triggerWebNavigationOnCommittedEvent, + triggerWebRequestOnCompletedEvent, } from "../spec/testing-utils"; import { @@ -3003,37 +3004,95 @@ describe("OverlayBackground", () => { expect(copyToClipboardSpy).toHaveBeenCalledWith("totp-code"); }); - it("triggers passkey authentication through mediated conditional UI", async () => { - const fido2Credential = mock({ credentialId: "credential-id" }); - const cipher1 = mock({ - id: "inline-menu-cipher-1", - login: { - username: "username1", - password: "password1", - fido2Credentials: [fido2Credential], - }, - }); - overlayBackground["inlineMenuCiphers"] = new Map([["inline-menu-cipher-1", cipher1]]); - const pageDetailsForTab = { - frameId: sender.frameId, - tab: sender.tab, - details: pageDetails, - }; - overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([ - [sender.frameId, pageDetailsForTab], - ]); - autofillService.isPasswordRepromptRequired.mockResolvedValue(false); - jest.spyOn(fido2ActiveRequestManager, "getActiveRequest"); + describe("triggering passkey authentication", () => { + let cipher1: CipherView; - sendPortMessage(listMessageConnectorSpy, { - command: "fillAutofillInlineMenuCipher", - inlineMenuCipherId: "inline-menu-cipher-1", - usePasskey: true, - portKey, + beforeEach(() => { + const fido2Credential = mock({ credentialId: "credential-id" }); + cipher1 = mock({ + id: "inline-menu-cipher-1", + login: { + username: "username1", + password: "password1", + fido2Credentials: [fido2Credential], + }, + }); + const pageDetailsForTab = { + frameId: sender.frameId, + tab: sender.tab, + details: pageDetails, + }; + overlayBackground["inlineMenuCiphers"] = new Map([["inline-menu-cipher-1", cipher1]]); + overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([ + [sender.frameId, pageDetailsForTab], + ]); + autofillService.isPasswordRepromptRequired.mockResolvedValue(false); }); - await flushPromises(); - expect(fido2ActiveRequestManager.getActiveRequest).toHaveBeenCalledWith(sender.tab.id); + it("logs an error if the authentication could not complete due to a missing FIDO2 request", async () => { + jest.spyOn(logService, "error"); + + sendPortMessage(listMessageConnectorSpy, { + command: "fillAutofillInlineMenuCipher", + inlineMenuCipherId: "inline-menu-cipher-1", + usePasskey: true, + portKey, + }); + await flushPromises(); + + expect(logService.error).toHaveBeenCalled(); + }); + + describe("when the FIDO2 request is present", () => { + beforeEach(async () => { + void fido2ActiveRequestManager.newActiveRequest( + sender.tab.id, + cipher1.login.fido2Credentials, + new AbortController(), + ); + }); + + it("aborts all active FIDO2 requests if the subsequent request after the authentication is invalid", async () => { + jest.spyOn(fido2ActiveRequestManager, "removeActiveRequest"); + + sendPortMessage(listMessageConnectorSpy, { + command: "fillAutofillInlineMenuCipher", + inlineMenuCipherId: "inline-menu-cipher-1", + usePasskey: true, + portKey, + }); + await flushPromises(); + triggerWebRequestOnCompletedEvent( + mock({ + statusCode: 401, + }), + ); + + expect(fido2ActiveRequestManager.removeActiveRequest).toHaveBeenCalled(); + }); + + it("triggers a closure of the inline menu if the subsequent request after the authentication is valid", async () => { + jest.useFakeTimers(); + + await initOverlayElementPorts(); + sendPortMessage(listMessageConnectorSpy, { + command: "fillAutofillInlineMenuCipher", + inlineMenuCipherId: "inline-menu-cipher-1", + usePasskey: true, + portKey, + }); + triggerWebRequestOnCompletedEvent( + mock({ + statusCode: 200, + }), + ); + jest.advanceTimersByTime(3100); + + expect(listPortSpy.postMessage).toHaveBeenCalledWith({ + command: "triggerDelayedAutofillInlineMenuClosure", + }); + }); + }); }); }); diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index c8d250df509..653d31ca52c 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -55,7 +55,11 @@ import { MAX_SUB_FRAME_DEPTH, } from "../enums/autofill-overlay.enum"; import { AutofillService } from "../services/abstractions/autofill.service"; -import { generateRandomChars } from "../utils"; +import { + generateDomainMatchPatterns, + generateRandomChars, + isInvalidResponseStatusCode, +} from "../utils"; import { LockedVaultPendingNotificationsData } from "./abstractions/notification.background"; import { @@ -151,7 +155,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { addEditCipherSubmitted: () => this.updateOverlayCiphers(), editedCipher: () => this.updateOverlayCiphers(), deletedCipher: () => this.updateOverlayCiphers(), - fido2AbortRequest: ({ sender }) => this.abortFido2ActiveRequest(sender), + fido2AbortRequest: ({ sender }) => this.abortFido2ActiveRequest(sender.tab.id), }; private readonly inlineMenuButtonPortMessageHandlers: InlineMenuButtonPortMessageHandlers = { triggerDelayedAutofillInlineMenuClosure: () => this.triggerDelayedInlineMenuClosure(), @@ -672,10 +676,10 @@ export class OverlayBackground implements OverlayBackgroundInterface { /** * Aborts an active FIDO2 request for a given tab and updates the inline menu ciphers. * - * @param sender - The sender of the message + * @param tabId - The id of the tab to abort the request for */ - private async abortFido2ActiveRequest(sender: chrome.runtime.MessageSender) { - this.fido2ActiveRequestManager.removeActiveRequest(sender.tab.id); + private async abortFido2ActiveRequest(tabId: number) { + this.fido2ActiveRequestManager.removeActiveRequest(tabId); await this.updateOverlayCiphers(false); } @@ -939,11 +943,10 @@ export class OverlayBackground implements OverlayBackgroundInterface { if (usePasskey && cipher.login?.hasFido2Credentials) { await this.authenticatePasskeyCredential( - sender.tab.id, + sender, cipher.login.fido2Credentials[0].credentialId, ); this.updateLastUsedInlineMenuCipher(inlineMenuCipherId, cipher); - this.closeInlineMenu(sender, { forceCloseInlineMenu: true }); return; } @@ -969,11 +972,11 @@ export class OverlayBackground implements OverlayBackgroundInterface { /** * Triggers a FIDO2 authentication from the inline menu using the passed credential ID. * - * @param tabId - The tab ID to trigger the authentication for + * @param sender - The sender of the port message * @param credentialId - The credential ID to authenticate */ - async authenticatePasskeyCredential(tabId: number, credentialId: string) { - const request = this.fido2ActiveRequestManager.getActiveRequest(tabId); + async authenticatePasskeyCredential(sender: chrome.runtime.MessageSender, credentialId: string) { + const request = this.fido2ActiveRequestManager.getActiveRequest(sender.tab.id); if (!request) { this.logService.error( "Could not complete passkey autofill due to missing active Fido2 request", @@ -981,9 +984,35 @@ export class OverlayBackground implements OverlayBackgroundInterface { return; } + chrome.webRequest.onCompleted.addListener(this.handlePasskeyAuthenticationOnCompleted, { + urls: generateDomainMatchPatterns(sender.tab.url), + }); request.subject.next({ type: Fido2ActiveRequestEvents.Continue, credentialId }); } + /** + * Handles the next web request that occurs after a passkey authentication has been completed. + * Ensures that the inline menu closes after the request, and that the FIDO2 request is aborted + * if the request is not successful. + * + * @param details - The web request details + */ + private handlePasskeyAuthenticationOnCompleted = ( + details: chrome.webRequest.WebResponseCacheDetails, + ) => { + chrome.webRequest.onCompleted.removeListener(this.handlePasskeyAuthenticationOnCompleted); + + if (isInvalidResponseStatusCode(details.statusCode)) { + this.closeInlineMenu({ tab: { id: details.tabId } } as chrome.runtime.MessageSender, { + forceCloseInlineMenu: true, + }); + this.abortFido2ActiveRequest(details.tabId).catch((error) => this.logService.error(error)); + return; + } + + globalThis.setTimeout(() => this.triggerDelayedInlineMenuClosure(), 3000); + }; + /** * Sets the most recently used cipher at the top of the list of ciphers. * @@ -1587,6 +1616,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { passkeys: this.i18nService.translate("passkeys"), passwords: this.i18nService.translate("passwords"), logInWithPasskey: this.i18nService.translate("logInWithPasskeyAriaLabel"), + authenticating: this.i18nService.translate("authenticating"), }; } diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/list/__snapshots__/autofill-inline-menu-list.spec.ts.snap b/apps/browser/src/autofill/overlay/inline-menu/pages/list/__snapshots__/autofill-inline-menu-list.spec.ts.snap index 3339781fabf..0a4ae8d795f 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/list/__snapshots__/autofill-inline-menu-list.spec.ts.snap +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/list/__snapshots__/autofill-inline-menu-list.spec.ts.snap @@ -2131,6 +2131,44 @@ exports[`AutofillInlineMenuList initAutofillInlineMenuList the list of ciphers f `; +exports[`AutofillInlineMenuList initAutofillInlineMenuList the list of ciphers for an authenticated user fill cipher button event listeners filling a cipher displays an \`Authenticating\` loader when a passkey cipher is filled 1`] = ` +
+
+ +
+
+`; + exports[`AutofillInlineMenuList initAutofillInlineMenuList the locked inline menu for an unauthenticated user creates the views for the locked inline menu 1`] = `
{ postWindowMessage(createInitAutofillInlineMenuListMessageMock({ portKey })); }); - it("allows the user to fill a cipher on click", () => { - const fillCipherButton = - autofillInlineMenuList["inlineMenuListContainer"].querySelector(".fill-cipher-button"); + describe("filling a cipher", () => { + it("allows the user to fill a cipher on click", () => { + const fillCipherButton = + autofillInlineMenuList["inlineMenuListContainer"].querySelector( + ".fill-cipher-button", + ); - fillCipherButton.dispatchEvent(new Event("click")); + fillCipherButton.dispatchEvent(new Event("click")); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { - command: "fillAutofillInlineMenuCipher", - inlineMenuCipherId: "1", - usePasskey: false, - portKey, - }, - "*", - ); + expect(globalThis.parent.postMessage).toHaveBeenCalledWith( + { + command: "fillAutofillInlineMenuCipher", + inlineMenuCipherId: "1", + usePasskey: false, + portKey, + }, + "*", + ); + }); + + it("displays an `Authenticating` loader when a passkey cipher is filled", async () => { + postWindowMessage( + createInitAutofillInlineMenuListMessageMock({ + ciphers: [ + createAutofillOverlayCipherDataMock(1, { + name: "https://example.com", + login: { + username: "username1", + passkey: { + rpName: "https://example.com", + userName: "username1", + }, + }, + }), + ], + showPasskeysLabels: true, + portKey, + }), + ); + await flushPromises(); + + const fillCipherButton = + autofillInlineMenuList["inlineMenuListContainer"].querySelector( + ".fill-cipher-button", + ); + + fillCipherButton.dispatchEvent(new Event("click")); + + expect(autofillInlineMenuList["inlineMenuListContainer"]).toMatchSnapshot(); + }); }); it("allows the user to move keyboard focus to the next cipher element on ArrowDown", () => { diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts b/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts index da8cbdd200f..27a9c68d995 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts @@ -14,6 +14,7 @@ import { plusIcon, viewCipherIcon, passkeyIcon, + spinnerIcon, } from "../../../../utils/svg-icons"; import { AutofillInlineMenuListWindowMessageHandlers, @@ -40,6 +41,7 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { private passkeysHeadingHeight: number; private lastPasskeysListItemHeight: number; private ciphersListHeight: number; + private isPasskeyAuthInProgress = false; private readonly showCiphersPerPage = 6; private readonly headingBorderClass = "inline-menu-list-heading--bordered"; private readonly inlineMenuListWindowMessageHandlers: AutofillInlineMenuListWindowMessageHandlers = @@ -156,15 +158,14 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { ciphers: InlineMenuCipherData[], showInlineMenuAccountCreation?: boolean, ) { + if (this.isPasskeyAuthInProgress) { + return; + } + this.ciphers = ciphers; this.currentCipherIndex = 0; this.showInlineMenuAccountCreation = showInlineMenuAccountCreation; - if (this.inlineMenuListContainer) { - this.inlineMenuListContainer.innerHTML = ""; - this.inlineMenuListContainer.classList.remove( - "inline-menu-list-container--with-new-item-button", - ); - } + this.resetInlineMenuContainer(); if (!ciphers?.length) { this.buildNoResultsInlineMenuList(); @@ -191,6 +192,18 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { this.newItemButtonElement.addEventListener(EVENTS.KEYUP, this.handleNewItemButtonKeyUpEvent); } + /** + * Clears and resets the inline menu list container. + */ + private resetInlineMenuContainer() { + if (this.inlineMenuListContainer) { + this.inlineMenuListContainer.innerHTML = ""; + this.inlineMenuListContainer.classList.remove( + "inline-menu-list-container--with-new-item-button", + ); + } + } + /** * Inline menu view that is presented when no ciphers are found for a given page. * Facilitates the ability to add a new vault item from the inline menu. @@ -330,7 +343,7 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { this.ciphersList.addEventListener( EVENTS.SCROLL, this.useEventHandlersMemo( - throttle(() => this.updatePasskeysHeadingsOnScroll(this.ciphersList.scrollTop), 50), + throttle(this.handleThrottledOnScrollEvent, 50), UPDATE_PASSKEYS_HEADINGS_ON_SCROLL, ), options, @@ -342,7 +355,10 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { * Handles updating the list of ciphers when the * user scrolls to the bottom of the list. */ - private updateCiphersListOnScroll = () => { + private updateCiphersListOnScroll = (event: MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + if (this.cipherListScrollIsDebounced) { return; } @@ -382,6 +398,18 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { } }; + /** + * Throttled handler for updating the passkeys and login headings when the user scrolls the ciphers list. + * + * @param event - The scroll event. + */ + private handleThrottledOnScrollEvent = (event: MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + + this.updatePasskeysHeadingsOnScroll(this.ciphersList.scrollTop); + }; + /** * Updates the passkeys and login headings when the user scrolls the ciphers list. * @@ -596,16 +624,29 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { private handleFillCipherClickEvent = (cipher: InlineMenuCipherData) => { const usePasskey = !!cipher.login?.passkey; return this.useEventHandlersMemo( - () => - this.postMessageToParent({ - command: "fillAutofillInlineMenuCipher", - inlineMenuCipherId: cipher.id, - usePasskey, - }), + () => this.triggerFillCipherClickEvent(cipher, usePasskey), `${cipher.id}-fill-cipher-button-click-handler-${usePasskey ? "passkey" : ""}`, ); }; + /** + * Triggers a fill of the currently selected cipher. + * + * @param cipher - The cipher to fill. + * @param usePasskey - Whether the cipher uses a passkey. + */ + private triggerFillCipherClickEvent = (cipher: InlineMenuCipherData, usePasskey: boolean) => { + if (usePasskey) { + this.createPasskeyAuthenticatingLoader(); + } + + this.postMessageToParent({ + command: "fillAutofillInlineMenuCipher", + inlineMenuCipherId: cipher.id, + usePasskey, + }); + }; + /** * Handles the keyup event for the fill cipher button. Facilitates * selecting the next/previous cipher item on ArrowDown/ArrowUp. Also @@ -889,6 +930,26 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement { return cipherDetailsElement; } + /** + * Creates an indicator for the user that the passkey is being authenticated. + */ + private createPasskeyAuthenticatingLoader() { + this.isPasskeyAuthInProgress = true; + this.resetInlineMenuContainer(); + + const passkeyAuthenticatingLoader = globalThis.document.createElement("div"); + passkeyAuthenticatingLoader.classList.add("passkey-authenticating-loader"); + passkeyAuthenticatingLoader.textContent = this.getTranslation("authenticating"); + passkeyAuthenticatingLoader.appendChild(buildSvgDomElement(spinnerIcon)); + + this.inlineMenuListContainer.appendChild(passkeyAuthenticatingLoader); + + globalThis.setTimeout(() => { + this.isPasskeyAuthInProgress = false; + this.postMessageToParent({ command: "checkAutofillInlineMenuButtonFocused" }); + }, 4000); + } + /** * Gets the subtitle text for a given cipher. * diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/list/list.scss b/apps/browser/src/autofill/overlay/inline-menu/pages/list/list.scss index 9cd8ae1a73c..fb12da78f48 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/list/list.scss +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/list/list.scss @@ -15,6 +15,8 @@ body { width: 100%; padding: 0; margin: 0; + font-family: $font-family-sans-serif; + font-weight: 400; @include themify($themes) { color: themed("textColor"); @@ -23,8 +25,6 @@ body { } .inline-menu-list-message { - font-family: $font-family-sans-serif; - font-weight: 400; font-size: 1.4rem; line-height: 1.5; width: 100%; @@ -393,3 +393,38 @@ body { } } } + +@keyframes bwi-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} + +.passkey-authenticating-loader { + display: flex; + align-content: center; + align-items: center; + justify-content: center; + text-align: center; + padding: 1rem 0.8rem; + font-size: 1.4rem; + font-weight: 400; + + @include themify($themes) { + color: themed("passkeysAuthenticating"); + } + + svg { + animation: bwi-spin 2s infinite linear; + margin-left: 1rem; + + path { + @include themify($themes) { + fill: themed("passkeysAuthenticating") !important; + } + } + } +} diff --git a/apps/browser/src/autofill/services/autofill.service.ts b/apps/browser/src/autofill/services/autofill.service.ts index 5d9bfa9f9d4..cd49da72194 100644 --- a/apps/browser/src/autofill/services/autofill.service.ts +++ b/apps/browser/src/autofill/services/autofill.service.ts @@ -3017,9 +3017,11 @@ export default class AutofillService implements AutofillServiceInterface { const tabs = await BrowserApi.tabsQuery({}); for (let index = 0; index < tabs.length; index++) { const tab = tabs[index]; - if (tab.url?.startsWith("http")) { + if (tab?.id && tab.url?.startsWith("http")) { const frames = await BrowserApi.getAllFrameDetails(tab.id); - frames.forEach((frame) => this.injectAutofillScripts(tab, frame.frameId, false)); + if (frames) { + frames.forEach((frame) => this.injectAutofillScripts(tab, frame.frameId, false)); + } } } } diff --git a/apps/browser/src/autofill/shared/styles/variables.scss b/apps/browser/src/autofill/shared/styles/variables.scss index 41d38c0b666..ec718451270 100644 --- a/apps/browser/src/autofill/shared/styles/variables.scss +++ b/apps/browser/src/autofill/shared/styles/variables.scss @@ -10,6 +10,7 @@ $border-color: #ced4dc; $border-color-dark: #ddd; $border-radius: 3px; $focus-outline-color: #1252a3; +$muted-blue: #5a6d91; $brand-primary: #175ddc; @@ -45,6 +46,7 @@ $themes: ( focusOutlineColor: $focus-outline-color, successColor: $success-color-light, errorColor: $error-color-light, + passkeysAuthenticating: $muted-blue, ), dark: ( textColor: #ffffff, @@ -60,6 +62,7 @@ $themes: ( focusOutlineColor: lighten($focus-outline-color, 25%), successColor: $success-color-dark, errorColor: $error-color-dark, + passkeysAuthenticating: #bac0ce, ), nord: ( textColor: $nord5, @@ -74,6 +77,7 @@ $themes: ( borderColor: $nord0, focusOutlineColor: lighten($focus-outline-color, 25%), successColor: $success-color-dark, + passkeysAuthenticating: $nord4, ), solarizedDark: ( textColor: $solarizedDarkBase2, @@ -89,6 +93,7 @@ $themes: ( borderColor: $solarizedDarkBase2, focusOutlineColor: lighten($focus-outline-color, 15%), successColor: $success-color-dark, + passkeysAuthenticating: $solarizedDarkBase2, ), ); diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts index 98c0a97ac56..f2fafac3d8c 100644 --- a/apps/browser/src/autofill/utils/index.ts +++ b/apps/browser/src/autofill/utils/index.ts @@ -426,3 +426,50 @@ export function getSubmitButtonKeywordsSet(element: HTMLElement): Set { return keywordsSet; } + +/** + * Generates the origin and subdomain match patterns for the URL. + * + * @param url - The URL of the tab + */ +export function generateDomainMatchPatterns(url: string): string[] { + try { + const extensionUrlPattern = + /^(chrome|chrome-extension|moz-extension|safari-web-extension):\/\/\/?/; + if (extensionUrlPattern.test(url)) { + return []; + } + + // Add protocol to URL if it is missing to allow for parsing the hostname correctly + const urlPattern = /^(https?|file):\/\/\/?/; + if (!urlPattern.test(url)) { + url = `https://${url}`; + } + + let protocolGlob = "*://"; + if (url.startsWith("file:///")) { + protocolGlob = "*:///"; // File URLs require three slashes to be a valid match pattern + } + + const parsedUrl = new URL(url); + const originMatchPattern = `${protocolGlob}${parsedUrl.hostname}/*`; + + const splitHost = parsedUrl.hostname.split("."); + const domain = splitHost.slice(-2).join("."); + const subDomainMatchPattern = `${protocolGlob}*.${domain}/*`; + + return [originMatchPattern, subDomainMatchPattern]; + } catch { + return []; + } +} + +/** + * Determines if the status code of the web response is invalid. An invalid status code is + * any status code that is not in the 200-299 range. + * + * @param statusCode - The status code of the web response + */ +export function isInvalidResponseStatusCode(statusCode: number) { + return statusCode < 200 || statusCode >= 300; +} diff --git a/apps/browser/src/autofill/utils/svg-icons.ts b/apps/browser/src/autofill/utils/svg-icons.ts index df2cfa189f9..908e57f2cba 100644 --- a/apps/browser/src/autofill/utils/svg-icons.ts +++ b/apps/browser/src/autofill/utils/svg-icons.ts @@ -27,3 +27,6 @@ export const passkeyIcon = export const circleCheckIcon = ''; + +export const spinnerIcon = + ''; diff --git a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts index f0d92c6f682..bf53b23c373 100644 --- a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts +++ b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts @@ -3,7 +3,9 @@ import { Component, importProvidersFrom } from "@angular/core"; import { RouterModule } from "@angular/router"; import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/angular"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; import { AvatarModule, BadgeModule, @@ -318,6 +320,30 @@ export default { }); }, }, + { + provide: PolicyService, + useFactory: () => { + return { + policyAppliesToActiveUser$: () => { + return { + pipe: () => ({ + subscribe: () => ({}), + }), + }; + }, + }; + }, + }, + { + provide: SendService, + useFactory: () => { + return { + sends$: () => { + return { pipe: () => ({}) }; + }, + }; + }, + }, ], }), applicationConfig({ diff --git a/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts b/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts index ced3f6462e9..8463bbe6e9f 100644 --- a/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts +++ b/apps/browser/src/platform/popup/layout/popup-tab-navigation.component.ts @@ -1,9 +1,41 @@ import { CommonModule } from "@angular/common"; import { Component } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { RouterModule } from "@angular/router"; +import { filter, map, switchMap } from "rxjs"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { PolicyType } from "@bitwarden/common/admin-console/enums"; +import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction"; import { LinkModule } from "@bitwarden/components"; +const allNavButtons = [ + { + label: "Vault", + page: "/tabs/vault", + iconKey: "lock", + iconKeyActive: "lock-f", + }, + { + label: "Generator", + page: "/tabs/generator", + iconKey: "generate", + iconKeyActive: "generate-f", + }, + { + label: "Send", + page: "/tabs/send", + iconKey: "send", + iconKeyActive: "send-f", + }, + { + label: "Settings", + page: "/tabs/settings", + iconKey: "cog", + iconKeyActive: "cog-f", + }, +]; + @Component({ selector: "popup-tab-navigation", templateUrl: "popup-tab-navigation.component.html", @@ -14,30 +46,23 @@ import { LinkModule } from "@bitwarden/components"; }, }) export class PopupTabNavigationComponent { - navButtons = [ - { - label: "Vault", - page: "/tabs/vault", - iconKey: "lock", - iconKeyActive: "lock-f", - }, - { - label: "Generator", - page: "/tabs/generator", - iconKey: "generate", - iconKeyActive: "generate-f", - }, - { - label: "Send", - page: "/tabs/send", - iconKey: "send", - iconKeyActive: "send-f", - }, - { - label: "Settings", - page: "/tabs/settings", - iconKey: "cog", - iconKeyActive: "cog-f", - }, - ]; + navButtons = allNavButtons; + constructor( + private policyService: PolicyService, + private sendService: SendService, + ) { + this.policyService + .policyAppliesToActiveUser$(PolicyType.DisableSend) + .pipe( + filter((policyAppliesToActiveUser) => policyAppliesToActiveUser), + switchMap(() => this.sendService.sends$), + map((sends) => sends.length > 1), + takeUntilDestroyed(), + ) + .subscribe((hasSends) => { + this.navButtons = hasSends + ? allNavButtons + : allNavButtons.filter((b) => b.page !== "/tabs/send"); + }); + } } diff --git a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.html b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.html index 7f723cc7364..e96a0742a03 100644 --- a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.html +++ b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.html @@ -9,6 +9,8 @@ > + + + + + diff --git a/apps/browser/src/tools/popup/send-v2/send-file-popout-dialog/send-file-popout-dialog.component.ts b/apps/browser/src/tools/popup/send-v2/send-file-popout-dialog/send-file-popout-dialog.component.ts new file mode 100644 index 00000000000..fb21b5bb026 --- /dev/null +++ b/apps/browser/src/tools/popup/send-v2/send-file-popout-dialog/send-file-popout-dialog.component.ts @@ -0,0 +1,25 @@ +import { CommonModule } from "@angular/common"; +import { Component } from "@angular/core"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { ButtonModule, DialogModule, DialogService, TypographyModule } from "@bitwarden/components"; + +import BrowserPopupUtils from "../../../../platform/popup/browser-popup-utils"; + +@Component({ + selector: "send-file-popout-dialog", + templateUrl: "./send-file-popout-dialog.component.html", + standalone: true, + imports: [JslibModule, CommonModule, DialogModule, ButtonModule, TypographyModule], +}) +export class SendFilePopoutDialogComponent { + constructor(private dialogService: DialogService) {} + + async popOutWindow() { + await BrowserPopupUtils.openCurrentPagePopout(window); + } + + close() { + this.dialogService.closeAll(); + } +} diff --git a/apps/browser/src/tools/popup/send-v2/send-v2.component.html b/apps/browser/src/tools/popup/send-v2/send-v2.component.html index a8dd3e24f29..698901d8460 100644 --- a/apps/browser/src/tools/popup/send-v2/send-v2.component.html +++ b/apps/browser/src/tools/popup/send-v2/send-v2.component.html @@ -1,12 +1,20 @@ - - + +
+ + {{ "sendDisabledWarning" | i18n }} + + + + + +
{{ "sendsNoItemsTitle" | i18n }} {{ "sendsNoItemsMessage" | i18n }} - +
@@ -31,9 +39,4 @@
- -
- - -
diff --git a/apps/browser/src/tools/popup/send-v2/send-v2.component.spec.ts b/apps/browser/src/tools/popup/send-v2/send-v2.component.spec.ts index 50e5531743a..63e3c2d2fc6 100644 --- a/apps/browser/src/tools/popup/send-v2/send-v2.component.spec.ts +++ b/apps/browser/src/tools/popup/send-v2/send-v2.component.spec.ts @@ -7,6 +7,7 @@ import { of, BehaviorSubject } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { SearchService } from "@bitwarden/common/abstractions/search.service"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service"; @@ -46,6 +47,7 @@ describe("SendV2Component", () => { let sendListFiltersServiceFilters$: BehaviorSubject<{ sendType: SendType | null }>; let sendItemsServiceEmptyList$: BehaviorSubject; let sendItemsServiceNoFilteredResults$: BehaviorSubject; + let policyService: MockProxy; beforeEach(async () => { sendListFiltersServiceFilters$ = new BehaviorSubject({ sendType: null }); @@ -60,6 +62,9 @@ describe("SendV2Component", () => { latestSearchText$: of(""), }); + policyService = mock(); + policyService.policyAppliesToActiveUser$.mockReturnValue(of(true)); // Return `true` by default + sendListFiltersService = new SendListFiltersService(mock(), new FormBuilder()); sendListFiltersService.filters$ = sendListFiltersServiceFilters$; @@ -104,6 +109,7 @@ describe("SendV2Component", () => { { provide: I18nService, useValue: { t: (key: string) => key } }, { provide: SendListFiltersService, useValue: sendListFiltersService }, { provide: PopupRouterCacheService, useValue: mock() }, + { provide: PolicyService, useValue: policyService }, ], }).compileComponents(); diff --git a/apps/browser/src/tools/popup/send-v2/send-v2.component.ts b/apps/browser/src/tools/popup/send-v2/send-v2.component.ts index 5c1ec89fde9..26a995e8c4c 100644 --- a/apps/browser/src/tools/popup/send-v2/send-v2.component.ts +++ b/apps/browser/src/tools/popup/send-v2/send-v2.component.ts @@ -5,8 +5,10 @@ import { RouterLink } from "@angular/router"; import { combineLatest } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { SendType } from "@bitwarden/common/tools/send/enums/send-type"; -import { ButtonModule, Icons, NoItemsModule } from "@bitwarden/components"; +import { ButtonModule, CalloutModule, Icons, NoItemsModule } from "@bitwarden/components"; import { NoSendsIcon, NewSendDropdownComponent, @@ -31,6 +33,7 @@ export enum SendState { templateUrl: "send-v2.component.html", standalone: true, imports: [ + CalloutModule, PopupPageComponent, PopupHeaderComponent, PopOutComponent, @@ -48,22 +51,20 @@ export enum SendState { }) export class SendV2Component implements OnInit, OnDestroy { sendType = SendType; - sendState = SendState; protected listState: SendState | null = null; - protected sends$ = this.sendItemsService.filteredAndSortedSends$; - protected title: string = "allSends"; - protected noItemIcon = NoSendsIcon; - protected noResultsIcon = Icons.NoResults; + protected sendsDisabled = false; + constructor( protected sendItemsService: SendItemsService, protected sendListFiltersService: SendListFiltersService, + private policyService: PolicyService, ) { combineLatest([ this.sendItemsService.emptyList$, @@ -90,6 +91,13 @@ export class SendV2Component implements OnInit, OnDestroy { this.listState = null; }); + + this.policyService + .policyAppliesToActiveUser$(PolicyType.DisableSend) + .pipe(takeUntilDestroyed()) + .subscribe((sendsDisabled) => { + this.sendsDisabled = sendsDisabled; + }); } ngOnInit(): void {} diff --git a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.ts b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.ts index 0f05480ea12..7cdb691d56c 100644 --- a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.ts +++ b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.ts @@ -38,7 +38,7 @@ export class MoreFromBitwardenPageV2Component { private organizationService: OrganizationService, ) { this.canAccessPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$; - this.familySponsorshipAvailable$ = this.organizationService.canManageSponsorships$; + this.familySponsorshipAvailable$ = this.organizationService.familySponsorshipAvailable$; } async openFreeBitwardenFamiliesPage() { 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 a02713c53f0..107447c50ac 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 @@ -14,6 +14,7 @@ import { EventType } from "@bitwarden/common/enums"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { ViewPasswordHistoryService } from "@bitwarden/common/vault/abstractions/view-password-history.service"; import { CipherType } from "@bitwarden/common/vault/enums"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; @@ -30,20 +31,19 @@ import { import { PremiumUpgradePromptService } from "../../../../../../../../libs/common/src/vault/abstractions/premium-upgrade-prompt.service"; import { CipherViewComponent } from "../../../../../../../../libs/vault/src/cipher-view"; import { PopOutComponent } from "../../../../../platform/popup/components/pop-out.component"; -import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component"; -import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component"; -import { PopupPageComponent } from "../../../../../platform/popup/layout/popup-page.component"; import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service"; import { BrowserPremiumUpgradePromptService } from "../../../services/browser-premium-upgrade-prompt.service"; -import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service"; +import { BrowserViewPasswordHistoryService } from "../../../services/browser-view-password-history.service"; + +import { PopupFooterComponent } from "./../../../../../platform/popup/layout/popup-footer.component"; +import { PopupHeaderComponent } from "./../../../../../platform/popup/layout/popup-header.component"; +import { PopupPageComponent } from "./../../../../../platform/popup/layout/popup-page.component"; +import { VaultPopupAutofillService } from "./../../../services/vault-popup-autofill.service"; @Component({ selector: "app-view-v2", templateUrl: "view-v2.component.html", standalone: true, - providers: [ - { provide: PremiumUpgradePromptService, useClass: BrowserPremiumUpgradePromptService }, - ], imports: [ CommonModule, SearchModule, @@ -58,6 +58,10 @@ import { VaultPopupAutofillService } from "../../../services/vault-popup-autofil AsyncActionsModule, PopOutComponent, ], + providers: [ + { provide: ViewPasswordHistoryService, useClass: BrowserViewPasswordHistoryService }, + { provide: PremiumUpgradePromptService, useClass: BrowserPremiumUpgradePromptService }, + ], }) export class ViewV2Component { headerText: string; diff --git a/apps/browser/src/vault/popup/services/browser-view-password-history.service.spec.ts b/apps/browser/src/vault/popup/services/browser-view-password-history.service.spec.ts new file mode 100644 index 00000000000..ded4686477e --- /dev/null +++ b/apps/browser/src/vault/popup/services/browser-view-password-history.service.spec.ts @@ -0,0 +1,28 @@ +import { TestBed } from "@angular/core/testing"; +import { Router } from "@angular/router"; +import { mock, MockProxy } from "jest-mock-extended"; + +import { BrowserViewPasswordHistoryService } from "./browser-view-password-history.service"; + +describe("BrowserViewPasswordHistoryService", () => { + let service: BrowserViewPasswordHistoryService; + let router: MockProxy; + + beforeEach(async () => { + router = mock(); + await TestBed.configureTestingModule({ + providers: [BrowserViewPasswordHistoryService, { provide: Router, useValue: router }], + }).compileComponents(); + + service = TestBed.inject(BrowserViewPasswordHistoryService); + }); + + describe("viewPasswordHistory", () => { + it("navigates to the password history screen", async () => { + await service.viewPasswordHistory("test"); + expect(router.navigate).toHaveBeenCalledWith(["/cipher-password-history"], { + queryParams: { cipherId: "test" }, + }); + }); + }); +}); diff --git a/apps/browser/src/vault/popup/services/browser-view-password-history.service.ts b/apps/browser/src/vault/popup/services/browser-view-password-history.service.ts new file mode 100644 index 00000000000..6b57b0b625e --- /dev/null +++ b/apps/browser/src/vault/popup/services/browser-view-password-history.service.ts @@ -0,0 +1,18 @@ +import { inject } from "@angular/core"; +import { Router } from "@angular/router"; + +import { ViewPasswordHistoryService } from "@bitwarden/common/vault/abstractions/view-password-history.service"; + +/** + * This class handles the premium upgrade process for the browser extension. + */ +export class BrowserViewPasswordHistoryService implements ViewPasswordHistoryService { + private router = inject(Router); + + /** + * Navigates to the password history screen. + */ + async viewPasswordHistory(cipherId: string) { + await this.router.navigate(["/cipher-password-history"], { queryParams: { cipherId } }); + } +} diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock index 603feabe136..347f8dd3f4f 100644 --- a/apps/desktop/desktop_native/Cargo.lock +++ b/apps/desktop/desktop_native/Cargo.lock @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" dependencies = [ "async-task", "concurrent-queue", @@ -139,9 +139,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", "async-io", @@ -154,7 +154,6 @@ dependencies = [ "futures-lite", "rustix", "tracing", - "windows-sys 0.59.0", ] [[package]] @@ -194,9 +193,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -290,9 +289,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cbc" @@ -305,9 +304,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -405,9 +404,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -603,9 +602,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" [[package]] name = "event-listener" @@ -1074,9 +1073,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cd81b794fc1d6051acf8c4f3cb4f82833b0621272a232b4ff0cf3df1dbddb61" +checksum = "967c485e00f0bf3b1bdbe510a38a4606919cf1d34d9a37ad41f25a81aa077abe" dependencies = [ "convert_case", "once_cell", @@ -1277,9 +1276,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -1339,9 +1338,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" @@ -1387,9 +1386,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.34.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] @@ -1435,9 +1434,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "62871f2d65009c0256aed1b9cfeeb8ac272833c404e13d53d400cd0dad7a2ac0" dependencies = [ "bitflags", ] @@ -1548,18 +1547,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1763,9 +1762,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -1838,21 +1837,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "version-compare" @@ -1874,9 +1873,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wayland-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", @@ -1888,9 +1887,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.5" +version = "0.31.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943" +checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" dependencies = [ "bitflags", "rustix", @@ -1925,9 +1924,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" dependencies = [ "proc-macro2", "quick-xml", @@ -1936,9 +1935,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" dependencies = [ "dlib", "log", @@ -2176,9 +2175,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "c52ac009d615e79296318c1bcce2d422aaca15ad08515e344feeda07df67a587" dependencies = [ "memchr", ] diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json index c9bc710b537..48dfbfd6fcb 100644 --- a/apps/desktop/native-messaging-test-runner/package-lock.json +++ b/apps/desktop/native-messaging-test-runner/package-lock.json @@ -46,8 +46,6 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -58,23 +56,17 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.4.15", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -82,27 +74,19 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "version": "1.0.10", "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "license": "MIT" }, "node_modules/@types/node": { @@ -116,8 +100,6 @@ }, "node_modules/@types/node-ipc": { "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@types/node-ipc/-/node-ipc-9.2.3.tgz", - "integrity": "sha512-/MvSiF71fYf3+zwqkh/zkVkZj1hl1Uobre9EMFy08mqfJNAmpR0vmPgOUdEIDVgifxHj6G1vYMPLSBLLxoDACQ==", "dev": true, "license": "MIT", "dependencies": { @@ -125,9 +107,7 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.11.3", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -137,21 +117,14 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.2", "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, "engines": { "node": ">=0.4.0" } }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -159,8 +132,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -174,14 +145,10 @@ }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "license": "MIT" }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -194,8 +161,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -206,20 +171,14 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "license": "MIT" }, "node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -227,8 +186,6 @@ }, "node_modules/easy-stack": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", - "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -236,14 +193,10 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "version": "3.1.2", "license": "MIT", "engines": { "node": ">=6" @@ -251,8 +204,6 @@ }, "node_modules/event-pubsub": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", - "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", "license": "Unlicense", "engines": { "node": ">=4.0.0" @@ -260,8 +211,6 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -269,8 +218,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -278,8 +225,6 @@ }, "node_modules/js-message": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", - "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", "license": "MIT", "engines": { "node": ">=0.6.0" @@ -287,8 +232,6 @@ }, "node_modules/js-queue": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", - "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", "license": "MIT", "dependencies": { "easy-stack": "^1.0.1" @@ -299,20 +242,14 @@ }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "license": "ISC" }, "node_modules/module-alias": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", "license": "MIT" }, "node_modules/node-ipc": { "version": "9.2.1", - "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", - "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", "license": "MIT", "dependencies": { "event-pubsub": "4.3.0", @@ -325,8 +262,6 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -334,8 +269,6 @@ }, "node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -348,8 +281,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -403,8 +334,6 @@ }, "node_modules/typescript": { "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -435,14 +364,10 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "license": "MIT" }, "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -458,8 +383,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", "engines": { "node": ">=10" @@ -467,8 +390,6 @@ }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -485,8 +406,6 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "license": "ISC", "engines": { "node": ">=12" @@ -494,8 +413,6 @@ }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "license": "MIT", "engines": { "node": ">=6" diff --git a/apps/desktop/src/app/accounts/settings.component.html b/apps/desktop/src/app/accounts/settings.component.html index 891314aa568..02b64a757a7 100644 --- a/apps/desktop/src/app/accounts/settings.component.html +++ b/apps/desktop/src/app/accounts/settings.component.html @@ -382,7 +382,7 @@ {{ - "enableBrowserIntegrationDesc" | i18n + "enableBrowserIntegrationDesc1" | i18n }}
diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 7f8ddb3aad3..9504ecb1fa3 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -1775,8 +1775,8 @@ "enableBrowserIntegration": { "message": "Allow browser integration" }, - "enableBrowserIntegrationDesc": { - "message": "Used for biometrics in browser." + "enableBrowserIntegrationDesc1": { + "message": "Used to allow biometric unlock in browsers that are not Safari." }, "enableDuckDuckGoBrowserIntegration": { "message": "Allow DuckDuckGo browser integration" diff --git a/apps/web/src/app/billing/individual/premium/premium-v2.component.html b/apps/web/src/app/billing/individual/premium/premium-v2.component.html index bdf6ff87d19..eb93d8ef6a3 100644 --- a/apps/web/src/app/billing/individual/premium/premium-v2.component.html +++ b/apps/web/src/app/billing/individual/premium/premium-v2.component.html @@ -66,33 +66,39 @@ -

{{ "uploadLicenseFilePremium" | i18n }}

-
- - {{ "licenseFile" | i18n }} -
- - {{ - licenseFormGroup.value.file ? licenseFormGroup.value.file.name : ("noFileChosen" | i18n) - }} -
- - {{ "licenseFileDesc" | i18n: "bitwarden_premium_license.json" }} -
- -
+ +

{{ "uploadLicenseFilePremium" | i18n }}

+
+ + {{ "licenseFile" | i18n }} +
+ + {{ + licenseFormGroup.value.file ? licenseFormGroup.value.file.name : ("noFileChosen" | i18n) + }} +
+ + {{ "licenseFileDesc" | i18n: "bitwarden_premium_license.json" }} +
+ +
+
+
diff --git a/apps/web/src/app/billing/individual/premium/premium-v2.component.ts b/apps/web/src/app/billing/individual/premium/premium-v2.component.ts index cf66dac2f76..4f6d30530c2 100644 --- a/apps/web/src/app/billing/individual/premium/premium-v2.component.ts +++ b/apps/web/src/app/billing/individual/premium/premium-v2.component.ts @@ -7,6 +7,8 @@ import { combineLatest, concatMap, from, Observable, of } from "rxjs"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; +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 { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -36,6 +38,10 @@ export class PremiumV2Component { protected cloudWebVaultURL: string; protected isSelfHost = false; + protected useLicenseUploaderComponent$ = this.configService.getFeatureFlag$( + FeatureFlag.PM11901_RefactorSelfHostingLicenseUploader, + ); + protected readonly familyPlanMaxUserCount = 6; protected readonly premiumPrice = 10; protected readonly storageGBPrice = 4; @@ -44,6 +50,7 @@ export class PremiumV2Component { private activatedRoute: ActivatedRoute, private apiService: ApiService, private billingAccountProfileStateService: BillingAccountProfileStateService, + private configService: ConfigService, private environmentService: EnvironmentService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, @@ -78,6 +85,9 @@ export class PremiumV2Component { finalizeUpgrade = async () => { await this.apiService.refreshIdentityToken(); await this.syncService.fullSync(true); + }; + + postFinalizeUpgrade = async () => { this.toastService.showToast({ variant: "success", title: null, @@ -119,6 +129,7 @@ export class PremiumV2Component { await this.apiService.postAccountLicense(formData); await this.finalizeUpgrade(); + await this.postFinalizeUpgrade(); }; submitPayment = async (): Promise => { @@ -138,6 +149,7 @@ export class PremiumV2Component { await this.apiService.postPremium(formData); await this.finalizeUpgrade(); + await this.postFinalizeUpgrade(); }; protected get additionalStorageCost(): number { @@ -161,4 +173,8 @@ export class PremiumV2Component { protected get total(): number { return this.subtotal + this.estimatedTax; } + + protected async onLicenseFileSelectedChanged(): Promise { + await this.postFinalizeUpgrade(); + } } diff --git a/apps/web/src/app/billing/organizations/organization-plans.component.html b/apps/web/src/app/billing/organizations/organization-plans.component.html index 5992af5f544..e6e2610d67c 100644 --- a/apps/web/src/app/billing/organizations/organization-plans.component.html +++ b/apps/web/src/app/billing/organizations/organization-plans.component.html @@ -7,32 +7,38 @@ {{ "loading" | i18n }} -

{{ "uploadLicenseFileOrg" | i18n }}

- - - {{ "licenseFile" | i18n }} -
- - {{ selectedFile?.name ?? ("noFileChosen" | i18n) }} -
- - {{ "licenseFileDesc" | i18n: "bitwarden_organization_license.json" }} -
- - + +

{{ "uploadLicenseFileOrg" | i18n }}

+
+ + {{ "licenseFile" | i18n }} +
+ + {{ selectedFile?.name ?? ("noFileChosen" | i18n) }} +
+ + {{ "licenseFileDesc" | i18n: "bitwarden_organization_license.json" }} +
+ +
+
+
{ + this.toastService.showToast({ + variant: "success", + title: this.i18nService.t("organizationCreated"), + message: this.i18nService.t("organizationReadyToGo"), + }); + + if (!this.acceptingSponsorship && !this.isInTrialFlow) { + // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.router.navigate(["/organizations/" + organizationId]); + } + + if (this.isInTrialFlow) { + this.onTrialBillingSuccess.emit({ + orgId: organizationId, + subLabelText: this.billingSubLabelText(), + }); + } + + this.onSuccess.emit({ organizationId: organizationId }); + + // TODO: No one actually listening to this message? + this.messagingService.send("organizationCreated", { organizationId: organizationId }); + } } diff --git a/apps/web/src/app/billing/shared/billing-shared.module.ts b/apps/web/src/app/billing/shared/billing-shared.module.ts index b966729c1df..57491a73e6d 100644 --- a/apps/web/src/app/billing/shared/billing-shared.module.ts +++ b/apps/web/src/app/billing/shared/billing-shared.module.ts @@ -13,6 +13,8 @@ import { OffboardingSurveyComponent } from "./offboarding-survey.component"; import { PaymentV2Component } from "./payment/payment-v2.component"; import { PaymentComponent } from "./payment/payment.component"; import { PaymentMethodComponent } from "./payment-method.component"; +import { IndividualSelfHostingLicenseUploaderComponent } from "./self-hosting-license-uploader/individual-self-hosting-license-uploader.component"; +import { OrganizationSelfHostingLicenseUploaderComponent } from "./self-hosting-license-uploader/organization-self-hosting-license-uploader.component"; import { SecretsManagerSubscribeComponent } from "./sm-subscribe.component"; import { TaxInfoComponent } from "./tax-info.component"; import { UpdateLicenseDialogComponent } from "./update-license-dialog.component"; @@ -40,6 +42,8 @@ import { VerifyBankAccountComponent } from "./verify-bank-account/verify-bank-ac OffboardingSurveyComponent, AdjustPaymentDialogV2Component, AdjustStorageDialogV2Component, + IndividualSelfHostingLicenseUploaderComponent, + OrganizationSelfHostingLicenseUploaderComponent, ], exports: [ SharedModule, @@ -53,6 +57,8 @@ import { VerifyBankAccountComponent } from "./verify-bank-account/verify-bank-ac OffboardingSurveyComponent, VerifyBankAccountComponent, PaymentV2Component, + IndividualSelfHostingLicenseUploaderComponent, + OrganizationSelfHostingLicenseUploaderComponent, ], }) export class BillingSharedModule {} diff --git a/apps/web/src/app/billing/shared/self-hosting-license-uploader/abstract-self-hosting-license-uploader.component.ts b/apps/web/src/app/billing/shared/self-hosting-license-uploader/abstract-self-hosting-license-uploader.component.ts new file mode 100644 index 00000000000..01605eae7dc --- /dev/null +++ b/apps/web/src/app/billing/shared/self-hosting-license-uploader/abstract-self-hosting-license-uploader.component.ts @@ -0,0 +1,81 @@ +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { ToastService } from "@bitwarden/components"; + +import { LicenseUploaderFormModel } from "./license-uploader-form-model"; + +/** + * Shared implementation for processing license file uploads. + * @remarks Requires self-hosting. + */ +export abstract class AbstractSelfHostingLicenseUploaderComponent { + protected form: FormGroup; + + protected constructor( + protected readonly formBuilder: FormBuilder, + protected readonly i18nService: I18nService, + protected readonly platformUtilsService: PlatformUtilsService, + protected readonly toastService: ToastService, + protected readonly tokenService: TokenService, + ) { + const isSelfHosted = this.platformUtilsService.isSelfHost(); + + if (!isSelfHosted) { + throw new Error("This component should only be used in self-hosted environments"); + } + + this.form = this.formBuilder.group({ + file: [null, [Validators.required]], + }); + this.submit = this.submit.bind(this); + } + + /** + * Gets the submitted license upload form model. + * @protected + */ + protected get formValue(): LicenseUploaderFormModel { + return this.form.value as LicenseUploaderFormModel; + } + + /** + * Triggered when a different license file is selected. + * @param event + */ + onLicenseFileSelectedChanged(event: Event): void { + const element = event.target as HTMLInputElement; + this.form.value.file = element.files.length > 0 ? element.files[0] : null; + } + + /** + * Submits the license upload form. + * @protected + */ + protected async submit(): Promise { + this.form.markAllAsTouched(); + + if (this.form.invalid) { + return this.toastService.showToast({ + variant: "error", + title: this.i18nService.t("errorOccurred"), + message: this.i18nService.t("selectFile"), + }); + } + + const emailVerified = await this.tokenService.getEmailVerified(); + if (!emailVerified) { + return this.toastService.showToast({ + variant: "error", + title: this.i18nService.t("errorOccurred"), + message: this.i18nService.t("verifyEmailFirst"), + }); + } + } + + abstract get description(): string; + + abstract get hintFileName(): string; +} diff --git a/apps/web/src/app/billing/shared/self-hosting-license-uploader/individual-self-hosting-license-uploader.component.ts b/apps/web/src/app/billing/shared/self-hosting-license-uploader/individual-self-hosting-license-uploader.component.ts new file mode 100644 index 00000000000..0d7698e00fd --- /dev/null +++ b/apps/web/src/app/billing/shared/self-hosting-license-uploader/individual-self-hosting-license-uploader.component.ts @@ -0,0 +1,60 @@ +import { Component, EventEmitter, Output } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { SyncService } from "@bitwarden/common/platform/sync"; +import { ToastService } from "@bitwarden/components"; + +import { AbstractSelfHostingLicenseUploaderComponent } from "../../shared/self-hosting-license-uploader/abstract-self-hosting-license-uploader.component"; + +/** + * Processes license file uploads for individual plans. + * @remarks Requires self-hosting. + */ +@Component({ + selector: "individual-self-hosting-license-uploader", + templateUrl: "./self-hosting-license-uploader.component.html", +}) +export class IndividualSelfHostingLicenseUploaderComponent extends AbstractSelfHostingLicenseUploaderComponent { + /** + * Emitted when a license file has been successfully uploaded & processed. + */ + @Output() onLicenseFileUploaded: EventEmitter = new EventEmitter(); + + constructor( + protected readonly apiService: ApiService, + protected readonly formBuilder: FormBuilder, + protected readonly i18nService: I18nService, + protected readonly platformUtilsService: PlatformUtilsService, + protected readonly syncService: SyncService, + protected readonly toastService: ToastService, + protected readonly tokenService: TokenService, + ) { + super(formBuilder, i18nService, platformUtilsService, toastService, tokenService); + } + + protected async submit(): Promise { + await super.submit(); + + const formData = new FormData(); + formData.append("license", this.formValue.file); + + await this.apiService.postAccountLicense(formData); + + await this.apiService.refreshIdentityToken(); + await this.syncService.fullSync(true); + + this.onLicenseFileUploaded.emit(); + } + + get description(): string { + return "uploadLicenseFilePremium"; + } + + get hintFileName(): string { + return "bitwarden_premium_license.json"; + } +} diff --git a/apps/web/src/app/billing/shared/self-hosting-license-uploader/license-uploader-form-model.ts b/apps/web/src/app/billing/shared/self-hosting-license-uploader/license-uploader-form-model.ts new file mode 100644 index 00000000000..42ce1be2ea4 --- /dev/null +++ b/apps/web/src/app/billing/shared/self-hosting-license-uploader/license-uploader-form-model.ts @@ -0,0 +1,3 @@ +export interface LicenseUploaderFormModel { + file: File; +} diff --git a/apps/web/src/app/billing/shared/self-hosting-license-uploader/organization-self-hosting-license-uploader.component.ts b/apps/web/src/app/billing/shared/self-hosting-license-uploader/organization-self-hosting-license-uploader.component.ts new file mode 100644 index 00000000000..79c3cb83a43 --- /dev/null +++ b/apps/web/src/app/billing/shared/self-hosting-license-uploader/organization-self-hosting-license-uploader.component.ts @@ -0,0 +1,85 @@ +import { Component, EventEmitter, Output } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; +import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request"; +import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; +import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; +import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { SyncService } from "@bitwarden/common/platform/sync"; +import { OrgKey } from "@bitwarden/common/types/key"; +import { ToastService } from "@bitwarden/components"; + +import { AbstractSelfHostingLicenseUploaderComponent } from "../../shared/self-hosting-license-uploader/abstract-self-hosting-license-uploader.component"; + +/** + * Processes license file uploads for organizations. + * @remarks Requires self-hosting. + */ +@Component({ + selector: "organization-self-hosting-license-uploader", + templateUrl: "./self-hosting-license-uploader.component.html", +}) +export class OrganizationSelfHostingLicenseUploaderComponent extends AbstractSelfHostingLicenseUploaderComponent { + /** + * Notifies the parent component of the `organizationId` the license was created for. + */ + @Output() onLicenseFileUploaded: EventEmitter = new EventEmitter(); + + constructor( + protected readonly formBuilder: FormBuilder, + protected readonly i18nService: I18nService, + protected readonly platformUtilsService: PlatformUtilsService, + protected readonly toastService: ToastService, + protected readonly tokenService: TokenService, + private readonly apiService: ApiService, + private readonly encryptService: EncryptService, + private readonly cryptoService: CryptoService, + private readonly organizationApiService: OrganizationApiServiceAbstraction, + private readonly syncService: SyncService, + ) { + super(formBuilder, i18nService, platformUtilsService, toastService, tokenService); + } + + protected async submit(): Promise { + await super.submit(); + + const orgKey = await this.cryptoService.makeOrgKey(); + const key = orgKey[0].encryptedString; + const collection = await this.encryptService.encrypt( + this.i18nService.t("defaultCollection"), + orgKey[1], + ); + const collectionCt = collection.encryptedString; + const orgKeys = await this.cryptoService.makeKeyPair(orgKey[1]); + + const fd = new FormData(); + fd.append("license", this.formValue.file); + fd.append("key", key); + fd.append("collectionName", collectionCt); + const response = await this.organizationApiService.createLicense(fd); + const orgId = response.id; + + await this.apiService.refreshIdentityToken(); + + // Org Keys live outside of the OrganizationLicense - add the keys to the org here + const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString); + await this.organizationApiService.updateKeys(orgId, request); + + await this.apiService.refreshIdentityToken(); + await this.syncService.fullSync(true); + + this.onLicenseFileUploaded.emit(orgId); + } + + get description(): string { + return "uploadLicenseFileOrg"; + } + + get hintFileName(): string { + return "bitwarden_organization_license.json"; + } +} diff --git a/apps/web/src/app/billing/shared/self-hosting-license-uploader/self-hosting-license-uploader.component.html b/apps/web/src/app/billing/shared/self-hosting-license-uploader/self-hosting-license-uploader.component.html new file mode 100644 index 00000000000..2238c10dd4a --- /dev/null +++ b/apps/web/src/app/billing/shared/self-hosting-license-uploader/self-hosting-license-uploader.component.html @@ -0,0 +1,26 @@ +

{{ "uploadLicenseFileOrg" | i18n }}

+ + + {{ description | i18n }} +
+ + {{ form.value.file ? form.value.file.name : ("noFileChosen" | i18n) }} +
+ + {{ "licenseFileDesc" | i18n: hintFileName }} +
+ + diff --git a/apps/web/src/app/vault/individual-vault/password-history.component.html b/apps/web/src/app/vault/individual-vault/password-history.component.html new file mode 100644 index 00000000000..bae10d85aa7 --- /dev/null +++ b/apps/web/src/app/vault/individual-vault/password-history.component.html @@ -0,0 +1,40 @@ + + + {{ "passwordHistory" | i18n }} + + +
+ +
+ +
{{ h.lastUsedDate | date: "medium" }}
+
+ + + + + +
+
+
+

{{ "noPasswordsInList" | i18n }}

+
+
+ + + +
diff --git a/apps/web/src/app/vault/individual-vault/password-history.component.ts b/apps/web/src/app/vault/individual-vault/password-history.component.ts new file mode 100644 index 00000000000..21a1b01e583 --- /dev/null +++ b/apps/web/src/app/vault/individual-vault/password-history.component.ts @@ -0,0 +1,131 @@ +import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; +import { CommonModule } from "@angular/common"; +import { OnInit, Inject, Component } from "@angular/core"; +import { firstValueFrom, map } from "rxjs"; + +import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { CipherId, UserId } from "@bitwarden/common/types/guid"; +import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { PasswordHistoryView } from "@bitwarden/common/vault/models/view/password-history.view"; +import { + AsyncActionsModule, + DialogModule, + DialogService, + ToastService, + ItemModule, +} from "@bitwarden/components"; + +import { SharedModule } from "../../shared/shared.module"; + +/** + * The parameters for the password history dialog. + */ +export interface ViewPasswordHistoryDialogParams { + cipherId: CipherId; +} + +/** + * A dialog component that displays the password history for a cipher. + */ +@Component({ + selector: "app-vault-password-history", + templateUrl: "password-history.component.html", + standalone: true, + imports: [CommonModule, AsyncActionsModule, DialogModule, ItemModule, SharedModule], +}) +export class PasswordHistoryComponent implements OnInit { + /** + * The ID of the cipher to display the password history for. + */ + cipherId: CipherId; + + /** + * The password history for the cipher. + */ + history: PasswordHistoryView[] = []; + + /** + * The constructor for the password history dialog component. + * @param params The parameters passed to the password history dialog. + * @param cipherService The cipher service - used to get the cipher to display the password history for. + * @param platformUtilsService The platform utils service - used to copy passwords to the clipboard. + * @param i18nService The i18n service - used to translate strings. + * @param accountService The account service - used to get the active account to decrypt the cipher. + * @param win The window object - used to copy passwords to the clipboard. + * @param toastService The toast service - used to display feedback to the user when a password is copied. + * @param dialogRef The dialog reference - used to close the dialog. + **/ + constructor( + @Inject(DIALOG_DATA) public params: ViewPasswordHistoryDialogParams, + protected cipherService: CipherService, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + protected accountService: AccountService, + @Inject(WINDOW) private win: Window, + protected toastService: ToastService, + private dialogRef: DialogRef, + ) { + /** + * Set the cipher ID from the parameters. + */ + this.cipherId = params.cipherId; + } + + async ngOnInit() { + await this.init(); + } + + /** + * Copies a password to the clipboard. + * @param password The password to copy. + */ + copy(password: string) { + const copyOptions = this.win != null ? { window: this.win } : undefined; + this.platformUtilsService.copyToClipboard(password, copyOptions); + this.toastService.showToast({ + variant: "info", + title: "", + message: this.i18nService.t("valueCopied", this.i18nService.t("password")), + }); + } + + /** + * Initializes the password history dialog component. + */ + protected async init() { + const cipher = await this.cipherService.get(this.cipherId); + const activeAccount = await firstValueFrom( + this.accountService.activeAccount$.pipe(map((a: { id: string | undefined }) => a)), + ); + + if (!activeAccount || !activeAccount.id) { + throw new Error("Active account is not available."); + } + + const activeUserId = activeAccount.id as UserId; + const decCipher = await cipher.decrypt( + await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId), + ); + this.history = decCipher.passwordHistory == null ? [] : decCipher.passwordHistory; + } + + /** + * Closes the password history dialog. + */ + close() { + this.dialogRef.close(); + } +} + +/** + * Strongly typed wrapper around the dialog service to open the password history dialog. + */ +export function openPasswordHistoryDialog( + dialogService: DialogService, + config: DialogConfig, +) { + return dialogService.open(PasswordHistoryComponent, config); +} diff --git a/apps/web/src/app/vault/individual-vault/view.component.ts b/apps/web/src/app/vault/individual-vault/view.component.ts index 67a0223c738..ead52d805a8 100644 --- a/apps/web/src/app/vault/individual-vault/view.component.ts +++ b/apps/web/src/app/vault/individual-vault/view.component.ts @@ -8,6 +8,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { ViewPasswordHistoryService } from "@bitwarden/common/vault/abstractions/view-password-history.service"; import { CipherType } from "@bitwarden/common/vault/enums/cipher-type"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; @@ -22,6 +23,7 @@ import { PremiumUpgradePromptService } from "../../../../../../libs/common/src/v import { CipherViewComponent } from "../../../../../../libs/vault/src/cipher-view/cipher-view.component"; import { SharedModule } from "../../shared/shared.module"; import { WebVaultPremiumUpgradePromptService } from "../services/web-premium-upgrade-prompt.service"; +import { WebViewPasswordHistoryService } from "../services/web-view-password-history.service"; export interface ViewCipherDialogParams { cipher: CipherView; @@ -57,6 +59,7 @@ export interface ViewCipherDialogCloseResult { standalone: true, imports: [CipherViewComponent, CommonModule, AsyncActionsModule, DialogModule, SharedModule], providers: [ + { provide: ViewPasswordHistoryService, useClass: WebViewPasswordHistoryService }, { provide: PremiumUpgradePromptService, useClass: WebVaultPremiumUpgradePromptService }, ], }) diff --git a/apps/web/src/app/vault/services/web-view-password-history.service.spec.ts b/apps/web/src/app/vault/services/web-view-password-history.service.spec.ts new file mode 100644 index 00000000000..2c5fb82c53c --- /dev/null +++ b/apps/web/src/app/vault/services/web-view-password-history.service.spec.ts @@ -0,0 +1,45 @@ +import { Overlay } from "@angular/cdk/overlay"; +import { TestBed } from "@angular/core/testing"; + +import { CipherId } from "@bitwarden/common/types/guid"; +import { DialogService } from "@bitwarden/components"; + +import { openPasswordHistoryDialog } from "../individual-vault/password-history.component"; + +import { WebViewPasswordHistoryService } from "./web-view-password-history.service"; + +jest.mock("../individual-vault/password-history.component", () => ({ + openPasswordHistoryDialog: jest.fn(), +})); + +describe("WebViewPasswordHistoryService", () => { + let service: WebViewPasswordHistoryService; + let dialogService: DialogService; + + beforeEach(async () => { + const mockDialogService = { + open: jest.fn(), + }; + + await TestBed.configureTestingModule({ + providers: [ + WebViewPasswordHistoryService, + { provide: DialogService, useValue: mockDialogService }, + Overlay, + ], + }).compileComponents(); + + service = TestBed.inject(WebViewPasswordHistoryService); + dialogService = TestBed.inject(DialogService); + }); + + describe("viewPasswordHistory", () => { + it("calls openPasswordHistoryDialog with the correct parameters", async () => { + const mockCipherId = "cipher-id" as CipherId; + await service.viewPasswordHistory(mockCipherId); + expect(openPasswordHistoryDialog).toHaveBeenCalledWith(dialogService, { + data: { cipherId: mockCipherId }, + }); + }); + }); +}); diff --git a/apps/web/src/app/vault/services/web-view-password-history.service.ts b/apps/web/src/app/vault/services/web-view-password-history.service.ts new file mode 100644 index 00000000000..cbdc3928e60 --- /dev/null +++ b/apps/web/src/app/vault/services/web-view-password-history.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from "@angular/core"; + +import { CipherId } from "@bitwarden/common/types/guid"; +import { DialogService } from "@bitwarden/components"; + +import { ViewPasswordHistoryService } from "../../../../../../libs/common/src/vault/abstractions/view-password-history.service"; +import { openPasswordHistoryDialog } from "../individual-vault/password-history.component"; + +/** + * This service is used to display the password history dialog in the web vault. + */ +@Injectable() +export class WebViewPasswordHistoryService implements ViewPasswordHistoryService { + constructor(private dialogService: DialogService) {} + + /** + * Opens the password history dialog for the given cipher ID. + * @param cipherId The ID of the cipher to view the password history for. + */ + async viewPasswordHistory(cipherId: CipherId) { + openPasswordHistoryDialog(this.dialogService, { data: { cipherId } }); + } +} diff --git a/libs/angular/src/admin-console/components/collections.component.ts b/libs/angular/src/admin-console/components/collections.component.ts index d6801aa155e..93410afaaea 100644 --- a/libs/angular/src/admin-console/components/collections.component.ts +++ b/libs/angular/src/admin-console/components/collections.component.ts @@ -72,7 +72,7 @@ export class CollectionsComponent implements OnInit { if (this.organization.canEditAllCiphers) { return !!(c as any).checked; } else { - return !!(c as any).checked && c.readOnly == null; + return !!(c as any).checked && !c.readOnly; } }) .map((c) => c.id); diff --git a/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts b/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts index 0cea2aee539..a2ea6aa8861 100644 --- a/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts +++ b/libs/common/src/admin-console/abstractions/organization/organization.service.abstraction.ts @@ -117,6 +117,10 @@ export abstract class OrganizationService { * Emits true if the user can create or manage a Free Bitwarden Families sponsorship. */ canManageSponsorships$: Observable; + /** + * Emits true if any of the user's organizations have a Free Bitwarden Families sponsorship available. + */ + familySponsorshipAvailable$: Observable; hasOrganizations: () => Promise; get$: (id: string) => Observable; get: (id: string) => Promise; diff --git a/libs/common/src/admin-console/services/organization/organization.service.ts b/libs/common/src/admin-console/services/organization/organization.service.ts index d8fe18dc5cb..91bfcbd0d5d 100644 --- a/libs/common/src/admin-console/services/organization/organization.service.ts +++ b/libs/common/src/admin-console/services/organization/organization.service.ts @@ -88,6 +88,10 @@ export class OrganizationService implements InternalOrganizationServiceAbstracti mapToBooleanHasAnyOrganizations(), ); + familySponsorshipAvailable$ = this.organizations$.pipe( + map((orgs) => orgs.some((o) => o.familySponsorshipAvailable)), + ); + async hasOrganizations(): Promise { return await firstValueFrom(this.organizations$.pipe(mapToBooleanHasAnyOrganizations())); } diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index 7ac473ff6ab..505fe33e82a 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -33,6 +33,7 @@ export enum FeatureFlag { NotificationBarAddLoginImprovements = "notification-bar-add-login-improvements", AC2476_DeprecateStripeSourcesAPI = "AC-2476-deprecate-stripe-sources-api", CipherKeyEncryption = "cipher-key-encryption", + PM11901_RefactorSelfHostingLicenseUploader = "PM-11901-refactor-self-hosting-license-uploader", } export type AllowedFeatureFlagTypes = boolean | number | string; @@ -76,6 +77,7 @@ export const DefaultFeatureFlagValue = { [FeatureFlag.NotificationBarAddLoginImprovements]: FALSE, [FeatureFlag.AC2476_DeprecateStripeSourcesAPI]: FALSE, [FeatureFlag.CipherKeyEncryption]: FALSE, + [FeatureFlag.PM11901_RefactorSelfHostingLicenseUploader]: FALSE, } satisfies Record; export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue; diff --git a/libs/common/src/models/response/profile.response.ts b/libs/common/src/models/response/profile.response.ts index 6b6555fc566..24aeb11cdbb 100644 --- a/libs/common/src/models/response/profile.response.ts +++ b/libs/common/src/models/response/profile.response.ts @@ -21,6 +21,7 @@ export class ProfileResponse extends BaseResponse { securityStamp: string; forcePasswordReset: boolean; usesKeyConnector: boolean; + managedByOrganizationId?: string | null; organizations: ProfileOrganizationResponse[] = []; providers: ProfileProviderResponse[] = []; providerOrganizations: ProfileProviderOrganizationResponse[] = []; @@ -42,6 +43,7 @@ export class ProfileResponse extends BaseResponse { this.securityStamp = this.getResponseProperty("SecurityStamp"); this.forcePasswordReset = this.getResponseProperty("ForcePasswordReset") ?? false; this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false; + this.managedByOrganizationId = this.getResponseProperty("ManagedByOrganizationId"); const organizations = this.getResponseProperty("Organizations"); if (organizations != null) { diff --git a/libs/common/src/vault/abstractions/view-password-history.service.ts b/libs/common/src/vault/abstractions/view-password-history.service.ts new file mode 100644 index 00000000000..d9b1306eacb --- /dev/null +++ b/libs/common/src/vault/abstractions/view-password-history.service.ts @@ -0,0 +1,8 @@ +import { CipherId } from "../../types/guid"; + +/** + * The ViewPasswordHistoryService is responsible for displaying the password history for a cipher. + */ +export abstract class ViewPasswordHistoryService { + abstract viewPasswordHistory(cipherId?: CipherId): Promise; +} diff --git a/libs/vault/src/cipher-view/item-history/item-history-v2.component.html b/libs/vault/src/cipher-view/item-history/item-history-v2.component.html index a03639dee61..d48666ad83a 100644 --- a/libs/vault/src/cipher-view/item-history/item-history-v2.component.html +++ b/libs/vault/src/cipher-view/item-history/item-history-v2.component.html @@ -27,10 +27,8 @@

{{ "passwordHistory" | i18n }} diff --git a/libs/vault/src/cipher-view/item-history/item-history-v2.component.ts b/libs/vault/src/cipher-view/item-history/item-history-v2.component.ts index 55c8b90da15..4a37c9a491b 100644 --- a/libs/vault/src/cipher-view/item-history/item-history-v2.component.ts +++ b/libs/vault/src/cipher-view/item-history/item-history-v2.component.ts @@ -3,6 +3,8 @@ import { Component, Input } from "@angular/core"; import { RouterModule } from "@angular/router"; import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { CipherId } from "@bitwarden/common/types/guid"; +import { ViewPasswordHistoryService } from "@bitwarden/common/vault/abstractions/view-password-history.service"; import { CipherType } from "@bitwarden/common/vault/enums"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { @@ -31,7 +33,16 @@ import { export class ItemHistoryV2Component { @Input() cipher: CipherView; + constructor(private viewPasswordHistoryService: ViewPasswordHistoryService) {} + get isLogin() { return this.cipher.type === CipherType.Login; } + + /** + * View the password history for the cipher. + */ + async viewPasswordHistory() { + await this.viewPasswordHistoryService.viewPasswordHistory(this.cipher?.id as CipherId); + } } diff --git a/package-lock.json b/package-lock.json index 57b3aa028fb..39cfb49a545 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,7 +95,7 @@ "@storybook/manager-api": "8.2.9", "@storybook/theming": "8.2.9", "@types/argon2-browser": "1.18.4", - "@types/chrome": "0.0.270", + "@types/chrome": "0.0.272", "@types/firefox-webext-browser": "111.0.5", "@types/inquirer": "8.2.10", "@types/jest": "29.5.12", @@ -358,14 +358,14 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1802.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.2.tgz", - "integrity": "sha512-LPRl9jhcf0NgshaL6RoUy1uL/cAyNt7oxctoZ9EHUu8eh5E9W/jZGhVowjOLpirwqYhmEzKJJIeS49Ssqs3RQg==", + "version": "0.1802.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.5.tgz", + "integrity": "sha512-c7sVoW85Yqj7IYvNKxtNSGS5I7gWpORorg/xxLZX3OkHWXDrwYbb5LN/2p5/Aytxyb0aXl4o5fFOu6CUwcaLUw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@angular-devkit/core": "18.2.2", + "@angular-devkit/core": "18.2.5", "rxjs": "7.8.1" }, "engines": { @@ -1439,9 +1439,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.2.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.2.tgz", - "integrity": "sha512-Zz0tGptI/QQnUBDdp+1G5wGwQWMjpfe2oO+UohkrDVgFS71yVj4VDnOy51kMTxBvzw+36evTgthPpmzqPIfxBw==", + "version": "18.2.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.5.tgz", + "integrity": "sha512-r9TumPlJ8PvA2+yz4sp+bUHgtznaVKzhvXTN5qL1k4YP8LJ7iZWMR2FOP+HjukHZOTsenzmV9pszbogabqwoZQ==", "dev": true, "license": "MIT", "peer": true, @@ -5027,12 +5027,13 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.10.tgz", - "integrity": "sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw==", + "version": "3.2.13", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.13.tgz", + "integrity": "sha512-pY5z2qQSwbFzJsBdgfJIzXf5ElHTVMutC2dxh0FD60njknMu3n1NnTABOcQwbb5/v5soqE79m9UjaJryBf3epg==", "dev": true, "license": "MIT", "dependencies": { + "@types/glob": "^7.1.0", "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" @@ -5374,57 +5375,6 @@ "node": "*" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", - "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", - "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", - "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.18.17", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", @@ -5442,312 +5392,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", - "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", - "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", - "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", - "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", - "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", - "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", - "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", - "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", - "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", - "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", - "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", - "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", - "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", - "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", - "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", - "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", - "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", - "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -5765,9 +5409,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "license": "MIT", "engines": { @@ -6095,9 +5739,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "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": { @@ -6811,6 +6455,7 @@ "version": "12.0.1", "resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.1.tgz", "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", + "deprecated": "Use v12.0.2 or higher to fix the vulnerability issue", "license": "MIT", "dependencies": { "debug": "^4.3.4", @@ -8080,10 +7725,38 @@ } } }, + "node_modules/@storybook/angular/node_modules/@storybook/components": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.3.3.tgz", + "integrity": "sha512-i2JYtesFGkdu+Hwuj+o9fLuO3yo+LPT1/8o5xBVYtEqsgDtEAyuRUWjSz8d8NPtzloGPOv5kvR6MokWDfbeMfw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.3.3" + } + }, + "node_modules/@storybook/angular/node_modules/@storybook/preview-api": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.3.3.tgz", + "integrity": "sha512-GP2QlaF3BBQGAyo248N7549YkTQjCentsc1hUvqPnFWU4xfjkejbnFk8yLaIw0VbYbL7jfd7npBtjZ+6AnphMQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.3.3" + } + }, "node_modules/@storybook/angular/node_modules/@types/node": { - "version": "18.19.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.48.tgz", - "integrity": "sha512-7WevbG4ekUcRQSZzOwxWgi5dZmTak7FaxXDoW7xVxPBmKx1rTzfmRLkeCgJzcbBnOV2dkhAPc8cCeT6agocpjg==", + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8186,9 +7859,9 @@ } }, "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { - "version": "18.19.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.48.tgz", - "integrity": "sha512-7WevbG4ekUcRQSZzOwxWgi5dZmTak7FaxXDoW7xVxPBmKx1rTzfmRLkeCgJzcbBnOV2dkhAPc8cCeT6agocpjg==", + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8338,20 +8011,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@storybook/components": { - "version": "8.2.9", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.2.9.tgz", - "integrity": "sha512-OkkcZ/f/6o3GdFEEK9ZHKIGHWUHmavZUYs5xaSgU64bOrA2aqEFtfeWWitZYTv3Euhk8MVLWfyEMDfez0AlvDg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.9" - } - }, "node_modules/@storybook/core": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.9.tgz", @@ -8395,9 +8054,9 @@ } }, "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "18.19.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.48.tgz", - "integrity": "sha512-7WevbG4ekUcRQSZzOwxWgi5dZmTak7FaxXDoW7xVxPBmKx1rTzfmRLkeCgJzcbBnOV2dkhAPc8cCeT6agocpjg==", + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8412,9 +8071,9 @@ "license": "MIT" }, "node_modules/@storybook/core/node_modules/@types/node": { - "version": "18.19.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.48.tgz", - "integrity": "sha512-7WevbG4ekUcRQSZzOwxWgi5dZmTak7FaxXDoW7xVxPBmKx1rTzfmRLkeCgJzcbBnOV2dkhAPc8cCeT6agocpjg==", + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8463,9 +8122,9 @@ "license": "MIT" }, "node_modules/@storybook/icons": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.10.tgz", - "integrity": "sha512-310apKdDcjbbX2VSLWPwhEwAgjxTzVagrwucVZIdGPErwiAppX8KvBuWZgPo+rQLVrtH8S+pw1dbUwjcE6d7og==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.12.tgz", + "integrity": "sha512-UxgyK5W3/UV4VrI3dl6ajGfHM4aOqMAkFLWe2KibeQudLf6NJpDrDMSHwZj+3iKC4jFU7dkKbbtH2h/al4sW3Q==", "dev": true, "license": "MIT", "engines": { @@ -8509,20 +8168,6 @@ "storybook": "^8.2.9" } }, - "node_modules/@storybook/preview-api": { - "version": "8.2.9", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.2.9.tgz", - "integrity": "sha512-D8/t+a78OJqQAcT/ABa1C4YM/OaLGQ9IvCsp3Q9ruUqDCwuZBj8bG3D4477dlY4owX2ycC0rWYu3VvuK0EmJjA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.9" - } - }, "node_modules/@storybook/react-dom-shim": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.9.tgz", @@ -8692,9 +8337,9 @@ } }, "node_modules/@thednp/event-listener": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@thednp/event-listener/-/event-listener-2.0.5.tgz", - "integrity": "sha512-Zns+CFEAIKIEyqmuBZ3K2DSvk5IppaWcioghxLZPMrzkV034aOA38lP7NIKSxkeu0Eqd4UPxC06FksO6Pb/tmA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@thednp/event-listener/-/event-listener-2.0.6.tgz", + "integrity": "sha512-6u55ydv4+2VHwHU8EJaJXa40QzZ7XOXVo74MMPnGCSzbl0q3yqHfQh8r0Sw/50rutHxecLVQBM/C9Fr0c+m+ew==", "dev": true, "license": "MIT", "engines": { @@ -8703,9 +8348,9 @@ } }, "node_modules/@thednp/shorty": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@thednp/shorty/-/shorty-2.0.3.tgz", - "integrity": "sha512-ngKP9/wQxM6JPDFjO6ak8lSz38ZA6cIFQy3gZbZM3xgUqArBr+VG9aoSoLHHEuaObyd9q9Jq/T0Wez7qrck0Gw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@thednp/shorty/-/shorty-2.0.4.tgz", + "integrity": "sha512-7iMeqgiHOTjAWLcl/rbWHgquHnvfawT2gExdAa1TLjZMGcFjx00FZkg6CHuMjLh9ayBnlgabC4Dsx0DV+h9yqQ==", "dev": true, "license": "MIT", "engines": { @@ -8901,9 +8546,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.0.270", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.270.tgz", - "integrity": "sha512-ADvkowV7YnJfycZZxL2brluZ6STGW+9oKG37B422UePf2PCXuFA/XdERI0T18wtuWPx0tmFeZqq6MOXVk1IC+Q==", + "version": "0.0.272", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.272.tgz", + "integrity": "sha512-9cxDmmgyhXV8gsZvlRjqaDizNjIjbV0spsR0fIEaQUoHtbl9D8VkTOLyONgiBKK+guR38x5eMO3E3avUYOXwcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9002,9 +8647,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, @@ -9075,6 +8720,24 @@ "@types/node": "*" } }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/glob/node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -9346,9 +9009,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", + "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", "dev": true, "license": "MIT" }, @@ -9486,9 +9149,9 @@ } }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", "dev": true, "license": "MIT" }, @@ -9503,9 +9166,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", "dev": true, "license": "MIT" }, @@ -9517,9 +9180,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", - "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", + "version": "18.3.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz", + "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12664,9 +12327,9 @@ "license": "MIT" }, "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", "dev": true, "license": "Apache-2.0", "optional": true @@ -12885,9 +12548,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "license": "MIT", "dependencies": { @@ -12899,7 +12562,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -13624,9 +13287,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001655", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", - "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", + "version": "1.0.30001663", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", + "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", "funding": [ { "type": "opencollective", @@ -13911,9 +13574,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", - "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true, "license": "MIT" }, @@ -14658,9 +14321,9 @@ } }, "node_modules/config-file-ts/node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -15369,23 +15032,17 @@ "license": "MIT" }, "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" } }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "license": "MIT" - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -15491,12 +15148,12 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -16570,9 +16227,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", + "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==", "license": "ISC" }, "node_modules/electron-updater": { @@ -16694,9 +16351,10 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -16773,9 +16431,9 @@ } }, "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true, "license": "MIT", "bin": { @@ -17322,9 +16980,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", - "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.1.tgz", + "integrity": "sha512-EwcbfLOhwVMAfatfqLecR2yv3dE5+kQ8kx+Rrt0DvDXEVwW86KQ/xbMDQhtp5l42VXukD5SOF8mQQHbaNtO0CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -18045,38 +17703,38 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -18098,14 +17756,14 @@ } }, "node_modules/express/node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -18124,9 +17782,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true, "license": "MIT" }, @@ -18523,6 +18181,16 @@ "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -18898,9 +18566,9 @@ "license": "ISC" }, "node_modules/flow-parser": { - "version": "0.245.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.245.0.tgz", - "integrity": "sha512-xUBkkpIDfDZHAebnDEX65FCVitJUctab82KFmtP5SY4cGly1vbuYNe6Muyp0NLXrgmBChVdoC2T+3/RUHi4Mww==", + "version": "0.246.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.246.0.tgz", + "integrity": "sha512-WHRizzSrWFTcKo7cVcbP3wzZVhzsoYxoWqbnH4z+JXGqrjVmnsld6kBZWVlB200PwD5ur8r+HV3KUDxv3cHhOQ==", "dev": true, "license": "MIT", "engines": { @@ -18959,9 +18627,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -19637,9 +19305,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", - "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", "dev": true, "license": "MIT", "dependencies": { @@ -19972,7 +19640,6 @@ "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", "dev": true, "license": "MIT", "dependencies": { @@ -20025,7 +19692,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -21689,9 +21356,9 @@ } }, "node_modules/i18next": { - "version": "23.14.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.14.0.tgz", - "integrity": "sha512-Y5GL4OdA8IU2geRrt2+Uc1iIhsjICdHZzT9tNwQ3TVqdNzgxHToGCKf/TPRP80vTCAP6svg2WbbJL+Gx5MFQVA==", + "version": "23.15.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.15.1.tgz", + "integrity": "sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==", "dev": true, "funding": [ { @@ -23506,9 +23173,9 @@ } }, "node_modules/jest-environment-jsdom/node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -25062,6 +24729,15 @@ "streaming-json-stringify": "3" } }, + "node_modules/koa/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/koa/node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -25111,9 +24787,9 @@ } }, "node_modules/launch-editor": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.1.tgz", - "integrity": "sha512-elBx2l/tp9z99X5H/qev8uyDywVh0VXAwEbjk8kJhnc5grOFkGh7aW6q55me9xnYbss261XtnUrysZ+XvGbhQA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", "dev": true, "license": "MIT", "dependencies": { @@ -25622,9 +25298,9 @@ } }, "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "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": { @@ -26010,9 +25686,9 @@ } }, "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "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": { @@ -26177,9 +25853,9 @@ } }, "node_modules/loglevel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", - "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "dev": true, "license": "MIT", "engines": { @@ -26975,11 +26651,14 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -28101,9 +27780,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/multer": { @@ -28412,9 +28091,9 @@ } }, "node_modules/node-abi": { - "version": "3.67.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.67.0.tgz", - "integrity": "sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==", + "version": "3.68.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz", + "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", "dev": true, "license": "MIT", "dependencies": { @@ -29597,9 +29276,9 @@ "license": "MIT" }, "node_modules/ohash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", - "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz", + "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==", "dev": true, "license": "MIT" }, @@ -30535,9 +30214,9 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "license": "MIT" }, "node_modules/path-type": { @@ -30581,9 +30260,9 @@ } }, "node_modules/pdfmake": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.12.tgz", - "integrity": "sha512-TFsqaG6KVtk+TWermmJNNwom3wmB/xiz07prM74KBhdM+7pz3Uwq2b0uoqhhQRn6cYUTpL8lXZY6xF011o1YcQ==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.13.tgz", + "integrity": "sha512-qeVE9Bzjm0oPCitH4/HYM/XCGTwoeOAOVAXPnV3s0kpPvTLkTF/bAF4jzorjkaIhXGQhzYk6Xclt0hMDYLY93w==", "dev": true, "license": "MIT", "dependencies": { @@ -30593,7 +30272,7 @@ "xmldoc": "^1.1.2" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/pend": { @@ -30604,9 +30283,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "license": "ISC" }, "node_modules/picomatch": { @@ -31583,9 +31262,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "license": "MIT", "dependencies": { @@ -31712,12 +31391,12 @@ "license": "GPL-3.0" }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -32302,9 +31981,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "license": "MIT", "dependencies": { @@ -33129,9 +32808,9 @@ } }, "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -33142,15 +32821,12 @@ }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", "dev": true, "license": "ISC", "engines": { @@ -33218,9 +32894,9 @@ "optional": true }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "license": "MIT", "bin": { @@ -33645,9 +33321,9 @@ "license": "ISC" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { @@ -33686,6 +33362,16 @@ "dev": true, "license": "MIT" }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -33699,13 +33385,6 @@ "node": ">=4" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", @@ -33834,16 +33513,16 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -34550,9 +34229,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -35152,9 +34831,9 @@ } }, "node_modules/streamx": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.0.tgz", - "integrity": "sha512-ZGd1LhDeGFucr1CUCTBOS58ZhEendd0ttpGT3usTvosS4ntIwKN9LJFp+OeCSprsCPL14BXVRZlHGRY1V9PVzQ==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", "dev": true, "license": "MIT", "dependencies": { @@ -35953,9 +35632,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", - "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -36040,9 +35719,9 @@ } }, "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -36245,9 +35924,9 @@ } }, "node_modules/tldts-core": { - "version": "6.1.46", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.46.tgz", - "integrity": "sha512-zA3ai/j4aFcmbqTvTONkSBuWs0Q4X4tJxa0gV9sp6kDbq5dAhQDSg0WUkReEm0fBAKAGNj+wPKCCsR8MYOYmwA==", + "version": "6.1.47", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz", + "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==", "license": "MIT" }, "node_modules/tmp": { @@ -36477,9 +36156,9 @@ } }, "node_modules/traverse": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz", - "integrity": "sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==", + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.10.tgz", + "integrity": "sha512-hN4uFRxbK+PX56DxYiGHsTn2dME3TVr9vbNqlQGcGcPhJAn+tdP126iA+TArMpI4YSgnTkMWyoLl5bf81Hi5TA==", "dev": true, "license": "MIT", "dependencies": { @@ -37282,9 +36961,9 @@ "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", "engines": { @@ -37306,9 +36985,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "license": "MIT", "engines": { @@ -37551,18 +37230,25 @@ } }, "node_modules/unplugin": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.12.3.tgz", - "integrity": "sha512-my8DH0/T/Kx33KO+6QXAqdeMYgyy0GktlOpdQjpagfHKw5DrD0ctPr7SHUyOT3g4ZVpzCQGt/qcpuoKJ/pniHA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz", + "integrity": "sha512-lBlHbfSFPToDYp9pjXlUEFVxYLaue9f9T1HC+4OHlmj+HnMDdz9oZY+erXfoCe/5V/7gKUSY2jpXPb9S7f0f/w==", "dev": true, "license": "MIT", "dependencies": { "acorn": "^8.12.1", - "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.6.2" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "webpack-sources": "^3" + }, + "peerDependenciesMeta": { + "webpack-sources": { + "optional": true + } } }, "node_modules/unset-value": { @@ -37711,22 +37397,6 @@ "dev": true, "license": "MIT" }, - "node_modules/url/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -38600,9 +38270,9 @@ } }, "node_modules/webpack-dev-server/node_modules/memfs": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", - "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.12.0.tgz", + "integrity": "sha512-74wDsex5tQDSClVkeK1vtxqYCAgCoXxx+K4NSHzgU/muYVYByFqa+0RnrPO9NM6naWm1+G9JmZ0p6QHhXmeYfA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -39196,9 +38866,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index b073cd27d87..a9d4f18e2fd 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@storybook/manager-api": "8.2.9", "@storybook/theming": "8.2.9", "@types/argon2-browser": "1.18.4", - "@types/chrome": "0.0.270", + "@types/chrome": "0.0.272", "@types/firefox-webext-browser": "111.0.5", "@types/inquirer": "8.2.10", "@types/jest": "29.5.12", @@ -209,7 +209,8 @@ "@storybook/angular": { "zone.js": "$zone.js" }, - "replacestream": "4.0.3" + "replacestream": "4.0.3", + "@types/minimatch": "3.0.5" }, "lint-staged": { "*": "prettier --cache --ignore-unknown --write",