From 962e8e0b23672674c0a29bee47e9f77ea3696b5e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 10 Nov 2022 09:27:20 +0000 Subject: [PATCH] Differentiate download and decryption errors when showing images (#9562) --- package.json | 1 + src/components/views/messages/MImageBody.tsx | 20 ++- src/i18n/strings/en_EN.json | 2 + src/utils/DecryptFile.ts | 47 +++++-- src/utils/LazyValue.ts | 6 +- .../views/messages/MImageBody-test.tsx | 99 ++++++++++++++ yarn.lock | 128 ++---------------- 7 files changed, 170 insertions(+), 133 deletions(-) create mode 100644 test/components/views/messages/MImageBody-test.tsx diff --git a/package.json b/package.json index e6d837880a..86af00b184 100644 --- a/package.json +++ b/package.json @@ -202,6 +202,7 @@ "jest-raw-loader": "^1.0.1", "matrix-mock-request": "^2.5.0", "matrix-web-i18n": "^1.3.0", + "node-fetch": "2", "postcss-scss": "^4.0.4", "raw-loader": "^4.0.2", "react-test-renderer": "^17.0.2", diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index da579664b2..43adf41d8c 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -39,6 +39,7 @@ import { blobIsAnimated, mayBeAnimated } from '../../../utils/Image'; import { presentableTextForFile } from "../../../utils/FileUtils"; import { createReconnectedListener } from '../../../utils/connection'; import MediaProcessingError from './shared/MediaProcessingError'; +import { DecryptError, DownloadError } from "../../../utils/DecryptFile"; enum Placeholder { NoImage, @@ -258,7 +259,15 @@ export default class MImageBody extends React.Component { ])); } catch (error) { if (this.unmounted) return; - logger.warn("Unable to decrypt attachment: ", error); + + if (error instanceof DecryptError) { + logger.error("Unable to decrypt attachment: ", error); + } else if (error instanceof DownloadError) { + logger.error("Unable to download attachment to decrypt it: ", error); + } else { + logger.error("Error encountered when downloading encrypted attachment: ", error); + } + // Set a placeholder image when we can't decrypt the image. this.setState({ error }); } @@ -557,9 +566,16 @@ export default class MImageBody extends React.Component { const content = this.props.mxEvent.getContent(); if (this.state.error) { + let errorText = _t("Unable to show image due to error"); + if (this.state.error instanceof DecryptError) { + errorText = _t("Error decrypting image"); + } else if (this.state.error instanceof DownloadError) { + errorText = _t("Error downloading image"); + } + return ( - { _t("Error decrypting image") } + { errorText } ); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f5913e50d2..93c49ccce1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2312,7 +2312,9 @@ "Decrypt %(text)s": "Decrypt %(text)s", "Invalid file%(extra)s": "Invalid file%(extra)s", "Image": "Image", + "Unable to show image due to error": "Unable to show image due to error", "Error decrypting image": "Error decrypting image", + "Error downloading image": "Error downloading image", "Show image": "Show image", "Join the conference at the top of this room": "Join the conference at the top of this room", "Join the conference from the room information card on the right": "Join the conference from the room information card on the right", diff --git a/src/utils/DecryptFile.ts b/src/utils/DecryptFile.ts index 7e8bcf1a99..dbcb0a85ed 100644 --- a/src/utils/DecryptFile.ts +++ b/src/utils/DecryptFile.ts @@ -16,11 +16,28 @@ limitations under the License. // Pull in the encryption lib so that we can decrypt attachments. import encrypt from 'matrix-encrypt-attachment'; +import { parseErrorResponse } from 'matrix-js-sdk/src/http-api'; import { mediaFromContent } from "../customisations/Media"; import { IEncryptedFile, IMediaEventInfo } from "../customisations/models/IMediaEventContent"; import { getBlobSafeMimeType } from "./blobs"; +export class DownloadError extends Error { + constructor(e) { + super(e.message); + this.name = "DownloadError"; + this.stack = e.stack; + } +} + +export class DecryptError extends Error { + constructor(e) { + super(e.message); + this.name = "DecryptError"; + this.stack = e.stack; + } +} + /** * Decrypt a file attached to a matrix event. * @param {IEncryptedFile} file The encrypted file information taken from the matrix event. @@ -30,19 +47,27 @@ import { getBlobSafeMimeType } from "./blobs"; * @param {IMediaEventInfo} info The info parameter taken from the matrix event. * @returns {Promise} Resolves to a Blob of the file. */ -export function decryptFile( +export async function decryptFile( file: IEncryptedFile, info?: IMediaEventInfo, ): Promise { const media = mediaFromContent({ file }); - // Download the encrypted file as an array buffer. - return media.downloadSource().then((response) => { - return response.arrayBuffer(); - }).then((responseData) => { - // Decrypt the array buffer using the information taken from - // the event content. - return encrypt.decryptAttachment(responseData, file); - }).then((dataArray) => { + + let responseData: ArrayBuffer; + try { + // Download the encrypted file as an array buffer. + const response = await media.downloadSource(); + if (!response.ok) { + throw parseErrorResponse(response, await response.text()); + } + responseData = await response.arrayBuffer(); + } catch (e) { + throw new DownloadError(e); + } + + try { + // Decrypt the array buffer using the information taken from the event content. + const dataArray = await encrypt.decryptAttachment(responseData, file); // Turn the array into a Blob and give it the correct MIME-type. // IMPORTANT: we must not allow scriptable mime-types into Blobs otherwise @@ -53,5 +78,7 @@ export function decryptFile( mimetype = getBlobSafeMimeType(mimetype); return new Blob([dataArray], { type: mimetype }); - }); + } catch (e) { + throw new DecryptError(e); + } } diff --git a/src/utils/LazyValue.ts b/src/utils/LazyValue.ts index 70ffb1106c..f73cbd43d5 100644 --- a/src/utils/LazyValue.ts +++ b/src/utils/LazyValue.ts @@ -48,12 +48,10 @@ export class LazyValue { if (this.prom) return this.prom; this.prom = this.getFn(); - // Fork the promise chain to avoid accidentally making it return undefined always. - this.prom.then(v => { + return this.prom.then(v => { this.val = v; this.done = true; + return v; }); - - return this.prom; } } diff --git a/test/components/views/messages/MImageBody-test.tsx b/test/components/views/messages/MImageBody-test.tsx new file mode 100644 index 0000000000..b2cbb85602 --- /dev/null +++ b/test/components/views/messages/MImageBody-test.tsx @@ -0,0 +1,99 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from "react"; +import { render, screen } from "@testing-library/react"; +import { EventType, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; +import fetchMock from "fetch-mock-jest"; +import encrypt from "matrix-encrypt-attachment"; +import { mocked } from "jest-mock"; + +import MImageBody from "../../../../src/components/views/messages/MImageBody"; +import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; +import { + getMockClientWithEventEmitter, + mockClientMethodsCrypto, + mockClientMethodsDevice, + mockClientMethodsServer, + mockClientMethodsUser, +} from "../../../test-utils"; +import { MediaEventHelper } from "../../../../src/utils/MediaEventHelper"; + +jest.mock("matrix-encrypt-attachment", () => ({ + decryptAttachment: jest.fn(), +})); + +describe("", () => { + const userId = "@user:server"; + const deviceId = "DEADB33F"; + const cli = getMockClientWithEventEmitter({ + ...mockClientMethodsUser(userId), + ...mockClientMethodsServer(), + ...mockClientMethodsDevice(deviceId), + ...mockClientMethodsCrypto(), + getRooms: jest.fn().mockReturnValue([]), + getIgnoredUsers: jest.fn(), + getVersions: jest.fn().mockResolvedValue({ + unstable_features: { + 'org.matrix.msc3882': true, + 'org.matrix.msc3886': true, + }, + }), + }); + const url = "https://server/_matrix/media/r0/download/server/encrypted-image"; + // eslint-disable-next-line no-restricted-properties + cli.mxcUrlToHttp.mockReturnValue(url); + const encryptedMediaEvent = new MatrixEvent({ + room_id: "!room:server", + sender: userId, + type: EventType.RoomMessage, + content: { + file: { + url: "mxc://server/encrypted-image", + }, + }, + }); + const props = { + onHeightChanged: jest.fn(), + onMessageAllowed: jest.fn(), + permalinkCreator: new RoomPermalinkCreator(new Room(encryptedMediaEvent.getRoomId(), cli, cli.getUserId())), + }; + + it("should show error when encrypted media cannot be downloaded", async () => { + fetchMock.getOnce(url, { status: 500 }); + + render(); + + await screen.findByText("Error downloading image"); + }); + + it("should show error when encrypted media cannot be decrypted", async () => { + fetchMock.getOnce(url, "thisistotallyanencryptedpng"); + mocked(encrypt.decryptAttachment).mockRejectedValue(new Error("Failed to decrypt")); + + render(); + + await screen.findByText("Error decrypting image"); + }); +}); diff --git a/yarn.lock b/yarn.lock index 596efcf468..7152c5bd4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2754,11 +2754,6 @@ object.fromentries "^2.0.0" prop-types "^15.7.0" -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -3481,7 +3476,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3845,7 +3840,7 @@ crc-32@^0.3.0: resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-0.3.0.tgz#6a3d3687f5baec41f7e9b99fe1953a2e5d19775e" integrity sha512-kucVIjOmMc1f0tv53BJ/5WIX+MGLcKuoBhnGqQrgKJNqLByb/sVMWfW/Aw6hw0jgcqjJ2pi9E5y32zOIpaUlsA== -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -5148,13 +5143,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -5238,15 +5226,6 @@ fs-extra@^10.0.1: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -5465,7 +5444,7 @@ globjoin@^0.1.4: resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" integrity sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg== -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -5887,11 +5866,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -6068,13 +6042,6 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -6813,13 +6780,6 @@ json5@^2.1.2, json5@^2.2.1: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -6893,13 +6853,6 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -7208,8 +7161,6 @@ matrix-events-sdk@0.0.1: matrix-events-sdk "0.0.1" matrix-widget-api "^1.0.0" p-retry "4" - patch-package "^6.5.0" - postinstall-postinstall "^2.1.0" qs "^6.9.6" sdp-transform "^2.14.1" unhomoglyph "^1.0.6" @@ -7452,6 +7403,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@2, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -7460,13 +7418,6 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -7640,14 +7591,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -7677,11 +7620,6 @@ opus-recorder@^8.0.3: resolved "https://registry.yarnpkg.com/opus-recorder/-/opus-recorder-8.0.5.tgz#06d3e32e15da57ebc3f57e41b93033475fcb4e3e" integrity sha512-tBRXc9Btds7i3bVfA7d5rekAlyOcfsivt5vSIXHxRV1Oa+s6iXFW8omZ0Lm3ABWotVcEyKt96iIIUcgbV07YOw== -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - ospath@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" @@ -7804,26 +7742,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== -patch-package@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.0.tgz#feb058db56f0005da59cfa316488321de585e88a" - integrity sha512-tC3EqJmo74yKqfsMzELaFwxOAu6FH6t+FzFOsnWAuARm7/n2xB5AOeOueE221eM9gtMuIKMKpF9tBy/X2mNP0Q== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^2.0.0" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -8002,11 +7920,6 @@ posthog-js@1.12.2: dependencies: fflate "^0.4.1" -postinstall-postinstall@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" - integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== - potpack@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" @@ -8603,13 +8516,6 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -9322,13 +9228,6 @@ tinyqueue@^2.0.3: resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08" integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmp@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -9605,11 +9504,6 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" @@ -9973,7 +9867,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==