Add compat with openssl 3
This commit is contained in:
parent
0667dbaf26
commit
5d7cb63ede
|
@ -102,7 +102,7 @@
|
||||||
"@opentelemetry/sdk-trace-node": "^1.3.1",
|
"@opentelemetry/sdk-trace-node": "^1.3.1",
|
||||||
"@opentelemetry/semantic-conventions": "^1.3.1",
|
"@opentelemetry/semantic-conventions": "^1.3.1",
|
||||||
"@peertube/feed": "^5.0.1",
|
"@peertube/feed": "^5.0.1",
|
||||||
"@peertube/http-signature": "^1.6.0",
|
"@peertube/http-signature": "^1.7.0",
|
||||||
"@uploadx/core": "^5.1.2",
|
"@uploadx/core": "^5.1.2",
|
||||||
"async": "^3.0.1",
|
"async": "^3.0.1",
|
||||||
"async-lru": "^1.1.1",
|
"async-lru": "^1.1.1",
|
||||||
|
@ -151,7 +151,6 @@
|
||||||
"nodemailer": "^6.0.0",
|
"nodemailer": "^6.0.0",
|
||||||
"parse-torrent": "^9.1.0",
|
"parse-torrent": "^9.1.0",
|
||||||
"password-generator": "^2.0.2",
|
"password-generator": "^2.0.2",
|
||||||
"pem": "^1.12.3",
|
|
||||||
"pg": "^8.2.1",
|
"pg": "^8.2.1",
|
||||||
"piscina": "^3.2.0",
|
"piscina": "^3.2.0",
|
||||||
"prompt": "^1.0.0",
|
"prompt": "^1.0.0",
|
||||||
|
@ -206,7 +205,6 @@
|
||||||
"@types/node": "^14.14.31",
|
"@types/node": "^14.14.31",
|
||||||
"@types/nodemailer": "^6.2.0",
|
"@types/nodemailer": "^6.2.0",
|
||||||
"@types/oauth2-server": "^3.0.8",
|
"@types/oauth2-server": "^3.0.8",
|
||||||
"@types/pem": "^1.9.3",
|
|
||||||
"@types/request": "^2.0.3",
|
"@types/request": "^2.0.3",
|
||||||
"@types/supertest": "^2.0.3",
|
"@types/supertest": "^2.0.3",
|
||||||
"@types/validator": "^13.0.0",
|
"@types/validator": "^13.0.0",
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { exec, ExecOptions } from 'child_process'
|
import { exec, ExecOptions } from 'child_process'
|
||||||
import { randomBytes } from 'crypto'
|
import { ED25519KeyPairOptions, generateKeyPair, randomBytes, RSAKeyPairOptions } from 'crypto'
|
||||||
import { truncate } from 'lodash'
|
import { truncate } from 'lodash'
|
||||||
import { createPrivateKey as createPrivateKey_1, getPublicKey as getPublicKey_1 } from 'pem'
|
|
||||||
import { pipeline } from 'stream'
|
import { pipeline } from 'stream'
|
||||||
import { URL } from 'url'
|
import { URL } from 'url'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
|
@ -242,6 +241,51 @@ function toEven (num: number) {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function generateRSAKeyPairPromise (size: number) {
|
||||||
|
return new Promise<{ publicKey: string, privateKey: string }>((res, rej) => {
|
||||||
|
const options: RSAKeyPairOptions<'pem', 'pem'> = {
|
||||||
|
modulusLength: size,
|
||||||
|
publicKeyEncoding: {
|
||||||
|
type: 'spki',
|
||||||
|
format: 'pem'
|
||||||
|
},
|
||||||
|
privateKeyEncoding: {
|
||||||
|
type: 'pkcs1',
|
||||||
|
format: 'pem'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateKeyPair('rsa', options, (err, publicKey, privateKey) => {
|
||||||
|
if (err) return rej(err)
|
||||||
|
|
||||||
|
return res({ publicKey, privateKey })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateED25519KeyPairPromise () {
|
||||||
|
return new Promise<{ publicKey: string, privateKey: string }>((res, rej) => {
|
||||||
|
const options: ED25519KeyPairOptions<'pem', 'pem'> = {
|
||||||
|
publicKeyEncoding: {
|
||||||
|
type: 'spki',
|
||||||
|
format: 'pem'
|
||||||
|
},
|
||||||
|
privateKeyEncoding: {
|
||||||
|
type: 'pkcs8',
|
||||||
|
format: 'pem'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateKeyPair('ed25519', options, (err, publicKey, privateKey) => {
|
||||||
|
if (err) return rej(err)
|
||||||
|
|
||||||
|
return res({ publicKey, privateKey })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> {
|
function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> {
|
||||||
return function promisified (): Promise<A> {
|
return function promisified (): Promise<A> {
|
||||||
return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
|
return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
|
||||||
|
@ -268,8 +312,6 @@ function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A)
|
||||||
}
|
}
|
||||||
|
|
||||||
const randomBytesPromise = promisify1<number, Buffer>(randomBytes)
|
const randomBytesPromise = promisify1<number, Buffer>(randomBytes)
|
||||||
const createPrivateKey = promisify1<number, { key: string }>(createPrivateKey_1)
|
|
||||||
const getPublicKey = promisify1<string, { publicKey: string }>(getPublicKey_1)
|
|
||||||
const execPromise2 = promisify2<string, any, string>(exec)
|
const execPromise2 = promisify2<string, any, string>(exec)
|
||||||
const execPromise = promisify1<string, string>(exec)
|
const execPromise = promisify1<string, string>(exec)
|
||||||
const pipelinePromise = promisify(pipeline)
|
const pipelinePromise = promisify(pipeline)
|
||||||
|
@ -298,8 +340,10 @@ export {
|
||||||
promisify2,
|
promisify2,
|
||||||
|
|
||||||
randomBytesPromise,
|
randomBytesPromise,
|
||||||
createPrivateKey,
|
|
||||||
getPublicKey,
|
generateRSAKeyPairPromise,
|
||||||
|
generateED25519KeyPairPromise,
|
||||||
|
|
||||||
execPromise2,
|
execPromise2,
|
||||||
execPromise,
|
execPromise,
|
||||||
pipelinePromise,
|
pipelinePromise,
|
||||||
|
|
|
@ -41,9 +41,9 @@ function isActorPreferredUsernameValid (preferredUsername: string) {
|
||||||
function isActorPrivateKeyValid (privateKey: string) {
|
function isActorPrivateKeyValid (privateKey: string) {
|
||||||
return exists(privateKey) &&
|
return exists(privateKey) &&
|
||||||
typeof privateKey === 'string' &&
|
typeof privateKey === 'string' &&
|
||||||
privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') &&
|
(privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') || privateKey.startsWith('-----BEGIN PRIVATE KEY-----')) &&
|
||||||
// Sometimes there is a \n at the end, so just assert the string contains the end mark
|
// Sometimes there is a \n at the end, so just assert the string contains the end mark
|
||||||
privateKey.includes('-----END RSA PRIVATE KEY-----') &&
|
(privateKey.includes('-----END RSA PRIVATE KEY-----') || privateKey.includes('-----END PRIVATE KEY-----')) &&
|
||||||
validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY)
|
validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { cloneDeep } from 'lodash'
|
||||||
import { sha256 } from '@shared/extra-utils'
|
import { sha256 } from '@shared/extra-utils'
|
||||||
import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants'
|
import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants'
|
||||||
import { MActor } from '../types/models'
|
import { MActor } from '../types/models'
|
||||||
import { createPrivateKey, getPublicKey, promisify1, promisify2 } from './core-utils'
|
import { generateRSAKeyPairPromise, promisify1, promisify2 } from './core-utils'
|
||||||
import { jsonld } from './custom-jsonld-signature'
|
import { jsonld } from './custom-jsonld-signature'
|
||||||
import { logger } from './logger'
|
import { logger } from './logger'
|
||||||
|
|
||||||
|
@ -15,13 +15,10 @@ const bcryptHashPromise = promisify2<any, string | number, string>(hash)
|
||||||
|
|
||||||
const httpSignature = require('@peertube/http-signature')
|
const httpSignature = require('@peertube/http-signature')
|
||||||
|
|
||||||
async function createPrivateAndPublicKeys () {
|
function createPrivateAndPublicKeys () {
|
||||||
logger.info('Generating a RSA key...')
|
logger.info('Generating a RSA key...')
|
||||||
|
|
||||||
const { key } = await createPrivateKey(PRIVATE_RSA_KEY_SIZE)
|
return generateRSAKeyPairPromise(PRIVATE_RSA_KEY_SIZE)
|
||||||
const { publicKey } = await getPublicKey(key)
|
|
||||||
|
|
||||||
return { privateKey: key, publicKey }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// User password checks
|
// User password checks
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as Sequelize from 'sequelize'
|
import * as Sequelize from 'sequelize'
|
||||||
import { createPrivateKey, getPublicKey } from '../../helpers/core-utils'
|
import { generateRSAKeyPairPromise } from '../../helpers/core-utils'
|
||||||
import { PRIVATE_RSA_KEY_SIZE } from '../constants'
|
import { PRIVATE_RSA_KEY_SIZE } from '../constants'
|
||||||
|
|
||||||
async function up (utils: {
|
async function up (utils: {
|
||||||
|
@ -15,10 +15,9 @@ async function up (utils: {
|
||||||
const actors = await utils.sequelize.query<any>(query, options)
|
const actors = await utils.sequelize.query<any>(query, options)
|
||||||
|
|
||||||
for (const actor of actors) {
|
for (const actor of actors) {
|
||||||
const { key } = await createPrivateKey(PRIVATE_RSA_KEY_SIZE)
|
const { privateKey, publicKey } = await generateRSAKeyPairPromise(PRIVATE_RSA_KEY_SIZE)
|
||||||
const { publicKey } = await getPublicKey(key)
|
|
||||||
|
|
||||||
const queryUpdate = `UPDATE "actor" SET "publicKey" = '${publicKey}', "privateKey" = '${key}' WHERE id = ${actor.id}`
|
const queryUpdate = `UPDATE "actor" SET "publicKey" = '${publicKey}', "privateKey" = '${privateKey}' WHERE id = ${actor.id}`
|
||||||
await utils.sequelize.query(queryUpdate)
|
await utils.sequelize.query(queryUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
58
yarn.lock
58
yarn.lock
|
@ -1780,10 +1780,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
xml-js "^1.6.11"
|
xml-js "^1.6.11"
|
||||||
|
|
||||||
"@peertube/http-signature@^1.6.0":
|
"@peertube/http-signature@^1.7.0":
|
||||||
version "1.6.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@peertube/http-signature/-/http-signature-1.6.0.tgz#22bef028384e6437e8dbd94052ba7b8bd7f7f1ae"
|
resolved "https://registry.yarnpkg.com/@peertube/http-signature/-/http-signature-1.7.0.tgz#12a84f3fc62e786aa3a2eb09426417bad65736dc"
|
||||||
integrity sha512-Bx780c7FPYtkV4LgCoaJcXYcKQqaMef2iQR2V2r5klkYkIQWFxbTOpyhKxvVXYIBIFpj5Cb8DGVDAmhkm7aavg==
|
integrity sha512-aGQIwo6/sWtyyqhVK4e1MtxYz4N1X8CNt6SOtCc+Wnczs5S5ONaLHDDR8LYaGn0MgOwvGgXyuZ5sJIfd7iyoUw==
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
jsprim "^1.2.2"
|
jsprim "^1.2.2"
|
||||||
|
@ -2221,13 +2221,6 @@
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
"@types/parse-torrent-file" "*"
|
"@types/parse-torrent-file" "*"
|
||||||
|
|
||||||
"@types/pem@^1.9.3":
|
|
||||||
version "1.9.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/pem/-/pem-1.9.6.tgz#c3686832e935947fdd9d848dec3b8fe830068de7"
|
|
||||||
integrity sha512-IC67SxacM9fxEi/w7hf98dTun83OwUMeLMo1NS2gE0wdM9MHeg73iH/Pp9nB02OUCQ7Zb2UuKE/IpFCmQw9jxw==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
|
|
||||||
"@types/pg-pool@2.0.3":
|
"@types/pg-pool@2.0.3":
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.3.tgz#3eb8df2933f617f219a53091ad4080c94ba1c959"
|
resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.3.tgz#3eb8df2933f617f219a53091ad4080c94ba1c959"
|
||||||
|
@ -3332,11 +3325,6 @@ character-parser@^2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-regex "^1.0.3"
|
is-regex "^1.0.3"
|
||||||
|
|
||||||
charenc@0.0.2:
|
|
||||||
version "0.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
|
||||||
integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
|
|
||||||
|
|
||||||
charset-detector@0.0.2:
|
charset-detector@0.0.2:
|
||||||
version "0.0.2"
|
version "0.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/charset-detector/-/charset-detector-0.0.2.tgz#1cd5ddaf56e83259c6ef8e906ccf06f75fe9a1b2"
|
resolved "https://registry.yarnpkg.com/charset-detector/-/charset-detector-0.0.2.tgz#1cd5ddaf56e83259c6ef8e906ccf06f75fe9a1b2"
|
||||||
|
@ -3778,11 +3766,6 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||||
shebang-command "^2.0.0"
|
shebang-command "^2.0.0"
|
||||||
which "^2.0.1"
|
which "^2.0.1"
|
||||||
|
|
||||||
crypt@0.0.2:
|
|
||||||
version "0.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
|
||||||
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
|
|
||||||
|
|
||||||
css-select@^5.1.0:
|
css-select@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
|
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
|
||||||
|
@ -4314,11 +4297,6 @@ es6-iterator@^2.0.3:
|
||||||
es5-ext "^0.10.35"
|
es5-ext "^0.10.35"
|
||||||
es6-symbol "^3.1.1"
|
es6-symbol "^3.1.1"
|
||||||
|
|
||||||
es6-promisify@^6.0.0:
|
|
||||||
version "6.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.1.tgz#46837651b7b06bf6fff893d03f29393668d01621"
|
|
||||||
integrity sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==
|
|
||||||
|
|
||||||
es6-symbol@^3.1.1, es6-symbol@^3.1.3:
|
es6-symbol@^3.1.1, es6-symbol@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
|
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
|
||||||
|
@ -5604,11 +5582,6 @@ is-boolean-object@^1.1.0:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-buffer@~1.1.6:
|
|
||||||
version "1.1.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
|
||||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
|
||||||
|
|
||||||
is-callable@^1.1.4, is-callable@^1.2.4:
|
is-callable@^1.1.4, is-callable@^1.2.4:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
||||||
|
@ -6348,15 +6321,6 @@ maxmind@^4.3.6:
|
||||||
mmdb-lib "2.0.2"
|
mmdb-lib "2.0.2"
|
||||||
tiny-lru "8.0.2"
|
tiny-lru "8.0.2"
|
||||||
|
|
||||||
md5@^2.2.1:
|
|
||||||
version "2.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
|
||||||
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
|
||||||
dependencies:
|
|
||||||
charenc "0.0.2"
|
|
||||||
crypt "0.0.2"
|
|
||||||
is-buffer "~1.1.6"
|
|
||||||
|
|
||||||
mdurl@^1.0.1:
|
mdurl@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||||
|
@ -6988,7 +6952,7 @@ optionator@^0.9.1:
|
||||||
type-check "^0.4.0"
|
type-check "^0.4.0"
|
||||||
word-wrap "^1.2.3"
|
word-wrap "^1.2.3"
|
||||||
|
|
||||||
os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
|
os-tmpdir@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
|
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
|
||||||
|
@ -7236,16 +7200,6 @@ peek-stream@^1.1.1:
|
||||||
duplexify "^3.5.0"
|
duplexify "^3.5.0"
|
||||||
through2 "^2.0.3"
|
through2 "^2.0.3"
|
||||||
|
|
||||||
pem@^1.12.3:
|
|
||||||
version "1.14.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/pem/-/pem-1.14.6.tgz#89babca3a73466fb844df70666dbf1b25eb0dc56"
|
|
||||||
integrity sha512-I5GKUer2PPv5qzUfxaZ6IGRkhp+357Kyv2t1JJg9vP8hGGI13qU34N2QupmggbpIZGPuudH0jn8KU5hjFpPk3g==
|
|
||||||
dependencies:
|
|
||||||
es6-promisify "^6.0.0"
|
|
||||||
md5 "^2.2.1"
|
|
||||||
os-tmpdir "^1.0.1"
|
|
||||||
which "^2.0.2"
|
|
||||||
|
|
||||||
pg-connection-string@^2.5.0:
|
pg-connection-string@^2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
|
||||||
|
@ -9332,7 +9286,7 @@ which@^1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
which@^2.0.1, which@^2.0.2:
|
which@^2.0.1:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||||
|
|
Loading…
Reference in New Issue