From 4dc21507a780428d34817ae49535b872cf08a4bd Mon Sep 17 00:00:00 2001 From: zkldi <20380519+zkldi@users.noreply.github.com> Date: Mon, 19 Dec 2022 05:08:56 +0000 Subject: [PATCH] feat: ugh full github bot rewrite with octokit --- github-bot/package.json | 4 +- github-bot/src/config.ts | 4 +- github-bot/src/main.ts | 137 ++++------------- pnpm-lock.yaml | 307 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 339 insertions(+), 113 deletions(-) diff --git a/github-bot/package.json b/github-bot/package.json index 1eb38d434..4a2633e98 100644 --- a/github-bot/package.json +++ b/github-bot/package.json @@ -9,9 +9,7 @@ "start": "tsc -b && node js/main.js" }, "dependencies": { - "@octokit/webhooks": "10.1.5", - "@types/body-parser": "^1.19.2", - "body-parser": "^1.20.0", + "@octokit/app": "^13.1.0", "dotenv": "16.0.0", "express": "4.17.2", "node-fetch": "2.6.7", diff --git a/github-bot/src/config.ts b/github-bot/src/config.ts index e3e4c8f75..39b21076c 100644 --- a/github-bot/src/config.ts +++ b/github-bot/src/config.ts @@ -10,10 +10,10 @@ function ParseEnvVars() { { APP_ID: "string", WEBHOOK_SECRET: "string", + BASE64_PRIVATE_KEY: "string", PORT: (self) => p.isPositiveInteger(Number(self)) === true || "Should be a string representing a whole integer port.", - CLIENT_SECRET: "string", }, {}, { allowExcessKeys: true } @@ -27,7 +27,7 @@ function ParseEnvVars() { appId: process.env.APP_ID!, webhookSecret: process.env.WEBHOOK_SECRET!, port: process.env.PORT!, - clientSecret: process.env.CLIENT_SECRET!, + privateKey: Buffer.from(process.env.BASE64_PRIVATE_KEY!, "base64").toString("utf-8"), }; } diff --git a/github-bot/src/main.ts b/github-bot/src/main.ts index e3a112bbc..dd85960ca 100644 --- a/github-bot/src/main.ts +++ b/github-bot/src/main.ts @@ -1,36 +1,17 @@ /* eslint-disable no-console */ import { ProcessEnv } from "./config"; -import bodyParser from "body-parser"; +import { App, createNodeMiddleware } from "@octokit/app"; import express from "express"; import fetch from "node-fetch"; -import crypto from "crypto"; import { URLSearchParams } from "url"; -import type { EmitterWebhookEvent } from "@octokit/webhooks"; -import type { Express } from "express"; -export const app: Express = express(); - -// Let NGINX work its magic. -app.set("trust proxy", "loopback"); - -// Disable query string nesting such as ?a[b]=4 -> {a: {b: 4}}. This -// almost always results in a painful security vuln. -app.set("query parser", "simple"); - -/** - * Return the status of this bot and the version it's running. - * - * @name GET / - */ -app.get("/", (req, res) => - res.status(200).json({ - success: true, - description: "Github Bot is online!", - body: { - time: Date.now(), - }, - }) -); +const app = new App({ + appId: ProcessEnv.appId, + privateKey: ProcessEnv.privateKey, + webhooks: { + secret: ProcessEnv.webhookSecret, + }, +}); /** * Create a response that contains a link to the seeds diff viewer. @@ -55,94 +36,36 @@ function ConvertGitHubURL(url: string) { return url.replace("https://github.com/", "GitHub:"); } -/** - * Listens for GitHub webhook calls. - * - * @note THIS ENDPOINT DOES NOT PARSE REQ BODY INTO AN OBJECT! - * it instead leaves it as a raw string, which is necessary because GitHub have - * an insane secret checking process. - * - * @name POST /webhook - */ -app.post("/webhook", bodyParser.text({ type: "*/*" }), async (req, res) => { - const hash = crypto - .createHmac("SHA256", ProcessEnv.webhookSecret) - .update(req.body as string) - .digest("hex"); +app.webhooks.on( + ["pull_request.opened", "pull_request.edited"], + async ({ octokit, payload: body }) => { + const filesChanged = (await fetch( + `https://api.github.com/repos/TNG-dev/Tachi/pulls/${body.number}/files` + ).then((r) => r.json())) as Array<{ filename: string }>; - if (`sha256=${hash}` !== req.header("X-Hub-Signature-256")) { - console.log( - `Signatures didn't match. ours="sha256=${hash}" theirs=${req.header( - "X-Hub-Signature-256" - )}` - ); - return res.status(400).json({ - success: false, - description: `Invalid Signature.`, - }); - } - - const event = req.header("X-GitHub-Event"); - - if (event !== "pull_request") { - return res.status(400).json({ - success: false, - description: `Unsupported Event.`, - }); - } - - const body = JSON.parse(req.body as string) as EmitterWebhookEvent<"pull_request">["payload"]; - - if (body.action !== "opened" && body.action !== "edited") { - return res.status(400).json({ - success: false, - description: `We only care about opened/edited pull requests!`, - }); - } - - const filesChanged = (await fetch( - `https://api.github.com/repos/TNG-dev/Tachi/pulls/${body.number}/files` - ).then((r) => r.json())) as Array<{ filename: string }>; - - // if any file modified in this pr is a collection - if (filesChanged.some((k) => k.filename.startsWith("database-seeds/collections"))) { - // post a link to the diff viewer in the PR comments. - await fetch(body.pull_request._links.comments.href, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${ProcessEnv.clientSecret}`, - }, - body: JSON.stringify({ + // if any file modified in this pr is a collection + if (filesChanged.some((k) => k.filename.startsWith("database-seeds/collections"))) { + // post a link to the diff viewer in the PR comments. + await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", { + owner: body.repository.owner.login, + repo: body.repository.name, + issue_number: body.pull_request.number, body: mkSeedDiffViewMsg( body.pull_request.head.repo.url, body.pull_request.head.sha, body.pull_request.base.repo.url, body.pull_request.base.sha ), - }), - }); + }); + } } - - return res.status(200).json({ - success: true, - description: "Handled request.", - body: {}, - }); -}); - -/** - * 404 Handler. If something gets to this point, they haven't matched with anything. - * - * @name ALL * - */ -app.all("*", (req, res) => - res.status(404).json({ - success: false, - description: "Nothing found here.", - }) ); -console.log(`Starting express server on port ${ProcessEnv.port}.`); +const serverMiddleware = createNodeMiddleware(app); -app.listen(ProcessEnv.port); +const expressApp = express(); + +expressApp.use(serverMiddleware); + +console.log(`Listening on port ${ProcessEnv.port}.`); +expressApp.listen(ProcessEnv.port); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 76725e613..244c3603f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -329,6 +329,7 @@ importers: github-bot: specifiers: + '@octokit/app': ^13.1.0 '@octokit/webhooks': 10.1.5 '@types/body-parser': ^1.19.2 '@types/express': 4.17.13 @@ -341,6 +342,7 @@ importers: prudence: 0.9.8 typescript: 4.6.3 dependencies: + '@octokit/app': 13.1.0 '@octokit/webhooks': 10.1.5 '@types/body-parser': 1.19.2 body-parser: 1.20.0 @@ -3255,10 +3257,183 @@ packages: fastq: 1.13.0 dev: true + /@octokit/app/13.1.0: + resolution: {integrity: sha512-w0DCS/+bvrIL0iva89VSSa9YhIy1YHATSXMYrHQtgsBHpbuAnMn7QEknYhuMn/4h2dGg9cNjU+3XeAF5eyNmEA==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-app': 4.0.7 + '@octokit/auth-unauthenticated': 3.0.3 + '@octokit/core': 4.1.0 + '@octokit/oauth-app': 4.2.0 + '@octokit/plugin-paginate-rest': 5.0.1_@octokit+core@4.1.0 + '@octokit/types': 8.0.0 + '@octokit/webhooks': 10.1.5 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/auth-app/4.0.7: + resolution: {integrity: sha512-hjjVCoI/+1oLminVHJPPexguYb9FP4Q60hEHExgy1uAKMMJ5Zf8iJIeRJlIIqneTb4vt7NvUTEj4YDxBLZ1FLg==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-oauth-app': 5.0.4 + '@octokit/auth-oauth-user': 2.0.4 + '@octokit/request': 6.2.2 + '@octokit/request-error': 3.0.1 + '@octokit/types': 8.0.0 + '@types/lru-cache': 5.1.1 + deprecation: 2.3.1 + lru-cache: 6.0.0 + universal-github-app-jwt: 1.1.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/auth-oauth-app/5.0.4: + resolution: {integrity: sha512-zlWuii5hAN50vsV6SJC+uIJ7SMhyWjQMEmKJQxkmNDlieE9LjnkZnbOjqRsfcG7VO7WTl4K8ccpo/3A7Kdpmrw==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-oauth-device': 4.0.3 + '@octokit/auth-oauth-user': 2.0.4 + '@octokit/request': 6.2.2 + '@octokit/types': 8.0.0 + '@types/btoa-lite': 1.0.0 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/auth-oauth-device/4.0.3: + resolution: {integrity: sha512-KPTx5nMntKjNZzzltO3X4T68v22rd7Cp/TcLJXQE2U8aXPcZ9LFuww9q9Q5WUNSu3jwi3lRwzfkPguRfz1R8Vg==} + engines: {node: '>= 14'} + dependencies: + '@octokit/oauth-methods': 2.0.4 + '@octokit/request': 6.2.2 + '@octokit/types': 8.0.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/auth-oauth-user/2.0.4: + resolution: {integrity: sha512-HrbDzTPqz6GcGSOUkR+wSeF3vEqsb9NMsmPja/qqqdiGmlk/Czkxctc3KeWYogHonp62Ml4kjz2VxKawrFsadQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-oauth-device': 4.0.3 + '@octokit/oauth-methods': 2.0.4 + '@octokit/request': 6.2.2 + '@octokit/types': 8.0.0 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/auth-token/3.0.2: + resolution: {integrity: sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 8.0.0 + dev: false + + /@octokit/auth-unauthenticated/3.0.3: + resolution: {integrity: sha512-IyfLo1T5GmIC9+07hHGlD3gHtZI1Bona8PLhHXUnwcYDuZt0BhjlNJDYMoPG21C4r7v7+ZSxQHBKrGgkxpYb7A==} + engines: {node: '>= 14'} + dependencies: + '@octokit/request-error': 3.0.1 + '@octokit/types': 8.0.0 + dev: false + + /@octokit/core/4.1.0: + resolution: {integrity: sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-token': 3.0.2 + '@octokit/graphql': 5.0.4 + '@octokit/request': 6.2.2 + '@octokit/request-error': 3.0.1 + '@octokit/types': 8.0.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/endpoint/7.0.3: + resolution: {integrity: sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 8.0.0 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/graphql/5.0.4: + resolution: {integrity: sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==} + engines: {node: '>= 14'} + dependencies: + '@octokit/request': 6.2.2 + '@octokit/types': 8.0.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/oauth-app/4.2.0: + resolution: {integrity: sha512-gyGclT77RQMkVUEW3YBeAKY+LBSc5u3eC9Wn/Uwt3WhuKuu9mrV18EnNpDqmeNll+mdV02yyBROU29Tlili6gg==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-oauth-app': 5.0.4 + '@octokit/auth-oauth-user': 2.0.4 + '@octokit/auth-unauthenticated': 3.0.3 + '@octokit/core': 4.1.0 + '@octokit/oauth-authorization-url': 5.0.0 + '@octokit/oauth-methods': 2.0.4 + '@types/aws-lambda': 8.10.109 + fromentries: 1.3.2 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/oauth-authorization-url/5.0.0: + resolution: {integrity: sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg==} + engines: {node: '>= 14'} + dev: false + + /@octokit/oauth-methods/2.0.4: + resolution: {integrity: sha512-RDSa6XL+5waUVrYSmOlYROtPq0+cfwppP4VaQY/iIei3xlFb0expH6YNsxNrZktcLhJWSpm9uzeom+dQrXlS3A==} + engines: {node: '>= 14'} + dependencies: + '@octokit/oauth-authorization-url': 5.0.0 + '@octokit/request': 6.2.2 + '@octokit/request-error': 3.0.1 + '@octokit/types': 8.0.0 + btoa-lite: 1.0.0 + transitivePeerDependencies: + - encoding + dev: false + /@octokit/openapi-types/13.12.0: resolution: {integrity: sha512-1QYzZrwnn3rTQE7ZoSxXrO8lhu0aIbac1c+qIPOPEaVXBWSaUyLV1x9yt4uDQOwmu6u5ywVS8OJgs+ErDLf6vQ==} dev: false + /@octokit/openapi-types/14.0.0: + resolution: {integrity: sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==} + dev: false + + /@octokit/plugin-paginate-rest/5.0.1_@octokit+core@4.1.0: + resolution: {integrity: sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==} + engines: {node: '>= 14'} + peerDependencies: + '@octokit/core': '>=4' + dependencies: + '@octokit/core': 4.1.0 + '@octokit/types': 8.0.0 + dev: false + /@octokit/request-error/3.0.1: resolution: {integrity: sha512-ym4Bp0HTP7F3VFssV88WD1ZyCIRoE8H35pXSKwLeMizcdZAYc/t6N9X9Yr9n6t3aG9IH75XDnZ6UeZph0vHMWQ==} engines: {node: '>= 14'} @@ -3268,12 +3443,32 @@ packages: once: 1.4.0 dev: false + /@octokit/request/6.2.2: + resolution: {integrity: sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==} + engines: {node: '>= 14'} + dependencies: + '@octokit/endpoint': 7.0.3 + '@octokit/request-error': 3.0.1 + '@octokit/types': 8.0.0 + is-plain-object: 5.0.0 + node-fetch: 2.6.7 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + /@octokit/types/7.5.1: resolution: {integrity: sha512-Zk4OUMLCSpXNI8KZZn47lVLJSsgMyCimsWWQI5hyjZg7hdYm0kjotaIkbG0Pp8SfU2CofMBzonboTqvzn3FrJA==} dependencies: '@octokit/openapi-types': 13.12.0 dev: false + /@octokit/types/8.0.0: + resolution: {integrity: sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==} + dependencies: + '@octokit/openapi-types': 14.0.0 + dev: false + /@octokit/webhooks-methods/3.0.0: resolution: {integrity: sha512-FAIyAchH9JUKXugKMC17ERAXM/56vVJekwXOON46pmUDYfU7uXB4cFY8yc8nYr5ABqVI7KjRKfFt3mZF7OcyUA==} engines: {node: '>= 14'} @@ -3404,6 +3599,10 @@ packages: /@tsconfig/node16/1.0.3: resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + /@types/aws-lambda/8.10.109: + resolution: {integrity: sha512-/ME92FneNyXQzrAfcnQQlW1XkCZGPDlpi2ao1MJwecN+6SbeonKeggU8eybv1DfKli90FAVT1MlIZVXfwVuCyg==} + dev: false + /@types/bcryptjs/2.4.2: resolution: {integrity: sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==} dev: false @@ -3420,6 +3619,10 @@ packages: '@types/node': 16.11.7 dev: false + /@types/btoa-lite/1.0.0: + resolution: {integrity: sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==} + dev: false + /@types/bunyan/1.8.8: resolution: {integrity: sha512-Cblq+Yydg3u+sGiz2mjHjC5MPmdjY+No4qvHrF+BUhblsmSfMvsHLbOG62tPbonsqBj6sbWv1LHcsoe5Jw+/Ow==} dependencies: @@ -3543,6 +3746,12 @@ packages: json5: 2.2.1 dev: true + /@types/jsonwebtoken/8.5.9: + resolution: {integrity: sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==} + dependencies: + '@types/node': 16.11.7 + dev: false + /@types/lodash.get/4.4.7: resolution: {integrity: sha512-af34Mj+KdDeuzsJBxc/XeTtOx0SZHZNLd+hdrn+PcKGQs0EG2TJTzQAOTCZTgDJCArahlCzLWSy8c2w59JRz7Q==} dependencies: @@ -3552,6 +3761,10 @@ packages: /@types/lodash/4.14.172: resolution: {integrity: sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==} + /@types/lru-cache/5.1.1: + resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + dev: false + /@types/luxon/1.27.1: resolution: {integrity: sha512-cPiXpOvPFDr2edMnOXlz3UBDApwUfR+cpizvxCy0n3vp9bz/qe8BWzHPIEFcy+ogUOyjKuCISgyq77ELZPmkkg==} dev: true @@ -4563,6 +4776,10 @@ packages: resolution: {integrity: sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=} dev: false + /before-after-hook/2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: false + /better-sqlite3/7.6.1: resolution: {integrity: sha512-kI2NV1qjKyO2I7iDKgrsbpYR7CxNVrObiGVxbrwYJRy6Sjn/4N6YwZmi0LP2kWZswSqeJlnnEThoYJ7eKCmqAg==} requiresBuild: true @@ -4896,6 +5113,14 @@ packages: engines: {node: '>=0.6.19'} dev: false + /btoa-lite/1.0.0: + resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} + dev: false + + /buffer-equal-constant-time/1.0.1: + resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} + dev: false + /buffer-from/1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -6574,6 +6799,12 @@ packages: safer-buffer: 2.1.2 dev: true + /ecdsa-sig-formatter/1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /ee-first/1.1.1: resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} @@ -7813,7 +8044,6 @@ packages: /fromentries/1.3.2: resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} - dev: true /fs-constants/1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -8907,6 +9137,11 @@ packages: dependencies: isobject: 3.0.1 + /is-plain-object/5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: false + /is-regex/1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -9187,6 +9422,22 @@ packages: graceful-fs: 4.2.10 dev: false + /jsonwebtoken/8.5.1: + resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==} + engines: {node: '>=4', npm: '>=1.4.28'} + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 5.7.1 + dev: false + /jsprim/1.4.2: resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} engines: {node: '>=0.6.0'} @@ -9267,6 +9518,21 @@ packages: object.assign: 4.1.2 dev: true + /jwa/1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws/3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + /killable/1.0.1: resolution: {integrity: sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==} dev: true @@ -9449,14 +9715,38 @@ packages: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: false + /lodash.includes/4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + dev: false + /lodash.isarguments/3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} dev: false + /lodash.isboolean/3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + dev: false + /lodash.isequal/4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} dev: false + /lodash.isinteger/4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + dev: false + + /lodash.isnumber/3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + dev: false + + /lodash.isplainobject/4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + + /lodash.isstring/4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: false + /lodash.memoize/4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} dev: false @@ -9465,6 +9755,10 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.once/4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: false + /lodash.pad/4.5.1: resolution: {integrity: sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg==} dev: false @@ -14553,6 +14847,17 @@ packages: unist-util-visit-parents: 5.1.0 dev: false + /universal-github-app-jwt/1.1.0: + resolution: {integrity: sha512-3b+ocAjjz4JTyqaOT+NNBd5BtTuvJTxWElIoeHSVelUV9J3Jp7avmQTdLKCaoqi/5Ox2o/q+VK19TJ233rVXVQ==} + dependencies: + '@types/jsonwebtoken': 8.5.9 + jsonwebtoken: 8.5.1 + dev: false + + /universal-user-agent/6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + dev: false + /universalify/0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'}